diff options
Diffstat (limited to 'cpukit')
96 files changed, 8993 insertions, 642 deletions
diff --git a/cpukit/include/rtems/libio_.h b/cpukit/include/rtems/libio_.h new file mode 100644 index 0000000000..bb6f81f35a --- /dev/null +++ b/cpukit/include/rtems/libio_.h @@ -0,0 +1,248 @@ +/* + * Libio Internal Information + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef __LIBIO__h +#define __LIBIO__h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems.h> +#include <rtems/assoc.h> /* assoc.h not included by rtems.h */ +#include <rtems/libio.h> + +#include <stdio.h> /* O_RDONLY, et.al. */ +#include <fcntl.h> /* O_RDONLY, et.al. */ +#include <assert.h> +#include <stdarg.h> + +#if ! defined(O_NDELAY) +# if defined(solaris2) +# define O_NDELAY O_NONBLOCK +# elif defined(RTEMS_NEWLIB) +# define O_NDELAY _FNBIO +# endif +#endif + +#include <errno.h> +#include <string.h> /* strcmp */ +#include <unistd.h> +#include <stdlib.h> /* calloc() */ + +#include "libio.h" /* libio.h not pulled in by rtems */ + + +/* + * Semaphore to protect the io table + */ + +#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O') +#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n) + +extern rtems_id rtems_libio_semaphore; + +/* + * File descriptor Table Information + */ + +extern unsigned32 rtems_libio_number_iops; +extern rtems_libio_t *rtems_libio_iops; +extern rtems_libio_t *rtems_libio_last_iop; + +/* + * External I/O Handlers Table + * + * Space for all possible handlers is preallocated + * to speed up dispatch to external handlers. + */ + +extern rtems_libio_handler_t rtems_libio_handlers[15]; + +/* + * Default mode for all files. + */ + +extern mode_t rtems_filesystem_umask; + +/* + * set_errno_and_return_minus_one + * + * Macro to ease common way to return an error. + */ + +#ifndef set_errno_and_return_minus_one +#define set_errno_and_return_minus_one( _error ) \ + do { errno = (_error); return -1; } while(0) +#endif + +/* + * rtems_libio_iop + * + * Macro to return the file descriptor pointer. + */ + +#define rtems_libio_iop(_fd) \ + ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \ + &rtems_libio_iops[_fd] : 0) + +/* + * rtems_libio_check_fd + * + * Macro to check if a file descriptor number is valid. + */ + +#define rtems_libio_check_fd(_fd) \ + do { \ + if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \ + errno = EBADF; \ + return -1; \ + } \ + } while (0) + +/* + * rtems_libio_check_fd + * + * Macro to check if a buffer pointer is valid. + */ + +#define rtems_libio_check_buffer(_buffer) \ + do { \ + if ((_buffer) == 0) { \ + errno = EINVAL; \ + return -1; \ + } \ + } while (0) + +/* + * rtems_libio_check_count + * + * Macro to check if a count or length is valid. + */ + +#define rtems_libio_check_count(_count) \ + do { \ + if ((_count) == 0) { \ + return 0; \ + } \ + } while (0) + +/* + * rtems_libio_check_permissions + * + * Macro to check if a file descriptor is open for this operation. + */ + +#define rtems_libio_check_permissions(_iop, _flag) \ + do { \ + if (((_iop)->flags & (_flag)) == 0) { \ + set_errno_and_return_minus_one( EINVAL ); \ + return -1; \ + } \ + } while (0) + +/* + * rtems_filesystem_is_separator + * + * Macro to determine if a character is a path name separator. + * + * NOTE: This macro handles MS-DOS and UNIX style names. + */ + +#define rtems_filesystem_is_separator( _ch ) \ + ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0')) + +/* + * rtems_filesystem_get_start_loc + * + * Macro to determine if path is absolute or relative. + */ + +#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \ + do { \ + if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \ + *(_loc) = rtems_filesystem_root; \ + *(_index) = 1; \ + } else { \ + *(_loc) = rtems_filesystem_current; \ + *(_index) = 0; \ + } \ + } while (0) + +#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \ + do { \ + if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \ + *(_loc) = rtems_filesystem_root; \ + *(_index) = 1; \ + } else { \ + *(_index) = 0; \ + } \ + } while (0) + + +/* + * External structures + */ + +extern rtems_filesystem_location_info_t rtems_filesystem_current; +extern rtems_filesystem_location_info_t rtems_filesystem_root; +extern nlink_t rtems_filesystem_link_counts; + + +/* + * File Descriptor Routine Prototypes + */ + +rtems_libio_t *rtems_libio_allocate(void); + +unsigned32 rtems_libio_fcntl_flags( + unsigned32 fcntl_flags +); + +void rtems_libio_free( + rtems_libio_t *iop +); + +int rtems_libio_is_open_files_in_fs( + rtems_filesystem_mount_table_entry_t *mt_entry +); + +int rtems_libio_is_file_open( + void *node_access +); + +/* + * File System Routine Prototypes + */ + +int rtems_filesystem_evaluate_path( + const char *pathname, + int flags, + rtems_filesystem_location_info_t *pathloc, + int follow_link +); + +void rtems_filesystem_initialize(); + +int init_fs_mount_table(); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ + + + diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index dcdda85aec..76a90954b0 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -1,11 +1,18 @@ /* - * General purpose communication channel for RTEMS to allow UNIX/POSIX - * system call behavior on top of RTEMS IO devices. + * System call and file system interface definition * - * TODO - * stat(2) - * unlink(2) - * rename(2) + * General purpose communication channel for RTEMS to allow UNIX/POSIX + * system call behavior under RTEMS. Initially this supported only + * IO to devices but has since been enhanced to support networking + * and support for mounted file systems. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. * * $Id$ */ @@ -15,36 +22,342 @@ #include <sys/stat.h> -typedef unsigned32 rtems_libio_offset_t; +/* + * Define data types which must be constructed using forward references. + */ + +typedef struct rtems_libio_tt rtems_libio_t; + +struct rtems_filesystem_location_info_tt; +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; + +/* + * Valid RTEMS file types. + */ +typedef enum { + RTEMS_FILESYSTEM_DIRECTORY, + RTEMS_FILESYSTEM_DEVICE, + RTEMS_FILESYSTEM_HARD_LINK, + RTEMS_FILESYSTEM_SYM_LINK, + RTEMS_FILESYSTEM_MEMORY_FILE +} rtems_filesystem_node_types_t; + +/* + * File Handler Operations Table + */ + +typedef int (*rtems_filesystem_open_t)( + rtems_libio_t *iop, + const char *pathname, + unsigned32 flag, + unsigned32 mode +); + +typedef int (*rtems_filesystem_close_t)( + rtems_libio_t *iop +); + +typedef int (*rtems_filesystem_read_t)( + rtems_libio_t *iop, + void *buffer, + unsigned32 count +); + +typedef int (*rtems_filesystem_write_t)( + rtems_libio_t *iop, + const void *buffer, + unsigned32 count +); + +typedef int (*rtems_filesystem_ioctl_t)( + rtems_libio_t *iop, + unsigned32 command, + void *buffer +); + +typedef int (*rtems_filesystem_lseek_t)( + rtems_libio_t *iop, + off_t length, + int whence +); + +typedef int (*rtems_filesystem_fstat_t)( + rtems_filesystem_location_info_t *loc, + struct stat *buf +); + +typedef int (*rtems_filesystem_fchmod_t)( + rtems_filesystem_location_info_t *loc, + mode_t mode +); + +typedef int (*rtems_filesystem_ftruncate_t)( + rtems_libio_t *iop, + off_t length +); + +typedef int (*rtems_filesystem_fpathconf_t)( + rtems_libio_t *iop, + int name +); + +typedef int (*rtems_filesystem_fsync_t)( + rtems_libio_t *iop +); + +typedef int (*rtems_filesystem_fdatasync_t)( + rtems_libio_t *iop +); + +typedef struct { + rtems_filesystem_open_t open; + rtems_filesystem_close_t close; + rtems_filesystem_read_t read; + rtems_filesystem_write_t write; + rtems_filesystem_ioctl_t ioctl; + rtems_filesystem_lseek_t lseek; + rtems_filesystem_fstat_t fstat; + rtems_filesystem_fchmod_t fchmod; + rtems_filesystem_ftruncate_t ftruncate; + rtems_filesystem_fpathconf_t fpathconf; + rtems_filesystem_fsync_t fsync; + rtems_filesystem_fdatasync_t fdatasync; +} rtems_filesystem_file_handlers_r; + +/* + * File System Operations Table + */ + +/* + * XXX + * This routine does not allocate any space and rtems_filesystem_freenode_t + * is not called by the generic after calling this routine. + * ie. node_access does not have to contain valid data when the + * routine returns. + */ + +typedef int (*rtems_filesystem_mknod_t)( + const char *path, /* IN */ + mode_t mode, /* IN */ + dev_t dev, /* IN */ + rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +); + +/* + * rtems_filesystem_freenode_t must be called by the generic after + * calling this routine + */ + +typedef int (*rtems_filesystem_evalpath_t)( + const char *pathname, /* IN */ + int flags, /* IN */ + rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +); + +typedef int (*rtems_filesystem_evalmake_t)( + const char *path, /* IN */ + rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ + const char **name /* OUT */ +); + +typedef int (*rtems_filesystem_link_t)( + rtems_filesystem_location_info_t *to_loc, /* IN */ + rtems_filesystem_location_info_t *parent_loc, /* IN */ + const char *name /* IN */ +); + +typedef int (*rtems_filesystem_unlink_t)( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +typedef int (*rtems_filesystem_chown_t)( + rtems_filesystem_location_info_t *pathloc, /* IN */ + uid_t owner, /* IN */ + gid_t group /* IN */ +); + +typedef int (*rtems_filesystem_freenode_t)( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +typedef int (*rtems_filesystem_rmnod_t)( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +typedef int (* rtems_filesystem_mount_t ) ( + rtems_filesystem_mount_table_entry_t *mt_entry /* in */ +); + +typedef int (* rtems_filesystem_fsmount_me_t )( + rtems_filesystem_mount_table_entry_t *mt_entry +); + +typedef int (* rtems_filesystem_unmount_t ) ( + rtems_filesystem_mount_table_entry_t *mt_entry /* in */ +); + +typedef int (* rtems_filesystem_fsunmount_me_t ) ( + rtems_filesystem_mount_table_entry_t *mt_entry /* in */ +); + +typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) ( + rtems_filesystem_location_info_t *pathloc /* in */ +); + +typedef int (* rtems_filesystem_utime_t)( + rtems_filesystem_location_info_t *pathloc, /* IN */ + time_t actime, /* IN */ + time_t modtime /* IN */ +); + +typedef int (*rtems_filesystem_evaluate_link_t)( + rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ + int flags /* IN */ +); + +typedef int (*rtems_filesystem_symlink_t)( + rtems_filesystem_location_info_t *loc, /* IN */ + const char *link_name, /* IN */ + const char *node_name +); + +typedef int (*rtems_filesystem_readlink_t)( + rtems_filesystem_location_info_t *loc, /* IN */ + char *buf, /* OUT */ + size_t bufsize +); + +/* + * operations table that must be defined for every file system. + */ + +/* + * File system types + */ +typedef struct { + rtems_filesystem_evalpath_t evalpath; + rtems_filesystem_evalmake_t evalformake; + rtems_filesystem_link_t link; + rtems_filesystem_unlink_t unlink; + rtems_filesystem_node_type_t node_type; + rtems_filesystem_mknod_t mknod; + rtems_filesystem_rmnod_t rmnod; + rtems_filesystem_chown_t chown; + rtems_filesystem_freenode_t freenod; + rtems_filesystem_mount_t mount; + rtems_filesystem_fsmount_me_t fsmount_me; + rtems_filesystem_unmount_t unmount; + rtems_filesystem_fsunmount_me_t fsunmount_me; + rtems_filesystem_utime_t utime; + rtems_filesystem_evaluate_link_t eval_link; + rtems_filesystem_symlink_t symlink; + rtems_filesystem_readlink_t readlink; +} rtems_filesystem_operations_table; + +#define IMFS_FILE_SYSTEM IMFS_ops +extern rtems_filesystem_operations_table IMFS_ops; + /* - * An open file data structure, indexed by 'fd' - * TODO: - * should really have a separate per/file data structure that this - * points to (eg: size, offset, driver, pathname should be in that) + * Structure used to determine a location/filesystem in the tree. + */ + +struct rtems_filesystem_location_info_tt +{ + void *node_access; + rtems_filesystem_file_handlers_r *handlers; + rtems_filesystem_operations_table *ops; + rtems_filesystem_mount_table_entry_t *mt_entry; +}; + +/* + * Structure used to contain file system specific information which + * is required to support fpathconf(). */ typedef struct { - rtems_driver_name_t *driver; - rtems_libio_offset_t size; /* size of file */ - rtems_libio_offset_t offset; /* current offset into the file */ - unsigned32 flags; - char *pathname; /* opened pathname */ - Objects_Id sem; - unsigned32 data0; /* private to "driver" */ - void *data1; /* ... */ -} rtems_libio_t; + int link_max; + int max_canon; + int max_input; + int name_max; + int path_max; + int pipe_buf; + int posix_async_io; + int posix_chown_restrictions; + int posix_no_trunc; + int posix_prio_io; + int posix_sync_io; + int posix_vdisable; +} rtems_filesystem_limits_and_options_t; + +/* + * Structure for a mount table entry. + */ + +struct rtems_filesystem_mount_table_entry_tt{ + Chain_Node Node; + rtems_filesystem_location_info_t mt_point_node; + rtems_filesystem_location_info_t mt_fs_root; + int options; + void *fs_info; + + rtems_filesystem_limits_and_options_t pathconf_limits_and_options; + /* + * When someone adds a mounted filesystem on a real device, + * this will need to be used. + * + * The best option long term for this is probably an open file descriptor. + */ + char *dev; +}; /* - * param block for read/write - * Note: it must include 'offset' instead of using iop's offset since - * we can have multiple outstanding i/o's on a device. + * Valid RTEMS file systems options + */ + +typedef enum +{ + RTEMS_FILESYSTEM_READ_ONLY, + RTEMS_FILESYSTEM_READ_WRITE_ONLY, + RTEMS_FILESYSTEM_BAD_OPTIONS +} rtems_filesystem_options_t; + + +/* + * An open file data structure, indexed by 'fd' + * TODO: + * should really have a separate per/file data structure that this + * points to (eg: size, offset, driver, pathname should be in that) + */ + +struct rtems_libio_tt { + rtems_driver_name_t *driver; + off_t size; /* size of file */ + off_t offset; /* current offset into file */ + unsigned32 flags; + rtems_filesystem_location_info_t pathinfo; + Objects_Id sem; + unsigned32 data0; /* private to "driver" */ + void *data1; /* ... */ + void *file_info; /* used by file handlers */ + rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */ +}; + +/* + * param block for read/write + * Note: it must include 'offset' instead of using iop's offset since + * we can have multiple outstanding i/o's on a device. */ typedef struct { rtems_libio_t *iop; - rtems_libio_offset_t offset; + off_t offset; unsigned8 *buffer; unsigned32 count; unsigned32 flags; @@ -52,7 +365,7 @@ typedef struct { } rtems_libio_rw_args_t; /* - * param block for open/close + * param block for open/close */ typedef struct { @@ -62,7 +375,7 @@ typedef struct { } rtems_libio_open_close_args_t; /* - * param block for ioctl + * param block for ioctl */ typedef struct { @@ -72,9 +385,8 @@ typedef struct { unsigned32 ioctl_return; } rtems_libio_ioctl_args_t; - /* - * Values for 'flag' + * Values for 'flag' */ #define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */ @@ -84,33 +396,72 @@ typedef struct { #define LIBIO_FLAGS_OPEN 0x0100 /* device is open */ #define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */ #define LIBIO_FLAGS_CREATE 0x0400 /* create file */ +#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */ #define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE) -void rtems_libio_init(void); -int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode); -int __rtems_close(int fd); -int __rtems_read(int fd, void *buffer, unsigned32 count); -int __rtems_write(int fd, const void *buffer, unsigned32 count); -int __rtems_ioctl(int fd, unsigned32 command, void *buffer); -int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence); -int __rtems_fstat(int _fd, struct stat* _sbuf); +void rtems_libio_init(void); /* - * External I/O handlers + * External I/O handlers */ + +typedef int (*rtems_libio_open_t)( + const char *pathname, + unsigned32 flag, + unsigned32 mode +); + +typedef int (*rtems_libio_close_t)( + int fd +); + +typedef int (*rtems_libio_read_t)( + int fd, + void *buffer, + unsigned32 count +); + +typedef int (*rtems_libio_write_t)( + int fd, + const void *buffer, + unsigned32 count +); + +typedef int (*rtems_libio_ioctl_t)( + int fd, + unsigned32 command, + void *buffer +); + +typedef int (*rtems_libio_lseek_t)( + int fd, + off_t offset, + int whence +); + typedef struct { - int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode); - int (*close)(int fd); - int (*read)(int fd, void *buffer, unsigned32 count); - int (*write)(int fd, const void *buffer, unsigned32 count); - int (*ioctl)(int fd, unsigned32 command, void *buffer); - int (*lseek)(int fd, rtems_libio_offset_t offset, int whence); + rtems_libio_open_t open; + rtems_libio_close_t close; + rtems_libio_read_t read; + rtems_libio_write_t write; + rtems_libio_ioctl_t ioctl; + rtems_libio_lseek_t lseek; } rtems_libio_handler_t; -void rtems_register_libio_handler(int handler_flag, - const rtems_libio_handler_t *handler); +/* + * Register a set of external handlers + */ + +void rtems_register_libio_handler( + int handler_flag, + const rtems_libio_handler_t *handler +); + +/* + * Macros to assist in management of external IO handlers. + */ #define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000 #define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000 @@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag, #define RTEMS_IO_TCDRAIN 3 /* + * The following macros are used to build up the permissions sets + * used to check permissions. These are similar in style to the + * mode_t bits and should stay compatible with them. + */ + +#define RTEMS_LIBIO_PERMS_READ S_IROTH +#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH +#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH) +#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH +#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC +#define RTEMS_LIBIO_PERMS_RWX S_IRWXO + +/* + * Macros + */ + +#define rtems_filesystem_make_dev_t( _major, _minor ) \ + ((((dev_t)(_major)) << 32) | (dev_t)(_minor)) + +#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \ + do { \ + (_major) = (rtems_device_major_number) ((_dev) >> 32); \ + (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \ + } while(0) + +/* + * Verifies that the permission flag is valid. + */ +#define rtems_libio_is_valid_perms( _perm ) \ + (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm )) + + +/* + * Prototypes for filesystem + */ + +void rtems_filesystem_initialize( void ); + + +/* * Callbacks from TERMIOS routines to device-dependent code */ + #include <termios.h> + typedef struct rtems_termios_callbacks { - int (*firstOpen)(int major, int minor, void *arg); - int (*lastClose)(int major, int minor, void *arg); - int (*pollRead)(int minor); - int (*write)(int minor, const char *buf, int len); - int (*setAttributes)(int minor, const struct termios *t); - int (*stopRemoteTx)(int minor); - int (*startRemoteTx)(int minor); - int outputUsesInterrupts; + int (*firstOpen)(int major, int minor, void *arg); + int (*lastClose)(int major, int minor, void *arg); + int (*pollRead)(int minor); + int (*write)(int minor, const char *buf, int len); + int (*setAttributes)(int minor, const struct termios *t); + int (*stopRemoteTx)(int minor); + int (*startRemoteTx)(int minor); + int outputUsesInterrupts; } rtems_termios_callbacks; /* - * Device-independent TERMIOS routines + * Device-independent TERMIOS routines */ + void rtems_termios_initialize (void); + rtems_status_code rtems_termios_open ( rtems_device_major_number major, rtems_device_minor_number minor, void *arg, const rtems_termios_callbacks *callbacks - ); -rtems_status_code rtems_termios_close (void *arg); -rtems_status_code rtems_termios_read (void *arg); -rtems_status_code rtems_termios_write (void *arg); -rtems_status_code rtems_termios_ioctl (void *arg); -int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len); -int rtems_termios_dequeue_characters (void *ttyp, int len); +); + +rtems_status_code rtems_termios_close( + void *arg +); + +rtems_status_code rtems_termios_read( + void *arg +); + +rtems_status_code rtems_termios_write( + void *arg +); + +rtems_status_code rtems_termios_ioctl( + void *arg +); + +int rtems_termios_enqueue_raw_characters( + void *ttyp, + char *buf, + int len +); + +int rtems_termios_dequeue_characters( + void *ttyp, + int len +); + void rtems_termios_reserve_resources( rtems_configuration_table *configuration, rtems_unsigned32 number_of_devices ); +int unmount( + const char *mount_path +); + +int mount( + rtems_filesystem_mount_table_entry_t **mt_entry, + rtems_filesystem_operations_table *fs_ops, + char *fsoptions, + char *device, + char *mount_point +); + #endif /* _RTEMS_LIBIO_H */ diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h new file mode 100644 index 0000000000..bb6f81f35a --- /dev/null +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -0,0 +1,248 @@ +/* + * Libio Internal Information + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef __LIBIO__h +#define __LIBIO__h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems.h> +#include <rtems/assoc.h> /* assoc.h not included by rtems.h */ +#include <rtems/libio.h> + +#include <stdio.h> /* O_RDONLY, et.al. */ +#include <fcntl.h> /* O_RDONLY, et.al. */ +#include <assert.h> +#include <stdarg.h> + +#if ! defined(O_NDELAY) +# if defined(solaris2) +# define O_NDELAY O_NONBLOCK +# elif defined(RTEMS_NEWLIB) +# define O_NDELAY _FNBIO +# endif +#endif + +#include <errno.h> +#include <string.h> /* strcmp */ +#include <unistd.h> +#include <stdlib.h> /* calloc() */ + +#include "libio.h" /* libio.h not pulled in by rtems */ + + +/* + * Semaphore to protect the io table + */ + +#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O') +#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n) + +extern rtems_id rtems_libio_semaphore; + +/* + * File descriptor Table Information + */ + +extern unsigned32 rtems_libio_number_iops; +extern rtems_libio_t *rtems_libio_iops; +extern rtems_libio_t *rtems_libio_last_iop; + +/* + * External I/O Handlers Table + * + * Space for all possible handlers is preallocated + * to speed up dispatch to external handlers. + */ + +extern rtems_libio_handler_t rtems_libio_handlers[15]; + +/* + * Default mode for all files. + */ + +extern mode_t rtems_filesystem_umask; + +/* + * set_errno_and_return_minus_one + * + * Macro to ease common way to return an error. + */ + +#ifndef set_errno_and_return_minus_one +#define set_errno_and_return_minus_one( _error ) \ + do { errno = (_error); return -1; } while(0) +#endif + +/* + * rtems_libio_iop + * + * Macro to return the file descriptor pointer. + */ + +#define rtems_libio_iop(_fd) \ + ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \ + &rtems_libio_iops[_fd] : 0) + +/* + * rtems_libio_check_fd + * + * Macro to check if a file descriptor number is valid. + */ + +#define rtems_libio_check_fd(_fd) \ + do { \ + if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \ + errno = EBADF; \ + return -1; \ + } \ + } while (0) + +/* + * rtems_libio_check_fd + * + * Macro to check if a buffer pointer is valid. + */ + +#define rtems_libio_check_buffer(_buffer) \ + do { \ + if ((_buffer) == 0) { \ + errno = EINVAL; \ + return -1; \ + } \ + } while (0) + +/* + * rtems_libio_check_count + * + * Macro to check if a count or length is valid. + */ + +#define rtems_libio_check_count(_count) \ + do { \ + if ((_count) == 0) { \ + return 0; \ + } \ + } while (0) + +/* + * rtems_libio_check_permissions + * + * Macro to check if a file descriptor is open for this operation. + */ + +#define rtems_libio_check_permissions(_iop, _flag) \ + do { \ + if (((_iop)->flags & (_flag)) == 0) { \ + set_errno_and_return_minus_one( EINVAL ); \ + return -1; \ + } \ + } while (0) + +/* + * rtems_filesystem_is_separator + * + * Macro to determine if a character is a path name separator. + * + * NOTE: This macro handles MS-DOS and UNIX style names. + */ + +#define rtems_filesystem_is_separator( _ch ) \ + ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0')) + +/* + * rtems_filesystem_get_start_loc + * + * Macro to determine if path is absolute or relative. + */ + +#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \ + do { \ + if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \ + *(_loc) = rtems_filesystem_root; \ + *(_index) = 1; \ + } else { \ + *(_loc) = rtems_filesystem_current; \ + *(_index) = 0; \ + } \ + } while (0) + +#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \ + do { \ + if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \ + *(_loc) = rtems_filesystem_root; \ + *(_index) = 1; \ + } else { \ + *(_index) = 0; \ + } \ + } while (0) + + +/* + * External structures + */ + +extern rtems_filesystem_location_info_t rtems_filesystem_current; +extern rtems_filesystem_location_info_t rtems_filesystem_root; +extern nlink_t rtems_filesystem_link_counts; + + +/* + * File Descriptor Routine Prototypes + */ + +rtems_libio_t *rtems_libio_allocate(void); + +unsigned32 rtems_libio_fcntl_flags( + unsigned32 fcntl_flags +); + +void rtems_libio_free( + rtems_libio_t *iop +); + +int rtems_libio_is_open_files_in_fs( + rtems_filesystem_mount_table_entry_t *mt_entry +); + +int rtems_libio_is_file_open( + void *node_access +); + +/* + * File System Routine Prototypes + */ + +int rtems_filesystem_evaluate_path( + const char *pathname, + int flags, + rtems_filesystem_location_info_t *pathloc, + int follow_link +); + +void rtems_filesystem_initialize(); + +int init_fs_mount_table(); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ + + + diff --git a/cpukit/libcsupport/src/CASES b/cpukit/libcsupport/src/CASES new file mode 100644 index 0000000000..4578ae5009 --- /dev/null +++ b/cpukit/libcsupport/src/CASES @@ -0,0 +1,23 @@ +# +# $Id$ +# + +This is a list of cases to consider when implementing a file system: + + ++ Given a tree of this form: + + a ----- b + / + c + + Where a and b are directories and c is a link to directory b. Consider + this sequence: + + - rmdir a/b + - mknod c/b/x + - unlink c + + + + diff --git a/cpukit/libcsupport/src/TODO b/cpukit/libcsupport/src/TODO new file mode 100644 index 0000000000..9d894688d9 --- /dev/null +++ b/cpukit/libcsupport/src/TODO @@ -0,0 +1,11 @@ +# +# $Id$ +# + ++ newlib 1.8.0 has the wrong prototype for at least read() and write(). + ++ There should be a "eat it" stub for all system calls which are + available to make filling out an operations table easier. + See device_lseek() for an example of where this would be nice. + ++ Fix strerror() so it prints all error numbers. diff --git a/cpukit/libcsupport/src/__brk.c b/cpukit/libcsupport/src/__brk.c index 4dab22c729..24efa93adb 100644 --- a/cpukit/libcsupport/src/__brk.c +++ b/cpukit/libcsupport/src/__brk.c @@ -1,10 +1,7 @@ -#if !defined(RTEMS_UNIX) - /* - * RTEMS "Broken" __brk/__sbrk Implementation - * - * NOTE: sbrk is BSP provided. + * RTEMS "Broken" __brk Implementation * + * NOTE: sbrk() is provided by each BSP. * * COPYRIGHT (c) 1989-1998. * On-Line Applications Research Corporation (OAR). @@ -18,27 +15,15 @@ */ #include <rtems.h> +#if !defined(RTEMS_UNIX) -#include <signal.h> #include <errno.h> -#include <sys/types.h> -#ifdef RTEMS_NEWLIB -#include <reent.h> -#endif -#include <unistd.h> - -/* we use RTEMS for memory management. We don't need sbrk */ -void * __sbrk(int incr) -{ - errno = EINVAL; - return (void *)0; -} - -int __brk( const void *endds ) +int __brk( + const void *endds +) { errno = EINVAL; return -1; } - #endif diff --git a/cpukit/libcsupport/src/__gettod.c b/cpukit/libcsupport/src/__gettod.c index dc83c47ce4..16857da870 100644 --- a/cpukit/libcsupport/src/__gettod.c +++ b/cpukit/libcsupport/src/__gettod.c @@ -1,11 +1,5 @@ -#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ - -#include <rtems.h> - -#if !defined(RTEMS_UNIX) /* - * RTEMS gettimeofday Implementation - * + * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib * * COPYRIGHT (c) 1989-1998. * On-Line Applications Research Corporation (OAR). @@ -18,6 +12,11 @@ * $Id$ */ +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ + +#include <rtems.h> + +#if !defined(RTEMS_UNIX) #ifdef RTEMS_NEWLIB #include <sys/reent.h> #endif @@ -61,7 +60,7 @@ int gettimeofday( * * NOTE: XXX this routine should really be in the executive proper. */ - + rtems_interrupt_disable(level); seconds = _TOD_Seconds_since_epoch; microseconds = _TOD_Current.ticks; @@ -86,7 +85,7 @@ int gettimeofday( return 0; } -#if defined(RTEMS_NEWLIB) +#if defined(RTEMS_NEWLIB) /* * "Reentrant" version @@ -102,7 +101,7 @@ int _gettimeofday_r( } /* - * "System call" version + * "System call" version */ int _gettimeofday( diff --git a/cpukit/libcsupport/src/__sbrk.c b/cpukit/libcsupport/src/__sbrk.c new file mode 100644 index 0000000000..b1d31467fd --- /dev/null +++ b/cpukit/libcsupport/src/__sbrk.c @@ -0,0 +1,29 @@ +/* + * RTEMS "Broken" __sbrk Implementation + * + * NOTE: sbrk is provided by the BSP. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if !defined(RTEMS_UNIX) + +#include <errno.h> + +void * __sbrk( + int incr +) +{ + errno = EINVAL; + return (void *)0; +} +#endif diff --git a/cpukit/libcsupport/src/__times.c b/cpukit/libcsupport/src/__times.c index 635bf8e062..5f7525ec5f 100644 --- a/cpukit/libcsupport/src/__times.c +++ b/cpukit/libcsupport/src/__times.c @@ -1,6 +1,5 @@ /* - * RTEMS _times Implementation - * + * times() - POSIX 1003.1b 4.5.2 - Get Process Times * * COPYRIGHT (c) 1989-1998. * On-Line Applications Research Corporation (OAR). @@ -25,8 +24,8 @@ clock_t _times( struct tms *ptms ) { - rtems_status_code status; - rtems_interval ticks_since_boot; + rtems_status_code status; + rtems_interval ticks; if ( !ptms ) { errno = EFAULT; @@ -34,21 +33,19 @@ clock_t _times( } /* "POSIX" does not seem to allow for not having a TOD */ - status = rtems_clock_get( - RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, - &ticks_since_boot - ); + status = rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks ); if ( status != RTEMS_SUCCESSFUL ) { assert( 0 ); return -1; } /* - * RTEMS has no notion of system versus user time and does - * not (as of 3.2.0) keep track of CPU usage on a per task basis. + * RTEMS has no notion of system versus user time and although + * a way to keep track of per task CPU usage was added since + * 3.6.0, this routine does not utilize it yet. */ - ptms->tms_utime = ticks_since_boot; + ptms->tms_utime = ticks; ptms->tms_stime = 0; ptms->tms_cutime = 0; ptms->tms_cstime = 0; @@ -56,6 +53,12 @@ clock_t _times( return 0; } +/* + * times() + * + * times() system call wrapper for _times() above. + */ + clock_t times( struct tms *ptms ) @@ -63,12 +66,21 @@ clock_t times( return _times( ptms ); } +/* + * _times_r + * + * This is the Newlib dependent reentrant version of times(). + */ + #if defined(RTEMS_NEWLIB) + +#include <reent.h> + clock_t _times_r( struct _reent *ptr, struct tms *ptms ) { - return _times(ptms); + return _times( ptms ); } #endif diff --git a/cpukit/libcsupport/src/access.c b/cpukit/libcsupport/src/access.c new file mode 100644 index 0000000000..a8be44a9a3 --- /dev/null +++ b/cpukit/libcsupport/src/access.c @@ -0,0 +1,46 @@ +/* + * access() - POSIX 1003.1b 5.6.3 - File Accessibility + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> + +int access( + const char *path, + int amode +) +{ + struct stat statbuf; + + if ( stat(path, &statbuf) ) + return -1; + + if ( amode & R_OK ) { + if (!( statbuf.st_mode & S_IREAD )) + return -1; + } + + if ( amode & W_OK ) { + if ( !( statbuf.st_mode & S_IWRITE ) ) + return -1; + } + + if ( amode & X_OK ) { + if ( !( statbuf.st_mode & S_IEXEC ) ) + return -1; + } + + return 0; +} + diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c new file mode 100644 index 0000000000..c8c23e5b43 --- /dev/null +++ b/cpukit/libcsupport/src/base_fs.c @@ -0,0 +1,81 @@ +/* + * Base file system initialization + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <rtems/libio.h> +#include "imfs.h" +#include "libio_.h" + +/* + * Global information for the base file system. + */ + +rtems_filesystem_location_info_t rtems_filesystem_current; +rtems_filesystem_location_info_t rtems_filesystem_root; +nlink_t rtems_filesystem_link_counts; + +/* + * Default mode for created files. + */ + +mode_t rtems_filesystem_umask; + +/* + * rtems_filesystem_initialize + * + * Initialize the foundation of the file system with one instantiation + * of the IMFS with a single "/dev" directory in it. + */ + +void rtems_filesystem_initialize( void ) +{ + int status; + rtems_filesystem_mount_table_entry_t *first_entry; + + /* + * Set the default umask to "022". + */ + + rtems_filesystem_umask = S_IWOTH | S_IROTH; + + init_fs_mount_table(); + + status = mount( + &first_entry, + &IMFS_ops, + "RW", + NULL, + NULL ); + if( status == -1 ){ + rtems_fatal_error_occurred( 0xABCD0002 ); + } + + rtems_filesystem_link_counts = 0; + + rtems_filesystem_root = first_entry->mt_fs_root; + + rtems_filesystem_current = rtems_filesystem_root; + + /* + * Traditionally RTEMS devices are under "/dev" so install this directory. + * + * If the mkdir() fails, we can't print anything so just fatal error. + * + * NOTE: UNIX root is 755 and owned by root/root (0/0). + */ + + status = mkdir( "/dev", S_IRWXU | S_IRWXG | S_IRWXO ); + if ( status != 0 ) + rtems_fatal_error_occurred( 0xABCD0003 ); +} diff --git a/cpukit/libcsupport/src/cfgetispeed.c b/cpukit/libcsupport/src/cfgetispeed.c new file mode 100644 index 0000000000..61d97cb2f1 --- /dev/null +++ b/cpukit/libcsupport/src/cfgetispeed.c @@ -0,0 +1,29 @@ +/* + * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if defined(RTEMS_NEWLIB) + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <termios.h> + +speed_t cfgetispeed( + const struct termios *tp +) +{ + return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD; +} +#endif diff --git a/cpukit/libcsupport/src/cfgetospeed.c b/cpukit/libcsupport/src/cfgetospeed.c new file mode 100644 index 0000000000..8815d436e9 --- /dev/null +++ b/cpukit/libcsupport/src/cfgetospeed.c @@ -0,0 +1,29 @@ +/* + * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if defined(RTEMS_NEWLIB) + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <termios.h> + +speed_t cfgetospeed( + const struct termios *tp +) +{ + return tp->c_cflag & CBAUD; +} +#endif diff --git a/cpukit/libcsupport/src/cfsetispeed.c b/cpukit/libcsupport/src/cfsetispeed.c new file mode 100644 index 0000000000..37d3cd0584 --- /dev/null +++ b/cpukit/libcsupport/src/cfsetispeed.c @@ -0,0 +1,36 @@ +/* + * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if defined(RTEMS_NEWLIB) + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <termios.h> + +#include "libio_.h" + +int cfsetispeed( + struct termios *tp, + speed_t speed +) +{ + if ( speed & ~CBAUD ) + set_errno_and_return_minus_one( EINVAL ); + + tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD)); + return 0; +} +#endif diff --git a/cpukit/libcsupport/src/cfsetospeed.c b/cpukit/libcsupport/src/cfsetospeed.c new file mode 100644 index 0000000000..f01237103b --- /dev/null +++ b/cpukit/libcsupport/src/cfsetospeed.c @@ -0,0 +1,36 @@ +/* + * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if defined(RTEMS_NEWLIB) + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <termios.h> + +#include "libio_.h" + +int cfsetospeed( + struct termios *tp, + speed_t speed +) +{ + if ( speed & ~CBAUD ) + set_errno_and_return_minus_one( EINVAL ); + + tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed; + return 0; +} +#endif diff --git a/cpukit/libcsupport/src/chdir.c b/cpukit/libcsupport/src/chdir.c new file mode 100644 index 0000000000..4acbc8cfe0 --- /dev/null +++ b/cpukit/libcsupport/src/chdir.c @@ -0,0 +1,50 @@ +/* + * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> + +#include <unistd.h> +#include <errno.h> + +#include "libio_.h" + +int chdir( + const char *pathname +) +{ + rtems_filesystem_location_info_t loc; + int result; + + /* + * Get the node where we wish to go. + */ + + result = rtems_filesystem_evaluate_path( pathname, 0, &loc, TRUE ); + if ( result != 0 ) + return -1; + + /* + * Verify you can change directory into this node. + */ + + if ( !loc.ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + rtems_filesystem_current = loc; + + return 0; +} diff --git a/cpukit/libcsupport/src/chmod.c b/cpukit/libcsupport/src/chmod.c new file mode 100644 index 0000000000..fa57d50691 --- /dev/null +++ b/cpukit/libcsupport/src/chmod.c @@ -0,0 +1,40 @@ +/* + * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <rtems/libio.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include "libio_.h" + +int chmod( + const char *path, + mode_t mode +) +{ + int status; + rtems_filesystem_location_info_t loc; + + status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE ); + if ( status != 0 ) + return -1; + + if ( !loc.handlers->fchmod ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*loc.handlers->fchmod)( &loc, mode ); +} diff --git a/cpukit/libcsupport/src/chown.c b/cpukit/libcsupport/src/chown.c new file mode 100644 index 0000000000..189096dcd1 --- /dev/null +++ b/cpukit/libcsupport/src/chown.c @@ -0,0 +1,38 @@ +/* + * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/stat.h> +#include <errno.h> + +#include <rtems.h> +#include <rtems/libio.h> + +#include "libio_.h" + +int chown( + const char *path, + uid_t owner, + gid_t group +) +{ + rtems_filesystem_location_info_t temp_loc; + + if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) ) + return -1; + + if ( !temp_loc.ops->chown ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*temp_loc.ops->chown)( &temp_loc, owner, group ); +} diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c new file mode 100644 index 0000000000..94ddb45c90 --- /dev/null +++ b/cpukit/libcsupport/src/close.c @@ -0,0 +1,70 @@ +/* + * close() - POSIX 1003.1b 6.3.1 - Close a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + +int close( + int fd +) +{ + rtems_libio_t *iop; + rtems_status_code rc; + int status; + + if ( rtems_file_descriptor_type( fd ) ) { + int (*fp)(int fd); + + fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].close; + if ( fp == NULL ) + set_errno_and_return_minus_one( EBADF ); + status = (*fp)( fd ); + return status; + } + iop = rtems_libio_iop(fd); + rtems_libio_check_fd(fd); + + if ( !iop->handlers ) + set_errno_and_return_minus_one( EBADF ); + + if ( !iop->handlers->close ) + set_errno_and_return_minus_one( ENOTSUP ); + + rc = (*iop->handlers->close)( iop ); + + rtems_libio_free( iop ); + + if (rc != RTEMS_SUCCESSFUL) + set_errno_and_return_minus_one( rc ); + + return rc; +} + +/* + * _close_r + * + * This is the Newlib dependent reentrant version of close(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _close_r( + struct _reent *ptr, + int fd +) +{ + return close( fd ); +} +#endif diff --git a/cpukit/libcsupport/src/closedir.c b/cpukit/libcsupport/src/closedir.c index 5edb3499e6..4d948ec95b 100644 --- a/cpukit/libcsupport/src/closedir.c +++ b/cpukit/libcsupport/src/closedir.c @@ -1,9 +1,44 @@ /* * closedir() - POSIX 1003.1b - XXX * - * $Id$ + * This was copied from Newlib 1.8.0. + * + * + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91"; +#endif /* LIBC_SCCS and not lint */ #include <sys/types.h> #include <dirent.h> @@ -11,10 +46,25 @@ #include <unistd.h> #include <errno.h> -int closedir( - register DIR *dirp -) + +#include "libio_.h" + +/* + * close a directory. + */ +int +closedir(dirp) + register DIR *dirp; { - errno = ENOSYS; - return -1; + int fd; + + if ( !dirp ) + set_errno_and_return_minus_one( EBADF ); + + fd = dirp->dd_fd; + dirp->dd_fd = -1; + dirp->dd_loc = 0; + (void)free((void *)dirp->dd_buf); + (void)free((void *)dirp); + return(close(fd)); } diff --git a/cpukit/libcsupport/src/dup.c b/cpukit/libcsupport/src/dup.c new file mode 100644 index 0000000000..c17db588a7 --- /dev/null +++ b/cpukit/libcsupport/src/dup.c @@ -0,0 +1,23 @@ +/* + * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <fcntl.h> + +int dup( + int fildes +) +{ + return fcntl( fildes, F_DUPFD, 0 ); +} diff --git a/cpukit/libcsupport/src/dup2.c b/cpukit/libcsupport/src/dup2.c new file mode 100644 index 0000000000..5653425708 --- /dev/null +++ b/cpukit/libcsupport/src/dup2.c @@ -0,0 +1,49 @@ +/* + * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <fcntl.h> + +#include "libio_.h" + +int dup2( + int fildes, + int fildes2 +) +{ + int status; + struct stat buf; + + /* + * If fildes is not valid, then fildes2 should not be closed. + */ + + status = fstat( fildes, &buf ); + if ( status == -1 ) + return -1; + + /* + * If fildes2 is not valid, then we should not do anything either. + */ + + status = fstat( fildes2, &buf ); + if ( status == -1 ) + return -1; + + /* + * This fcntl handles everything else. + */ + + return fcntl( fildes, F_DUPFD, fildes2 ); +} diff --git a/cpukit/libcsupport/src/eval.c b/cpukit/libcsupport/src/eval.c new file mode 100644 index 0000000000..bf7dd1c126 --- /dev/null +++ b/cpukit/libcsupport/src/eval.c @@ -0,0 +1,74 @@ +/* + * rtems_filesystem_evaluate_path() + * + * Routine to seed the evaluate path routine. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include "libio_.h" + +int rtems_filesystem_evaluate_path( + const char *pathname, + int flags, + rtems_filesystem_location_info_t *pathloc, + int follow_link +) +{ + int i; + int result; + rtems_filesystem_node_types_t type; + + /* + * Verify Input parameters. + */ + + if ( !pathname ) + set_errno_and_return_minus_one( EFAULT ); + + if ( !pathloc ) + set_errno_and_return_minus_one( EIO ); /* should never happen */ + + /* + * Evaluate the path using the optable evalpath. + */ + + rtems_filesystem_get_start_loc( pathname, &i, pathloc ); + + result = (*pathloc->ops->evalpath)( &pathname[i], flags, pathloc ); + + /* + * Get the Node type and determine if you need to follow the link or + * not. + */ + + if ( follow_link ) { + + if ( !pathloc->ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + type = (*pathloc->ops->node_type)( pathloc ); + + if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) || + ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) { + + if ( !pathloc->ops->eval_link ) + set_errno_and_return_minus_one( ENOTSUP ); + + result = (*pathloc->ops->eval_link)( pathloc, flags ); + + } + } + + return result; +} + diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c new file mode 100644 index 0000000000..a3ca4507ab --- /dev/null +++ b/cpukit/libcsupport/src/fchmod.c @@ -0,0 +1,50 @@ +/* + * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <sys/stat.h> +#include <errno.h> + +#include <rtems.h> +#include <rtems/libio.h> +#include "libio_.h" + +int fchmod( + int fd, + mode_t mode +) +{ + rtems_libio_t *iop; + + /* + * If this is not a file system based entity, it is an error. + */ + + if ( rtems_file_descriptor_type( fd ) ) + set_errno_and_return_minus_one( EBADF ); + + /* + * Now process the fchmod(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + + if ( !iop->handlers->fchmod ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->pathinfo.handlers->fchmod)( &iop->pathinfo, mode ); +} + diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c new file mode 100644 index 0000000000..f6f33534ab --- /dev/null +++ b/cpukit/libcsupport/src/fcntl.c @@ -0,0 +1,111 @@ +/* + * fcntl() - POSIX 1003.1b 6.5.2 - File Control + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include <rtems.h> +#include "libio_.h" + +int fcntl( + int fd, + int cmd, + ... +) +{ + va_list ap; + rtems_libio_t *iop; + + va_start( ap, cmd ); + + /* + * If this is not a file system based entity, it is an error. + */ + + if ( rtems_file_descriptor_type( fd ) ) + set_errno_and_return_minus_one( EBADF ); + + /* + * Now process the fcntl(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + + /* + * This switch should contain all the cases from POSIX. + */ + + switch ( cmd ) { + case F_DUPFD: /* dup */ + /* + * This is how it appears that this case should work: + * + * filedes2 = va_arg( ap, int ) + * if filedes2 is 0 + * duplicate fd into a new descriptor + * else + * duplicate fd into specified descriptor after error checking it + * + * See dup2() in case we can eliminate stuff in there. + */ + return -1; + + case F_GETFD: /* get f_flags */ + if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC ) + return 1; + return 0; + + case F_SETFD: /* set f_flags */ + /* + * Interpret the third argument as the "close on exec()" flag. + * If this argument is 1, then the file descriptor is to be closed + * if a new process is exec()'ed. Since RTEMS does not support + * processes, then we can ignore this one except to make + * F_GETFD work. + */ + + if ( va_arg( ap, int ) ) + iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC; + else + iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC; + return 0; + + case F_GETFL: /* more flags (cloexec) */ + return -1; + + case F_SETFL: + return -1; + + case F_GETLK: + return -1; + + case F_SETLK: + return -1; + + case F_SETLKW: + return -1; + + case F_SETOWN: /* for sockets. */ + return -1; + + case F_GETOWN: /* for sockets. */ + return -1; + + default: + break; + } + return -1; +} diff --git a/cpukit/libcsupport/src/fdatasync.c b/cpukit/libcsupport/src/fdatasync.c new file mode 100644 index 0000000000..58a4c4e118 --- /dev/null +++ b/cpukit/libcsupport/src/fdatasync.c @@ -0,0 +1,45 @@ +/* + * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> + +#include "libio_.h" + +int fdatasync( + int fd +) +{ + rtems_libio_t *iop; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if ( rtems_file_descriptor_type( fd ) ) + set_errno_and_return_minus_one( EBADF ); + + /* + * Now process the fdatasync(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + + if ( !iop->handlers->fdatasync ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->handlers->fdatasync)( iop ); +} diff --git a/cpukit/libcsupport/src/fpathconf.c b/cpukit/libcsupport/src/fpathconf.c new file mode 100644 index 0000000000..ea2377e15b --- /dev/null +++ b/cpukit/libcsupport/src/fpathconf.c @@ -0,0 +1,91 @@ +/* + * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + +#include <unistd.h> +#include <errno.h> + +long fpathconf( + int fd, + int name +) +{ + long return_value; + rtems_libio_t *iop; + rtems_filesystem_limits_and_options_t *the_limits; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then it is an error since fpathconf() is not included in the + * set. + */ + + if ( rtems_file_descriptor_type( fd ) ) + set_errno_and_return_minus_one( EBADF ); + + /* + * Now process the information request. + */ + + iop = rtems_libio_iop(fd); + rtems_libio_check_fd(fd); + rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ); + + the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options; + + switch ( name ) { + case _PC_LINK_MAX: + return_value = the_limits->link_max; + break; + case _PC_MAX_CANON: + return_value = the_limits->max_canon; + break; + case _PC_MAX_INPUT: + return_value = the_limits->max_input; + break; + case _PC_NAME_MAX: + return_value = the_limits->name_max; + break; + case _PC_PATH_MAX: + return_value = the_limits->path_max; + break; + case _PC_PIPE_BUF: + return_value = the_limits->pipe_buf; + break; + case _PC_CHOWN_RESTRICTED: + return_value = the_limits->posix_chown_restrictions; + break; + case _PC_NO_TRUNC: + return_value = the_limits->posix_no_trunc; + break; + case _PC_VDISABLE: + return_value = the_limits->posix_vdisable; + break; + case _PC_ASYNC_IO: + return_value = the_limits->posix_async_io; + break; + case _PC_PRIO_IO: + return_value = the_limits->posix_prio_io; + break; + case _PC_SYNC_IO: + return_value = the_limits->posix_sync_io; + break; + default: + set_errno_and_return_minus_one( EINVAL ); + break; + } + + return return_value; +} diff --git a/cpukit/libcsupport/src/fstat.c b/cpukit/libcsupport/src/fstat.c new file mode 100644 index 0000000000..82d144dd2c --- /dev/null +++ b/cpukit/libcsupport/src/fstat.c @@ -0,0 +1,94 @@ +/* + * fstat() - POSIX 1003.1b 5.6.2 - Get File Status + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> + +#include "libio_.h" + +int fstat( + int fd, + struct stat *sbuf +) +{ + rtems_libio_t *iop; + + /* + * Check to see if we were passed a valid pointer. + */ + + if ( !sbuf ) + set_errno_and_return_minus_one( EFAULT ); + + /* + * Zero out the stat structure so the various support + * versions of stat don't have to. + */ + + memset( sbuf, 0, sizeof(struct stat) ); + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if (rtems_file_descriptor_type(fd)) { + switch (rtems_file_descriptor_type (fd)) { + case RTEMS_FILE_DESCRIPTOR_TYPE_FILE: + break; + + case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET: +#if !defined(__GO32__) + sbuf->st_mode = S_IFSOCK; + break; +#endif + + default: + set_errno_and_return_minus_one( EBADF ); + } + } + + /* + * Now process the stat() request. + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + + if ( !iop->handlers->fstat ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->handlers->fstat)( &iop->pathinfo, sbuf ); +} + +/* + * _fstat_r + * + * This is the Newlib dependent reentrant version of fstat(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _fstat_r( + struct _reent *ptr, + int fd, + struct stat *buf +) +{ + return fstat( fd, buf ); +} +#endif diff --git a/cpukit/libcsupport/src/fsync.c b/cpukit/libcsupport/src/fsync.c new file mode 100644 index 0000000000..a5ed1e99e7 --- /dev/null +++ b/cpukit/libcsupport/src/fsync.c @@ -0,0 +1,45 @@ +/* + * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> + +#include "libio_.h" + +int fsync( + int fd +) +{ + rtems_libio_t *iop; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if ( rtems_file_descriptor_type( fd ) ) + set_errno_and_return_minus_one( EBADF ); + + /* + * Now process the fsync(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + + if ( !iop->handlers->fsync ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->handlers->fsync)( iop ); +} diff --git a/cpukit/libcsupport/src/ftruncate.c b/cpukit/libcsupport/src/ftruncate.c new file mode 100644 index 0000000000..7fb2286531 --- /dev/null +++ b/cpukit/libcsupport/src/ftruncate.c @@ -0,0 +1,60 @@ +/* + * ftruncate() - Truncate a File to the Specified Length + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <errno.h> + +#include "libio_.h" + +int ftruncate( + int fd, + off_t length +) +{ + rtems_libio_t *iop; + rtems_filesystem_location_info_t loc; + + /* + * If this is not a file system based entity, it is an error. + */ + + if ( rtems_file_descriptor_type( fd ) ) + set_errno_and_return_minus_one( EBADF ); + + /* + * Now process the ftruncate() request. + */ + + iop = rtems_libio_iop( fd ); + + /* + * Make sure we are not working on a directory + */ + + loc = iop->pathinfo; + if ( !loc.ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) + set_errno_and_return_minus_one( EISDIR ); + + rtems_libio_check_fd( fd ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + + if ( !iop->handlers->ftruncate ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->handlers->ftruncate)( iop, length ); +} + diff --git a/cpukit/libcsupport/src/getdents.c b/cpukit/libcsupport/src/getdents.c index 9b16d82409..91631843b7 100644 --- a/cpukit/libcsupport/src/getdents.c +++ b/cpukit/libcsupport/src/getdents.c @@ -1,14 +1,59 @@ /* - * Just enough to make newlib return an error. + * getdents() - Get Directory Entries + * + * SVR4 and SVID extension required by Newlib readdir() family. + * + * This routine will dd_len / (sizeof dirent) directory entries relative to + * the current directory position index. These entries will be placed in + * character array pointed to by -dd_buf- + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. * * $Id$ */ +#include <errno.h> + +#include "libio_.h" + int getdents( - int fd, - void *buf, - int len + int dd_fd, + char *dd_buf, + int dd_len ) { - return -1; + rtems_libio_t *iop; + rtems_filesystem_location_info_t loc; + + /* + * Get the file control block structure associated with the file descriptor + */ + + iop = rtems_libio_iop( dd_fd ); + + /* + * Make sure we are working on a directory + */ + loc = iop->pathinfo; + if ( !loc.ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * Return the number of bytes that were actually transfered as a result + * of the read attempt. + */ + + if ( !iop->handlers->read ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->handlers->read)( iop, dd_buf, dd_len ); } diff --git a/cpukit/libcsupport/src/hosterr.c b/cpukit/libcsupport/src/hosterr.c index a55e4a7e84..6c0308df3b 100644 --- a/cpukit/libcsupport/src/hosterr.c +++ b/cpukit/libcsupport/src/hosterr.c @@ -13,31 +13,36 @@ */ #include <rtems.h> +#if defined(RTEMS_UNIX) #include <errno.h> -int host_errno(void); +int host_errno( void ); /* - * copy host errno, if any to thread aware errno, if any + * fix_syscall_errno + * + * copy host errno, if any to thread aware errno, if any */ -void fix_syscall_errno(void) +void fix_syscall_errno( void ) { - errno = host_errno(); + errno = host_errno(); } /* - * Get the host system errno, if any - * When using newlib (or possibly other libc's) on top of UNIX - * the errno returned by system calls may be unavailable due - * to trickery of making errno thread aware. - * This provides a kludge of getting at it. + * host_errno + * + * Get the host system errno, if any + * When using newlib (or possibly other libc's) on top of UNIX + * the errno returned by system calls may be unavailable due + * to trickery of making errno thread aware. + * This provides a kludge of getting at it. */ #undef errno extern int errno; int host_errno(void) { - return errno; + return errno; } - +#endif diff --git a/cpukit/libcsupport/src/ioctl.c b/cpukit/libcsupport/src/ioctl.c new file mode 100644 index 0000000000..0aaf0379ae --- /dev/null +++ b/cpukit/libcsupport/src/ioctl.c @@ -0,0 +1,57 @@ +/* + * ioctl() system call + * + * This routine is not defined in the POSIX 1003.1b standard but is + * commonly supported on most UNIX and POSIX systems. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + +int ioctl( + int fd, + unsigned32 command, + void * buffer +) +{ + rtems_status_code rc; + rtems_libio_t *iop; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if ( rtems_file_descriptor_type( fd ) ) { + rtems_libio_ioctl_t fp; + + fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].ioctl; + if ( fp == NULL ) + set_errno_and_return_minus_one( EBADF ); + + return (*fp)( fd, command, buffer ); + } + + /* + * Now process the ioctl(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + + if ( !iop->handlers->ioctl ) + set_errno_and_return_minus_one( ENOTSUP ); + + rc = (*iop->handlers->ioctl)( iop, command, buffer ); + + return rc; +} diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c index 12682c1190..e63a4626d4 100644 --- a/cpukit/libcsupport/src/libio.c +++ b/cpukit/libcsupport/src/libio.c @@ -1,524 +1,295 @@ /* - * Provide UNIX/POSIX-like io system calls for RTEMS using the - * RTEMS IO manager + * This file contains the support infrastructure used to manage the + * table of integer style file descriptors used by the low level + * POSIX system calls like open(), read, fstat(), etc. + * + * This provides the foundation for POSIX compliant IO system calls + * for RTEMS. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. * * $Id$ */ -#include <rtems.h> -#include <rtems/assoc.h> /* assoc.h not included by rtems.h */ - -#include <stdio.h> /* O_RDONLY, et.al. */ -#include <fcntl.h> /* O_RDONLY, et.al. */ -#include <assert.h> - -#if ! defined(O_NDELAY) -# if defined(solaris2) -# define O_NDELAY O_NONBLOCK -# elif defined(RTEMS_NEWLIB) -# define O_NDELAY _FNBIO -# endif -#endif - - -#include <errno.h> -#include <string.h> /* strcmp */ -#include <unistd.h> -#include <stdlib.h> /* calloc() */ - -#include "libio.h" /* libio.h not pulled in by rtems */ +#include "libio_.h" /* libio_.h pulls in rtems */ /* - * Semaphore to protect the io table + * Global variables used to manage the File Descriptor Table. + * IOP = IO Pointer. */ -Objects_Id rtems_libio_semaphore; - -#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O') -#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n) - -extern unsigned32 rtems_libio_number_iops; -rtems_libio_t *rtems_libio_iops; -rtems_libio_t *rtems_libio_last_iop; - -#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \ - &rtems_libio_iops[fd] : 0) - -#define rtems_libio_check_fd(fd) \ - do { \ - if ((unsigned32) (fd) >= rtems_libio_number_iops) \ - { \ - errno = EBADF; \ - return -1; \ - } \ - } while (0) - -#define rtems_libio_check_buffer(buffer) \ - do { \ - if ((buffer) == 0) \ - { \ - errno = EINVAL; \ - return -1; \ - } \ - } while (0) - -#define rtems_libio_check_count(count) \ - do { \ - if ((count) == 0) \ - { \ - return 0; \ - } \ - } while (0) - -#define rtems_libio_check_permissions(iop, flag) \ - do { \ - if (((iop)->flags & (flag)) == 0) \ - { \ - errno = EINVAL; \ - return -1; \ - } \ - } while (0) +rtems_id rtems_libio_semaphore; +rtems_libio_t *rtems_libio_iops; +rtems_libio_t *rtems_libio_last_iop; +rtems_libio_handler_t rtems_libio_handlers[15]; /* - * External I/O handlers - * - * Space for all possible handlers is preallocated - * to speed up dispatch to external handlers. + * rtems_register_libio_handler + * + * This function registers an external IO handler set. This lets + * other subsystems have their own versions of many of the system + * calls. For example, the networking code registers handlers which + * map the system calls for read() and write() to socket calls. + * */ -static rtems_libio_handler_t handlers[15]; - -void -rtems_register_libio_handler( - int handler_flag, - const rtems_libio_handler_t *handler +void rtems_register_libio_handler( + int handler_flag, + const rtems_libio_handler_t *handler ) { - int handler_index = rtems_file_descriptor_type_index(handler_flag); + int handler_index = rtems_file_descriptor_type_index( handler_flag ); + if ((handler_index < 0) || (handler_index >= 15)) rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER ); - handlers[handler_index] = *handler; -} - -/* - * Called by bsp startup code to init the libio area. - */ -void -rtems_libio_init(void) -{ - rtems_status_code rc; - - if (rtems_libio_number_iops > 0) - { - rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops, - sizeof(rtems_libio_t)); - if (rtems_libio_iops == NULL) - rtems_fatal_error_occurred(RTEMS_NO_MEMORY); - - rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1); - } - - rc = rtems_semaphore_create( - RTEMS_LIBIO_SEM, - 1, - RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &rtems_libio_semaphore - ); - if (rc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred(rc); + rtems_libio_handlers[handler_index] = *handler; } /* - * Convert RTEMS status to a UNIX errno + * rtems_libio_init + * + * Called by BSP startup code to initialize the libio subsystem. */ -rtems_assoc_t errno_assoc[] = { - { "OK", RTEMS_SUCCESSFUL, 0 }, - { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY }, - { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL }, - { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS }, - { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT }, - { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM }, - { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV }, - { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF}, - { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM}, - { "IO ERROR", RTEMS_IO_ERROR, EIO}, - { 0, 0, 0 }, -}; - -static unsigned32 -rtems_libio_errno(rtems_status_code code) +void rtems_libio_init( void ) { - int rc; - - if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code))) - { - errno = rc; - return -1; - } - return -1; + rtems_status_code rc; + + /* + * Allocate memory for the IOP Table + */ + + if ( rtems_libio_number_iops > 0 ) { + rtems_libio_iops = + (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t)); + + if (rtems_libio_iops == NULL) + rtems_fatal_error_occurred( RTEMS_NO_MEMORY ); + + rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1); + } + + /* + * Create the binary semaphore used to provide mutual exclusion + * on the IOP Table. + */ + + rc = rtems_semaphore_create( + RTEMS_LIBIO_SEM, + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &rtems_libio_semaphore + ); + if ( rc != RTEMS_SUCCESSFUL ) + rtems_fatal_error_occurred( rc ); + + /* + * Initialize the base file system infrastructure. + */ + + rtems_filesystem_initialize(); } /* - * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand + * rtems_libio_fcntl_flags + * + * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand */ 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 }, + { "READ", LIBIO_FLAGS_READ, O_RDONLY }, + { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, + { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, + { 0, 0, 0 }, }; rtems_assoc_t status_flags_assoc[] = { - { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, - { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, - { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, - { 0, 0, 0 }, + { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, + { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, + { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, + { 0, 0, 0 }, }; -static unsigned32 -rtems_libio_fcntl_flags(unsigned32 fcntl_flags) +unsigned32 rtems_libio_fcntl_flags( + unsigned32 fcntl_flags +) { - unsigned32 flags = 0; - unsigned32 access_modes; + unsigned32 flags = 0; + unsigned32 access_modes; - /* - * Access mode is a small integer - */ - - access_modes = fcntl_flags & O_ACCMODE; - fcntl_flags &= ~O_ACCMODE; - flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes); + /* + * Access mode is a small integer + */ + + access_modes = fcntl_flags & O_ACCMODE; + fcntl_flags &= ~O_ACCMODE; + flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes ); - /* - * Everything else is single bits - */ + /* + * Everything else is single bits + */ - flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); - return flags; + flags |= + rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); + return flags; } +/* + * rtems_libio_allocate + * + * This routine searches the IOP Table for an unused entry. If it + * finds one, it returns it. Otherwise, it returns NULL. + */ -static rtems_libio_t * -rtems_libio_allocate(void) +rtems_libio_t *rtems_libio_allocate( void ) { - rtems_libio_t *iop; - rtems_status_code rc; - - rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - - for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) - if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) - { - /* - * Got one; create a semaphore for it - */ - - rc = rtems_semaphore_create( - RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), - 1, - RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &iop->sem - ); - if (rc != RTEMS_SUCCESSFUL) - goto failed; - - iop->flags = LIBIO_FLAGS_OPEN; - goto done; - } + rtems_libio_t *iop; + rtems_status_code rc; + + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); + + for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) + if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) { + /* + * Got an IOP -- create a semaphore for it. + */ + + rc = rtems_semaphore_create( + RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &iop->sem + ); + if ( rc != RTEMS_SUCCESSFUL ) + goto failed; + iop->flags = LIBIO_FLAGS_OPEN; + goto done; + } + failed: - iop = 0; - + iop = 0; + done: - rtems_semaphore_release(rtems_libio_semaphore); - return iop; + rtems_semaphore_release( rtems_libio_semaphore ); + return iop; } -static void -rtems_libio_free(rtems_libio_t *iop) -{ - rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - - if (iop->sem) - rtems_semaphore_delete(iop->sem); - (void) memset(iop, 0, sizeof(*iop)); - - rtems_semaphore_release(rtems_libio_semaphore); -} +/* + * rtems_libio_free + * + * This routine frees the resources associated with an IOP (file descriptor) + * and clears the slot in the IOP Table. + */ -int -__rtems_open( - const char *pathname, - unsigned32 flag, - unsigned32 mode) +void rtems_libio_free( + rtems_libio_t *iop +) { - rtems_status_code rc; - rtems_libio_t *iop = 0; - rtems_driver_name_t *np; - rtems_libio_open_close_args_t args; - - /* - * 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(). - */ - - if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) - goto done; - - iop = rtems_libio_allocate(); - if (iop == 0) - { - rc = RTEMS_TOO_MANY; - goto done; - } - - iop->driver = np; - iop->pathname = (char *) pathname; - iop->flags |= rtems_libio_fcntl_flags(flag); + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); - args.iop = iop; - args.flags = iop->flags; - args.mode = mode; + if (iop->sem) + rtems_semaphore_delete(iop->sem); - rc = rtems_io_open(np->major, np->minor, (void *) &args); - -done: - - if (rc != RTEMS_SUCCESSFUL) - { - if (iop) - rtems_libio_free(iop); - return rtems_libio_errno(rc); - } - - return iop - rtems_libio_iops; -} - -int -__rtems_close( - int fd - ) -{ - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_open_close_args_t args; - int status; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd); - - fp = handlers[rtems_file_descriptor_type_index(fd)].close; - if (fp == NULL) { - errno = EBADF; - return -1; - } - status = (*fp)(fd); - return status; - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); + (void) memset(iop, 0, sizeof(*iop)); - np = iop->driver; - - args.iop = iop; - args.flags = 0; - args.mode = 0; - - rc = rtems_io_close(np->major, np->minor, (void *) &args); + rtems_semaphore_release( rtems_libio_semaphore ); +} - rtems_libio_free(iop); +/* + * 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 atleast 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. + */ - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); - return 0; -} - -int -__rtems_read( - int fd, - void * buffer, - unsigned32 count - ) +int rtems_libio_is_open_files_in_fs( + rtems_filesystem_mount_table_entry_t * fs_mt_entry +) { - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_rw_args_t args; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, void *buffer, unsigned32 count); - - fp = handlers[rtems_file_descriptor_type_index(fd)].read; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, buffer, count); - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); - rtems_libio_check_buffer(buffer); - rtems_libio_check_count(count); - rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ); + rtems_libio_t *iop; + int result = 0; - np = iop->driver; + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); - args.iop = iop; - args.offset = iop->offset; - args.buffer = buffer; - args.count = count; - args.flags = iop->flags; - args.bytes_moved = 0; + /* + * Look for any active file descriptor entry. + */ - rc = rtems_io_read(np->major, np->minor, (void *) &args); + for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) { - iop->offset += args.bytes_moved; + if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); + /* + * Check if this node is under the file system that we + * are trying to dismount. + */ - return args.bytes_moved; -} - -int -__rtems_write( - int fd, - const void *buffer, - unsigned32 count - ) -{ - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_rw_args_t args; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, const void *buffer, unsigned32 count); - - fp = handlers[rtems_file_descriptor_type_index(fd)].write; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, buffer, count); + if ( iop->pathinfo.mt_entry == fs_mt_entry ) { + result = 1; + break; + } } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); - rtems_libio_check_buffer(buffer); - rtems_libio_check_count(count); - rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE); - - np = iop->driver; - - args.iop = iop; - args.offset = iop->offset; - args.buffer = (void *) buffer; - args.count = count; - args.flags = iop->flags; - args.bytes_moved = 0; - - rc = rtems_io_write(np->major, np->minor, (void *) &args); + } - iop->offset += args.bytes_moved; + rtems_semaphore_release( rtems_libio_semaphore ); - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); - - return args.bytes_moved; + return result; } -int -__rtems_ioctl( - int fd, - unsigned32 command, - void * buffer) -{ - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_ioctl_args_t args; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, unsigned32 command, void *buffer); - - fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, command, buffer); - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); +/* + * 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. + */ - np = iop->driver; +int rtems_libio_is_file_open( + void *node_access +) +{ + rtems_libio_t *iop; + int result=0; - args.iop = iop; - args.command = command; - args.buffer = buffer; + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); - rc = rtems_io_control(np->major, np->minor, (void *) &args); + /* + * Look for any active file descriptor entry. + */ - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); + for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) { - return args.ioctl_return; -} - -/* - * internal only?? - */ + if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { + /* + * Check if this node is under the file system that we + * are trying to dismount. + */ -int -__rtems_lseek( - int fd, - rtems_libio_offset_t offset, - int whence - ) -{ - rtems_libio_t *iop; + if ( iop->pathinfo.node_access == node_access ) { + result = 1; + break; + } + } + } - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, rtems_libio_offset_t offset, int whence); + rtems_semaphore_release( rtems_libio_semaphore ); - fp = handlers[rtems_file_descriptor_type_index(fd)].lseek; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, offset, whence); - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); - - switch (whence) - { - case SEEK_SET: - iop->offset = offset; - break; - - case SEEK_CUR: - iop->offset += offset; - break; - - case SEEK_END: - iop->offset = iop->size - offset; - break; - - default: - errno = EINVAL; - return -1; - } - return 0; + return result; } diff --git a/cpukit/libcsupport/src/link.c b/cpukit/libcsupport/src/link.c new file mode 100644 index 0000000000..1cee54d0bf --- /dev/null +++ b/cpukit/libcsupport/src/link.c @@ -0,0 +1,60 @@ +/* + * link() - POSIX 1003.1b - 5.3.4 - Create a new link + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <rtems/libio.h> +#include <errno.h> + +#include "libio_.h" + +int link( + const char *existing, + const char *new +) +{ + rtems_filesystem_location_info_t existing_loc; + rtems_filesystem_location_info_t parent_loc; + int i; + int result; + const char *name_start; + + /* + * Get the node we are linking to. + */ + result = rtems_filesystem_evaluate_path( 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)( &new[i], &parent_loc, &name_start ); + if ( result != 0 ) + set_errno_and_return_minus_one( result ); + + /* + * Check to see if the caller is trying to link across file system + * boundaries. + */ + + if ( parent_loc.mt_entry != existing_loc.mt_entry ) + set_errno_and_return_minus_one( EXDEV ); + + if ( !parent_loc.ops->link ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*parent_loc.ops->link)( &existing_loc, &parent_loc, name_start ); +} diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c new file mode 100644 index 0000000000..514f8cd912 --- /dev/null +++ b/cpukit/libcsupport/src/lseek.c @@ -0,0 +1,93 @@ +/* + * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <stdio.h> + +#include "libio_.h" + +off_t lseek( + int fd, + off_t offset, + int whence +) +{ + rtems_libio_t *iop; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if ( rtems_file_descriptor_type( fd ) ) { + rtems_libio_lseek_t fp; + + fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].lseek; + if ( fp == NULL ) + set_errno_and_return_minus_one( EBADF ); + + return (*fp)( fd, offset, whence ); + } + + /* + * Now process the lseek(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + + switch ( whence ) { + case SEEK_SET: + iop->offset = offset; + break; + + case SEEK_CUR: + iop->offset += offset; + break; + + case SEEK_END: + iop->offset = iop->size - offset; + break; + + default: + errno = EINVAL; + return -1; + } + + if ( !iop->handlers->lseek ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*iop->handlers->lseek)( iop, offset, whence ); +} + +/* + * _lseek_r + * + * This is the Newlib dependent reentrant version of lseek(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +off_t _lseek_r( + struct _reent *ptr, + int fd, + off_t offset, + int whence +) +{ + return lseek( fd, offset, whence ); +} +#endif + diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c index fac38585a7..f164e45f6c 100644 --- a/cpukit/libcsupport/src/malloc.c +++ b/cpukit/libcsupport/src/malloc.c @@ -135,7 +135,7 @@ void RTEMS_Malloc_Initialize( #ifdef MALLOC_STATS /* zero all the stats */ - (void) memset(&rtems_malloc_stats, 0, sizeof(rtems_malloc_stats)); + (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) ); #endif MSBUMP(space_available, length); @@ -220,9 +220,11 @@ void *malloc( { unsigned32 actual_size; unsigned32 current_depth; - status = rtems_region_get_segment_size(RTEMS_Malloc_Heap, return_this, &actual_size); + status = rtems_region_get_segment_size( + RTEMS_Malloc_Heap, return_this, &actual_size); MSBUMP(lifetime_allocated, actual_size); - current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed; + current_depth = rtems_malloc_stats.lifetime_allocated - + rtems_malloc_stats.lifetime_freed; if (current_depth > rtems_malloc_stats.max_depth) rtems_malloc_stats.max_depth = current_depth; } @@ -335,10 +337,12 @@ void free( void malloc_dump(void) { - unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed; + unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - + rtems_malloc_stats.lifetime_freed; printf("Malloc stats\n"); - printf(" avail:%uk allocated:%uk (%d%%) max:%uk (%d%%) lifetime:%Luk freed:%Luk\n", + printf(" avail:%uk allocated:%uk (%d%%) " + "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n", (unsigned int) rtems_malloc_stats.space_available / 1024, (unsigned int) allocated / 1024, /* avoid float! */ diff --git a/cpukit/libcsupport/src/mkdir.c b/cpukit/libcsupport/src/mkdir.c new file mode 100644 index 0000000000..18fc7171c7 --- /dev/null +++ b/cpukit/libcsupport/src/mkdir.c @@ -0,0 +1,28 @@ +/* + * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> + +int mkdir( + const char *pathname, + mode_t mode +) +{ + return mknod( pathname, mode | S_IFDIR, 0LL); +} + diff --git a/cpukit/libcsupport/src/mkfifo.c b/cpukit/libcsupport/src/mkfifo.c new file mode 100644 index 0000000000..6b3ece5650 --- /dev/null +++ b/cpukit/libcsupport/src/mkfifo.c @@ -0,0 +1,25 @@ +/* + * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +int mkfifo( + const char *path, + mode_t mode +) +{ + return mknod( path, mode | S_IFIFO, 0LL ); +} diff --git a/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c new file mode 100644 index 0000000000..4f83321ecd --- /dev/null +++ b/cpukit/libcsupport/src/mknod.c @@ -0,0 +1,60 @@ +/* + * mknod() + * + * This routine is not defined in the POSIX 1003.1b standard but is + * commonly supported on most UNIX and POSIX systems. It is the + * foundation for creating file system objects. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <assert.h> + +#include "libio_.h" + +int mknod( + const char *pathname, + mode_t mode, + dev_t dev +) +{ + rtems_filesystem_location_info_t temp_loc; + int i; + const char *name_start; + int result; + + if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) ) + set_errno_and_return_minus_one( EINVAL ); + + if ( S_ISFIFO(mode) ) + set_errno_and_return_minus_one( ENOTSUP ); + + rtems_filesystem_get_start_loc( pathname, &i, &temp_loc ); + + result = (*temp_loc.ops->evalformake)( + &pathname[i], + &temp_loc, + &name_start + ); + if ( result != 0 ) + return -1; + + if ( !temp_loc.ops->mknod ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*temp_loc.ops->mknod)( name_start, mode, dev, &temp_loc ); +} diff --git a/cpukit/libcsupport/src/mount.c b/cpukit/libcsupport/src/mount.c new file mode 100644 index 0000000000..fa8cebc3f9 --- /dev/null +++ b/cpukit/libcsupport/src/mount.c @@ -0,0 +1,299 @@ +/* + * mount() + * + * XXX + * + * XXX make sure no required ops are NULL + * XXX make sure no optional ops you are using are NULL + * XXX unmount should be required. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <chain.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "libio_.h" + +Chain_Control rtems_filesystem_mount_table_control; + + +rtems_filesystem_limits_and_options_t IMFS_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 */ +}; + +/* + * XXX + */ + +int search_mt_for_mount_point( + rtems_filesystem_location_info_t *location_of_mount_point +); + + +rtems_filesystem_options_t get_file_system_options( + char *fsoptions +); + +int init_fs_mount_table( void ); + + +/* + * XXX + */ + +#define FOUND 0 +#define NOT_FOUND -1 + +/* + * 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 + * + */ + +int mount( + rtems_filesystem_mount_table_entry_t **mt_entry, + rtems_filesystem_operations_table *fs_ops, + char *fsoptions, + char *device, + char *mount_point +) +{ + rtems_filesystem_location_info_t temp_loc; + rtems_filesystem_options_t options; + rtems_filesystem_mount_table_entry_t *temp_mt_entry; + +/* XXX add code to check for required operations */ + + /* + * Are the file system options valid? + */ + + options = get_file_system_options( fsoptions ); + if ( options == RTEMS_FILESYSTEM_BAD_OPTIONS ){ + errno = EINVAL; + return -1; + } + + /* + * Is the file system type valid? + */ + + if ( fs_ops == NULL ){ + errno = EINVAL; + return -1; + } + + /* + * Allocate a mount table entry + */ + + temp_mt_entry = malloc( sizeof(rtems_filesystem_mount_table_entry_t) ); + + temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry; + temp_mt_entry->options = options; + if( device ) + sprintf( temp_mt_entry->dev, "%s", device ); + else + temp_mt_entry->dev = 0; + + /* + * The mount_point should be a directory with read/write/execute + * permissions in the existing tree. + */ + + if ( mount_point ) { + if ( rtems_filesystem_evaluate_path( + mount_point, + RTEMS_LIBIO_PERMS_RWX, + &temp_loc , + TRUE ) == -1 ) + goto cleanup_and_bail; + + /* + * Test to see if it is a directory + */ + + if ( temp_loc.ops->node_type( &temp_loc ) != RTEMS_FILESYSTEM_DIRECTORY ){ + errno = ENOTDIR; + goto cleanup_and_bail; + } + + /* + * You can only mount one file system onto a single mount point. + */ + + if ( search_mt_for_mount_point( &temp_loc ) == FOUND ){ + errno = EBUSY; + goto cleanup_and_bail; + } + + /* + * This must be a good mount point, so move the location information + * into the allocated mount entry + */ + + temp_mt_entry->mt_point_node.node_access = temp_loc.node_access; + temp_mt_entry->mt_point_node.handlers = temp_loc.handlers; + temp_mt_entry->mt_point_node.ops = temp_loc.ops; + temp_mt_entry->mt_point_node.mt_entry = temp_loc.mt_entry; + + /* + * This link to the parent is only done when we are dealing with system + * below the base file system + */ + + if ( !temp_loc.ops->mount ){ + errno = ENOTSUP; + goto cleanup_and_bail; + } + + if ( temp_loc.ops->mount( temp_mt_entry ) ) { + goto cleanup_and_bail; + } + } + else { + + /* + * This is a mount of the base file system --> The + * mt_point_node.node_access will be set to null to indicate that this + * is the root of the entire file system. + */ + + temp_mt_entry->mt_fs_root.node_access = NULL; + temp_mt_entry->mt_fs_root.handlers = NULL; + temp_mt_entry->mt_fs_root.ops = NULL; + + temp_mt_entry->mt_point_node.node_access = NULL; + temp_mt_entry->mt_point_node.handlers = NULL; + temp_mt_entry->mt_point_node.ops = NULL; + temp_mt_entry->mt_point_node.mt_entry = NULL; + } + + if ( !fs_ops->fsmount_me ){ + errno = ENOTSUP; + goto cleanup_and_bail; + } + + if ( fs_ops->fsmount_me( temp_mt_entry ) ) + goto cleanup_and_bail; + + /* + * Add the mount table entry to the mount table chain + */ + + Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node ); + + *mt_entry = temp_mt_entry; + return 0; + +cleanup_and_bail: + + free( temp_mt_entry ); + return -1; +} + + + +/* + * init_fs_mount_table + * + * This routine will initialize the chain control element that manages the + * mount table chain. + */ + +int init_fs_mount_table() +{ + Chain_Initialize_empty ( &rtems_filesystem_mount_table_control ); + return 0; +} + +/* + * get_file_system_options + * + * This routine will determine is the text string that represents the options + * that are to be used to mount the file system are actually valid. If the + * options are valid the appropriate file system options type will be returned + * to the calling routine. + */ + +rtems_filesystem_options_t get_file_system_options( + char *fsoptions +) +{ + if ( strcmp( "RO", strupr( fsoptions ) ) == 0 ) + return RTEMS_FILESYSTEM_READ_ONLY; + if ( strcmp( "RW", strupr( fsoptions ) ) == 0 ) + return RTEMS_FILESYSTEM_READ_WRITE_ONLY; + else + return RTEMS_FILESYSTEM_BAD_OPTIONS; +} + + + +/* + * search_mt_for_mount_point + * + * This routine will run through the entries that currently exist in the + * mount table chain. For each entry in the mount table chain it will + * compare the mount tables mt_point_node to the node describing the selected + * mount point.. If any of the mount table file system mount point nodes + * match the new file system selected mount point node, we are attempting + * to mount the new file system onto a node that already has a file system + * mounted to it. This is not a permitted operation. + */ + +int search_mt_for_mount_point( + rtems_filesystem_location_info_t *location_of_mount_point +) +{ + Chain_Node *the_node; + rtems_filesystem_mount_table_entry_t *the_mount_entry; + + for ( the_node = rtems_filesystem_mount_table_control.first; + !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node ); + the_node = the_node->next ) { + + the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node; + if ( the_mount_entry->mt_point_node.node_access == + location_of_mount_point->node_access ) + return FOUND; + } + return NOT_FOUND; +} + diff --git a/cpukit/libcsupport/src/newlibc.c b/cpukit/libcsupport/src/newlibc.c index a6acc1c8d7..bea592a46e 100644 --- a/cpukit/libcsupport/src/newlibc.c +++ b/cpukit/libcsupport/src/newlibc.c @@ -1,21 +1,14 @@ - /* + * Implementation of hooks for the CYGNUS newlib libc + * These hooks set things up so that: + * + '_REENT' is switched at task switch time. + * * COPYRIGHT (c) 1994 by Division Incorporated * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. * - * Description: - * Implementation of hooks for the CYGNUS newlib libc - * These hooks set things up so that: - * '_REENT' is switched at task switch time. - * - * - * TODO: - * - * NOTE: - * * $Id$ * */ @@ -47,7 +40,21 @@ #include <stdio.h> #endif -#include "internal.h" +/* + * Private routines + */ + +void MY_task_set_note( + rtems_tcb *tcb, + rtems_unsigned32 notepad, + rtems_unsigned32 note +); + +rtems_unsigned32 MY_task_get_note( + rtems_tcb *tcb, + rtems_unsigned32 notepad +); + #define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST @@ -304,7 +311,7 @@ libc_init(int reentrant) rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'), &libc_extension, &extension_id); if (rc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred(rc); + rtems_fatal_error_occurred( rc ); libc_reentrant = reentrant; } @@ -353,11 +360,14 @@ int get_errno() /* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */ #if !defined(RTEMS_UNIX) && !defined(_AM29K) +#if !defined(pc386) void _exit(int status) { libc_wrapup(); /* Why? XXX */ rtems_shutdown_executive(status); } +#endif + #else void exit(int status) @@ -426,4 +436,46 @@ unsigned int sleep( #endif +/* + * Newlib Interface Support + * + * Routines to Access Internal RTEMS Resources without violating + * kernel visibility. + * + */ + +void MY_task_set_note( + Thread_Control *the_thread, + unsigned32 notepad, + unsigned32 note +) +{ + RTEMS_API_Control *api; + + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + + if ( api ) + api->Notepads[ notepad ] = note; +} + + +unsigned32 MY_task_get_note( + Thread_Control *the_thread, + unsigned32 notepad +) +{ + RTEMS_API_Control *api; + + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + + return api->Notepads[ notepad ]; +} + +void *MY_CPU_Context_FP_start( + void *base, + unsigned32 offset +) +{ + return _CPU_Context_Fp_start( base, offset ); +} #endif diff --git a/cpukit/libcsupport/src/no_libc.c b/cpukit/libcsupport/src/no_libc.c index 5a58ba761c..4bd02c4b27 100644 --- a/cpukit/libcsupport/src/no_libc.c +++ b/cpukit/libcsupport/src/no_libc.c @@ -1,6 +1,4 @@ - -/* no_libc.h - * +/* * This file contains stubs for the reentrancy hooks when * an unknown C library is used. * @@ -17,15 +15,15 @@ #include <rtems.h> -#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX) +#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX) #include "libcsupport.h" -#include "internal.h" #include <stdlib.h> /* for free() */ -void -libc_init(int reentrant) +void libc_init( + int reentrant +) { } @@ -34,11 +32,15 @@ void libc_suspend_main(void) } -void libc_global_exit(rtems_unsigned32 code) +void libc_global_exit( + rtems_unsigned32 code +) { } -void _exit(int status) +void _exit( + int status +) { } diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c new file mode 100644 index 0000000000..4cdf5acf35 --- /dev/null +++ b/cpukit/libcsupport/src/open.c @@ -0,0 +1,202 @@ +/* + * open() - POSIX 1003.1 5.3.1 - Open a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.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 eitehr 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. + */ + +int open( + const char *pathname, + int flags, + ... +) +{ + va_list ap; + int mode; + int rc; + rtems_libio_t *iop = 0; + int status; + rtems_filesystem_location_info_t temp_loc; + int eval_flags; + + + /* + * 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; + + + va_start(ap, flags); + + mode = va_arg( ap, int ); + + /* + * 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; + } + + /* + * See if the file exists. + */ + + + status = rtems_filesystem_evaluate_path( pathname, eval_flags, &temp_loc, TRUE ); + + 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; + } + + /* Sanity check to see if the file name exists after the mknod() */ + status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_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; + goto done; + } + + /* + * Fill in the file control block based on the temp_loc structure + * returned by successful path evaluation. + */ + + iop->handlers = temp_loc.handlers; + iop->file_info = temp_loc.node_access; + iop->flags |= rtems_libio_fcntl_flags( flags ); + iop->pathinfo = temp_loc; + + if ( !iop->handlers->open ) { + rc = ENOTSUP; + goto done; + } + + rc = (*iop->handlers->open)( iop, pathname, flags, mode ); + if ( rc ) + goto done; + + /* + * Optionally truncate the file. + */ + + if ( (flags & O_TRUNC) == O_TRUNC ) { + rc = ftruncate( iop - rtems_libio_iops, 0 ); + } + + /* + * Single exit and clean up path. + */ + +done: + va_end(ap); + + if ( rc ) { + if ( iop ) + rtems_libio_free( iop ); + set_errno_and_return_minus_one( rc ); + } + return iop - rtems_libio_iops; +} + +/* + * _open_r + * + * This is the Newlib dependent reentrant version of open(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _open_r( + struct _reent *ptr, + const char *buf, + int flags, + int mode +) +{ + return open( buf, flags, mode ); +} +#endif diff --git a/cpukit/libcsupport/src/opendir.c b/cpukit/libcsupport/src/opendir.c index e303eb28e5..f0e9488684 100644 --- a/cpukit/libcsupport/src/opendir.c +++ b/cpukit/libcsupport/src/opendir.c @@ -1,17 +1,85 @@ /* * opendir() - POSIX 1003.1b - XXX * - * $Id$ + * This was copied from Newlib 1.8.0. + * + * + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91"; +#endif /* LIBC_SCCS and not lint */ + #include <dirent.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> -DIR *opendir( - const char *name -) +/* + * open a directory. + */ +DIR * +opendir(name) + const char *name; { - return NULL; + register DIR *dirp; + register int fd; + + if ((fd = open(name, 0)) == -1) + return NULL; + if (fcntl(fd, F_SETFD, 1) == -1 || + (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { + close (fd); + return NULL; + } + /* + * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE + * buffer that it cluster boundary aligned. + * Hopefully this can be a big win someday by allowing page trades + * to user space to be done by getdirentries() + */ + dirp->dd_buf = malloc (512); + dirp->dd_len = 512; + + if (dirp->dd_buf == NULL) { + close (fd); + return NULL; + } + dirp->dd_fd = fd; + dirp->dd_loc = 0; + dirp->dd_seek = 0; + /* + * Set up seek point for rewinddir. + */ + return dirp; } diff --git a/cpukit/libcsupport/src/pathconf.c b/cpukit/libcsupport/src/pathconf.c new file mode 100644 index 0000000000..e19d1329f4 --- /dev/null +++ b/cpukit/libcsupport/src/pathconf.c @@ -0,0 +1,38 @@ +/* + * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +long pathconf( + const char *path, + int name +) +{ + int status; + int fd; + + fd = open( path, O_RDONLY ); + if ( fd == -1 ) + return -1; + + status = fpathconf( fd, name ); + + (void) close( fd ); + + return status; +} diff --git a/cpukit/libcsupport/src/pipe.c b/cpukit/libcsupport/src/pipe.c new file mode 100644 index 0000000000..35dcf627bb --- /dev/null +++ b/cpukit/libcsupport/src/pipe.c @@ -0,0 +1,23 @@ +/* + * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> + +int pipe( + int filsdes[2] +) +{ + errno = ENOSYS; + return -1; +} diff --git a/cpukit/libcsupport/src/read.c b/cpukit/libcsupport/src/read.c new file mode 100644 index 0000000000..150fe675ab --- /dev/null +++ b/cpukit/libcsupport/src/read.c @@ -0,0 +1,84 @@ +/* + * read() - POSIX 1003.1b 6.4.1 - Read From a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + +/* XXX newlib has the prototype for this wrong. It will be a bit painful */ +/* XXX to fix so we are choosing to delay fixing this. */ + +int read( + int fd, + void *buffer, + unsigned32 count +) +{ + int rc; /* XXX change to a size_t when prototype is fixed */ + rtems_libio_t *iop; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if ( rtems_file_descriptor_type( fd ) ) { + rtems_libio_read_t fp; + + fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].read; + if ( fp == NULL ) + set_errno_and_return_minus_one( EBADF ); + + return (*fp)( fd, buffer, count ); + } + + /* + * Now process the read(). + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + rtems_libio_check_buffer( buffer ); + rtems_libio_check_count( count ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ ); + + if ( !iop->handlers->read ) + set_errno_and_return_minus_one( ENOTSUP ); + + rc = (*iop->handlers->read)( iop, buffer, count ); + + if ( rc > 0 ) + iop->offset += rc; + + return rc; +} + +/* + * _read_r + * + * This is the Newlib dependent reentrant version of read(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +_ssize_t _read_r( + struct _reent *ptr, + int fd, + void *buf, + size_t nbytes +) +{ + return read( fd, buf, nbytes ); +} +#endif diff --git a/cpukit/libcsupport/src/readdir.c b/cpukit/libcsupport/src/readdir.c index d592a62b99..f950d56171 100644 --- a/cpukit/libcsupport/src/readdir.c +++ b/cpukit/libcsupport/src/readdir.c @@ -1,14 +1,77 @@ /* * readdir() - POSIX 1003.1b - XXX * - * $Id$ + * This was copied from Newlib 1.8.0. + * + * + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + #include <dirent.h> -struct dirent *readdir( - register DIR *dirp -) -{ - return NULL; +/* + * get next entry in a directory. + */ +struct dirent * +readdir(dirp) +register DIR *dirp; { + register struct dirent *dp; + + for (;;) { + if (dirp->dd_loc == 0) { + dirp->dd_size = getdents (dirp->dd_fd, + dirp->dd_buf, + dirp->dd_len); + + if (dirp->dd_size <= 0) + return NULL; + } + if (dirp->dd_loc >= dirp->dd_size) { + dirp->dd_loc = 0; + continue; + } + dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); + if ((int)dp & 03) /* bogus pointer check */ + return NULL; + if (dp->d_reclen <= 0 || + dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) + return NULL; + dirp->dd_loc += dp->d_reclen; + if (dp->d_ino == 0) + continue; + return (dp); + } } diff --git a/cpukit/libcsupport/src/readlink.c b/cpukit/libcsupport/src/readlink.c new file mode 100644 index 0000000000..22de51e88f --- /dev/null +++ b/cpukit/libcsupport/src/readlink.c @@ -0,0 +1,43 @@ +/* + * readlink() - POSIX 1003.1b - X.X.X - XXX + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + +int readlink( + const char *pathname, + char *buf, + int bufsize +) +{ + rtems_filesystem_location_info_t loc; + int result; + + result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE ); + if ( result != 0 ) + return -1; + + if (!buf) + set_errno_and_return_minus_one( EFAULT ); + + if ( !loc.ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK ) + set_errno_and_return_minus_one( EINVAL ); + + if ( !loc.ops->readlink ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*loc.ops->readlink)( &loc, buf, bufsize ); +} diff --git a/cpukit/libcsupport/src/rewinddir.c b/cpukit/libcsupport/src/rewinddir.c index c85e6fd4d0..04313a6042 100644 --- a/cpukit/libcsupport/src/rewinddir.c +++ b/cpukit/libcsupport/src/rewinddir.c @@ -1,7 +1,14 @@ /* * rewinddir() - POSIX 1003.1b - XXX * - * $Id$ + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * */ #include <sys/types.h> @@ -15,6 +22,14 @@ void rewinddir( DIR *dirp ) { - errno = ENOSYS; - return -1; + off_t status; + + status = lseek( dirp->dd_fd, 0, SEEK_SET ); + + if( status == -1 ) + return; + + dirp->dd_loc = 0; + + } diff --git a/cpukit/libcsupport/src/rmdir.c b/cpukit/libcsupport/src/rmdir.c new file mode 100644 index 0000000000..6c0331087f --- /dev/null +++ b/cpukit/libcsupport/src/rmdir.c @@ -0,0 +1,56 @@ +/* + * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> + +#include "libio_.h" + +int rmdir( + const char *pathname +) +{ + rtems_filesystem_location_info_t loc; + int result; + + /* + * Get the node where we wish to go. + */ + + result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE ); + if ( result != 0 ) + return -1; + + /* + * Verify you can remove this node as a directory. + */ + + if ( !loc.ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * Use the filesystems rmnod to remove the node. + */ + + if ( !loc.ops->rmnod ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*loc.ops->rmnod)( &loc ); +} diff --git a/cpukit/libcsupport/src/scandir.c b/cpukit/libcsupport/src/scandir.c index 380415dd97..9ba1cb7bec 100644 --- a/cpukit/libcsupport/src/scandir.c +++ b/cpukit/libcsupport/src/scandir.c @@ -1,7 +1,50 @@ /* * scandir() - POSIX 1003.1b - XXX * - * $Id$ + * This was copied from Newlib 1.8.0. + * + * + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Scan the directory dirname calling select to make a list of selected + * directory entries then sort using qsort and compare routine dcomp. + * Returns the number of entries and a pointer to a list of pointers to + * struct dirent (through namelist). Returns -1 if there were any errors. */ #include <sys/types.h> @@ -9,15 +52,98 @@ #include <dirent.h> #include <stdlib.h> #include <string.h> -#include <errno.h> - -int scandir( - const char *dirname, - struct dirent ***namelist, - int (*select)(struct dirent *), - int (*dcomp)(const void *, const void *) -) + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct dirent + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#undef DIRSIZ +/* +#define DIRSIZ(dp) \ + ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) +*/ + +#define DIRSIZ(dp) \ + ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) + +#ifndef __P +#define __P(args) () +#endif + +int +scandir(dirname, namelist, select, dcomp) + const char *dirname; + struct dirent ***namelist; + int (*select) __P((struct dirent *)); + int (*dcomp) __P((const void *, const void *)); +{ + register struct dirent *d, *p, **names; + register size_t nitems; + struct stat stb; + long arraysz; + DIR *dirp; + + if ((dirp = opendir(dirname)) == NULL) + return(-1); + if (fstat(dirp->dd_fd, &stb) < 0) + return(-1); + + /* + * estimate the array size by taking the size of the directory file + * and dividing it by a multiple of the minimum size entry. + */ + arraysz = (stb.st_size / 24); + names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); + if (names == NULL) + return(-1); + + nitems = 0; + while ((d = readdir(dirp)) != NULL) { + if (select != NULL && !(*select)(d)) + continue; /* just selected names */ + /* + * Make a minimum size copy of the data + */ + p = (struct dirent *)malloc(DIRSIZ(d)); + if (p == NULL) + return(-1); + p->d_ino = d->d_ino; + p->d_reclen = d->d_reclen; + p->d_namlen = d->d_namlen; + bcopy(d->d_name, p->d_name, p->d_namlen + 1); + /* + * Check to make sure the array has space left and + * realloc the maximum size. + */ + if (++nitems >= arraysz) { + if (fstat(dirp->dd_fd, &stb) < 0) + return(-1); /* just might have grown */ + arraysz = stb.st_size / 12; + names = (struct dirent **)realloc((char *)names, + arraysz * sizeof(struct dirent *)); + if (names == NULL) + return(-1); + } + names[nitems-1] = p; + } + closedir(dirp); + if (nitems && dcomp != NULL){ + qsort(names, nitems, sizeof(struct dirent *), dcomp); + } + *namelist = names; + return(nitems); +} + +/* + * Alphabetic order comparison routine for those who want it. + */ +int +alphasort(d1, d2) + const void *d1; + const void *d2; { - errno = ENOSYS; - return -1; + return(strcmp((*(struct dirent **)d1)->d_name, + (*(struct dirent **)d2)->d_name)); } diff --git a/cpukit/libcsupport/src/seekdir.c b/cpukit/libcsupport/src/seekdir.c index e591adbb9f..80802b56c6 100644 --- a/cpukit/libcsupport/src/seekdir.c +++ b/cpukit/libcsupport/src/seekdir.c @@ -1,7 +1,14 @@ /* * seekdir() - POSIX 1003.1b - XXX * - * $Id$ + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * */ #include <sys/param.h> @@ -12,10 +19,20 @@ #include <errno.h> void seekdir( - DIR *dirp, - long loc + DIR *dirp, + long loc ) { - errno = ENOSYS; - return -1; + off_t status; + + status = lseek( dirp->dd_fd, loc, SEEK_SET ); + + /* + * This is not a nice way to error out, but we have no choice here. + */ + if( status == -1 ) + return; + + dirp->dd_loc = 0; + } diff --git a/cpukit/libcsupport/src/stat.c b/cpukit/libcsupport/src/stat.c new file mode 100644 index 0000000000..8ad7e61511 --- /dev/null +++ b/cpukit/libcsupport/src/stat.c @@ -0,0 +1,79 @@ +/* + * stat() - POSIX 1003.1b 5.6.2 - Get File Status + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> + +#if !defined(RTEMS_UNIX) + +#include <rtems/libio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include "libio_.h" + +int stat( + const char *path, + struct stat *buf +) +{ + int status; + rtems_filesystem_location_info_t loc; + + /* + * Check to see if we were passed a valid pointer. + */ + + if ( !buf ) + set_errno_and_return_minus_one( EFAULT ); + + status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE ); + if ( status != 0 ) + return -1; + + if ( !loc.handlers->fstat ) + set_errno_and_return_minus_one( ENOTSUP ); + + /* + * Zero out the stat structure so the various support + * versions of stat don't have to. + */ + + memset( buf, 0, sizeof(struct stat) ); + + return (*loc.handlers->fstat)( &loc, buf ); +} +#endif + +/* + * _stat_r + * + * This is the Newlib dependent reentrant version of stat(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _stat_r( + struct _reent *ptr, + const char *path, + struct stat *buf +) +{ + return stat( path, buf ); +} +#endif diff --git a/cpukit/libcsupport/src/symlink.c b/cpukit/libcsupport/src/symlink.c new file mode 100644 index 0000000000..ca9673f51b --- /dev/null +++ b/cpukit/libcsupport/src/symlink.c @@ -0,0 +1,34 @@ +/* + * symlink() - POSIX 1003.1b - X.X.X - XXX + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + +int symlink( + const char *actualpath, + const char *sympath +) +{ + rtems_filesystem_location_info_t loc; + int i; + const char *name_start; + int result; + + rtems_filesystem_get_start_loc( sympath, &i, &loc ); + result = (*loc.ops->evalformake)( &sympath[i], &loc, &name_start ); + if ( result != 0 ) + return -1; + + return (*loc.ops->symlink)( &loc, actualpath, name_start); +} + diff --git a/cpukit/libcsupport/src/tcdrain.c b/cpukit/libcsupport/src/tcdrain.c index 585871cc90..c2749a90e1 100644 --- a/cpukit/libcsupport/src/tcdrain.c +++ b/cpukit/libcsupport/src/tcdrain.c @@ -1,9 +1,15 @@ /* - * This file contains the RTEMS implementation of the POSIX API - * routines tcdrain. + * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions * - * $Id$ + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. * + * $Id$ */ #include <rtems.h> @@ -13,14 +19,15 @@ #include <sys/stat.h> #include <errno.h> #include <termios.h> +#include <sys/ioctl.h> -#include "internal.h" #include "libio.h" -int -tcdrain(int fd) +int tcdrain( + int fd +) { - return __rtems_ioctl(fd,RTEMS_IO_TCDRAIN,0); + return ioctl( fd, RTEMS_IO_TCDRAIN, 0 ); } #endif diff --git a/cpukit/libcsupport/src/tcgetattr.c b/cpukit/libcsupport/src/tcgetattr.c new file mode 100644 index 0000000000..2d3e4d7e3c --- /dev/null +++ b/cpukit/libcsupport/src/tcgetattr.c @@ -0,0 +1,33 @@ +/* + * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if defined(RTEMS_NEWLIB) + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <termios.h> +#include <sys/ioctl.h> + +#include "libio.h" + +int tcgetattr( + int fd, + struct termios *tp +) +{ + return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp ); +} +#endif diff --git a/cpukit/libcsupport/src/tcsetattr.c b/cpukit/libcsupport/src/tcsetattr.c new file mode 100644 index 0000000000..c0ed509a0f --- /dev/null +++ b/cpukit/libcsupport/src/tcsetattr.c @@ -0,0 +1,38 @@ +/* + * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#if defined(RTEMS_NEWLIB) + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <termios.h> +#include <sys/ioctl.h> + +#include "libio.h" +#include "libio_.h" + +int tcsetattr( + int fd, + int opt, + struct termios *tp +) +{ + if ( opt != TCSANOW ) + set_errno_and_return_minus_one( ENOTSUP ); + + return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp ); +} +#endif diff --git a/cpukit/libcsupport/src/telldir.c b/cpukit/libcsupport/src/telldir.c index eee8d925ec..cea6cc08cb 100644 --- a/cpukit/libcsupport/src/telldir.c +++ b/cpukit/libcsupport/src/telldir.c @@ -1,7 +1,14 @@ /* * telldir() - XXX * - * $Id$ + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * */ #include <sys/param.h> @@ -9,15 +16,24 @@ #include <dirent.h> #include <stdlib.h> #include <unistd.h> -#include <errno.h> -#include <rtems.h> -#include "libio.h" +#include "libio_.h" + long telldir( DIR *dirp ) { - errno = ENOSYS; - return -1; + rtems_libio_t *iop; + + /* + * Get the file control block structure associated with the file descriptor + */ + + iop = rtems_libio_iop( dirp->dd_fd ); + + if (iop == NULL) + assert(0); + + return (long)( iop->offset ); } diff --git a/cpukit/libcsupport/src/truncate.c b/cpukit/libcsupport/src/truncate.c new file mode 100644 index 0000000000..145e596654 --- /dev/null +++ b/cpukit/libcsupport/src/truncate.c @@ -0,0 +1,41 @@ +/* + * truncate() - Truncate a File to the Specified Length + * + * This routine is not defined in the POSIX 1003.1b standard but is + * commonly supported on most UNIX and POSIX systems. It is provided + * for compatibility. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +int truncate( + const char *path, + off_t length +) +{ + int status; + int fd; + + fd = open( path, O_WRONLY ); + if ( fd == -1 ) + return -1; + + status = ftruncate( fd, length ); + + (void) close( fd ); + + return status; +} + diff --git a/cpukit/libcsupport/src/umask.c b/cpukit/libcsupport/src/umask.c new file mode 100644 index 0000000000..35229a30a1 --- /dev/null +++ b/cpukit/libcsupport/src/umask.c @@ -0,0 +1,30 @@ +/* + * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include "libio_.h" + +mode_t umask( + mode_t cmask +) +{ + mode_t old_mask; + + old_mask = rtems_filesystem_umask; + rtems_filesystem_umask = cmask; + + return old_mask; +} diff --git a/cpukit/libcsupport/src/unixlibc.c b/cpukit/libcsupport/src/unixlibc.c index 3e757e313d..a581d95534 100644 --- a/cpukit/libcsupport/src/unixlibc.c +++ b/cpukit/libcsupport/src/unixlibc.c @@ -1,5 +1,15 @@ /* * $Id$ + * UNIX Port C Library Support + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * */ #include <rtems.h> diff --git a/cpukit/libcsupport/src/unlink.c b/cpukit/libcsupport/src/unlink.c new file mode 100644 index 0000000000..d4a5520bcb --- /dev/null +++ b/cpukit/libcsupport/src/unlink.c @@ -0,0 +1,44 @@ +/* + * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> + +#include "libio_.h" + +int unlink( + const char *path +) +{ + rtems_filesystem_location_info_t loc; + int result; + + /* + * Get the node to be unlinked. + */ + + result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE ); + if ( result != 0 ) + return -1; + + if ( !loc.ops->node_type ) + set_errno_and_return_minus_one( ENOTSUP ); + + if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) + set_errno_and_return_minus_one( EISDIR ); + + if ( !loc.ops->unlink ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*loc.ops->unlink)( &loc ); +} diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c new file mode 100644 index 0000000000..f50e63ff42 --- /dev/null +++ b/cpukit/libcsupport/src/unmount.c @@ -0,0 +1,214 @@ +/* + * unmount() - Unmount a File System + * + * This routine is not defined in the POSIX 1003.1b standard but + * in some form is supported on most UNIX and POSIX systems. This + * routine is necessary to mount instantiations of a file system + * into the file system name space. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <chain.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "imfs.h" +#include "libio_.h" + +/* + * Data structures and routines private to mount/unmount pair. + */ + +extern Chain_Control rtems_filesystem_mount_table_control; +extern rtems_filesystem_location_info_t rtems_filesystem_current; + +int search_mt_for_mount_point( + rtems_filesystem_location_info_t *location_of_mount_point +); + + +int file_systems_below_this_mountpoint( + const char *mount_path, + rtems_filesystem_location_info_t *temp_loc, + rtems_filesystem_mount_table_entry_t *temp_mt_entry +); + +/* + * unmount + * + * This routine will attempt to unmount the file system that has been + * is mounted a mount_path. If the operation is successful, 0 will + * be returned to the calling routine. Otherwise, 1 will be returned. + */ + +int unmount( + const char *mount_path +) +{ + int status; + rtems_filesystem_location_info_t temp_loc; + rtems_filesystem_mount_table_entry_t temp_mt_entry; + int result; + + /* + * Are there any file systems below the mount_path specified + */ + + status = file_systems_below_this_mountpoint( + mount_path, + &temp_loc, + &temp_mt_entry + ); + + if ( status != 0 ) + return -1; + + /* + * Is the current node reference pointing to a node in the file system + * we are attempting to unmount ? + */ + + if ( rtems_filesystem_current.mt_entry == temp_loc.mt_entry ) + set_errno_and_return_minus_one( EBUSY ); + + /* + * Run the file descriptor table to determine if there are any file + * descriptors that are currently active and reference nodes in the + * file system that we are trying to unmount + */ + + if ( rtems_libio_is_open_files_in_fs( temp_loc.mt_entry ) == 1 ) + set_errno_and_return_minus_one( EBUSY ); + + /* + * Allow the file system being mounted on to do its cleanup. + * XXX - Did I change these correctly ??? It looks like either I did + * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped. + * XXX Add to the mt_point_node unmount to set the mt_entry back to null + * XXX I will step off in space when evaluating past the end of the node. + */ + + if ( ( temp_mt_entry.mt_point_node.ops->unmount )( temp_loc.mt_entry ) != 0 ) + return -1; + + /* + * Run the unmount function for the subordinate file system. + */ + + if ( ( temp_mt_entry.mt_fs_root.ops->fsunmount_me )( temp_loc.mt_entry ) != 0 ) + return -1; + + /* + * Allow the file system to clean up. + */ + + result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry ); + + /* + * Extract the mount table entry from the chain + */ + + Chain_Extract( ( Chain_Node * ) temp_loc.mt_entry ); + + /* + * Free the memory associated with the extracted mount table entry. + */ + + free( temp_loc.mt_entry ); + + return result; + +} + + +/* + * file_systems_below_this_mountpoint + * + * This routine will run through the entries that currently exist in the + * mount table chain. For each entry in the mount table chain it will + * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the + * mount table file system root nodes matches the new file system root node + * this indicates that we are trying to mount a file system that has already + * been mounted. This is not a permitted operation. temp_loc is set to + * the root node of the file system being unmounted. + */ + +int file_systems_below_this_mountpoint( + const char *mount_path, + rtems_filesystem_location_info_t *temp_loc, + rtems_filesystem_mount_table_entry_t *temp_mt_entry +) +{ + Chain_Node *the_node; + rtems_filesystem_mount_table_entry_t *the_mount_entry; + rtems_filesystem_mount_table_entry_t *current_fs_mt_entry; + + /* + * Is the mount_path even a valid node name in the existing tree? + */ + + if ( rtems_filesystem_evaluate_path( mount_path, 0x0, temp_loc, TRUE ) ) + return -1; + + /* + * Look for the node defined in temp_loc as a mount point in the + * mount table chain. + */ + + for ( the_node = rtems_filesystem_mount_table_control.first; + !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node ); + the_node = the_node->next ) { + + the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node; + if (the_mount_entry->mt_point_node.node_access == + temp_loc->node_access ) { + current_fs_mt_entry = the_mount_entry; + *temp_loc = current_fs_mt_entry->mt_fs_root; + goto after_real_mount_point_found; + } + } + set_errno_and_return_minus_one( EACCES ); + + +after_real_mount_point_found: + + for ( the_node = rtems_filesystem_mount_table_control.first; + !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node ); + the_node = the_node->next ) { + + the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node; + + /* + * Exclude the current file systems mount table entry from the test + */ + + if ( current_fs_mt_entry != the_mount_entry ) { + if ( the_mount_entry->mt_point_node.mt_entry == current_fs_mt_entry ) { + + /* + * There is at least one fs below the fs on the mount_path. + */ + set_errno_and_return_minus_one( EBUSY ); + } + } + } + + *temp_mt_entry = *current_fs_mt_entry; + + return 0; +} diff --git a/cpukit/libcsupport/src/utime.c b/cpukit/libcsupport/src/utime.c new file mode 100644 index 0000000000..f1a12ee1b2 --- /dev/null +++ b/cpukit/libcsupport/src/utime.c @@ -0,0 +1,35 @@ +/* + * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <utime.h> +#include <errno.h> + +#include "libio_.h" + +int utime( + const char *path, + const struct utimbuf *times +) +{ + rtems_filesystem_location_info_t temp_loc; + + if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) ) + return -1; + + if ( !temp_loc.ops->utime ) + set_errno_and_return_minus_one( ENOTSUP ); + + return (*temp_loc.ops->utime)( &temp_loc, times->actime, times->modtime ); +} diff --git a/cpukit/libcsupport/src/write.c b/cpukit/libcsupport/src/write.c new file mode 100644 index 0000000000..7e0953bb90 --- /dev/null +++ b/cpukit/libcsupport/src/write.c @@ -0,0 +1,92 @@ +/* + * write() - POSIX 1003.1b 6.4.2 - Write to a File + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include "libio_.h" + + +/* + * write + * + * This routine writes count bytes from from buffer pointed to by buffer + * to the file associated with the open file descriptor, fildes. + */ + +/* XXX newlib has the prototype for this wrong. It will be a bit painful */ +/* XXX to fix so we are choosing to delay fixing this. */ + +int write( /* XXX this should return a ssize_t */ + int fd, + const void *buffer, + unsigned32 count /* XXX this should be a size_t */ +) +{ + rtems_status_code rc; + rtems_libio_t *iop; + + /* + * If this file descriptor is mapped to an external set of handlers, + * then pass the request on to them. + */ + + if ( rtems_file_descriptor_type( fd ) ) { + rtems_libio_write_t fp; + + fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].write; + if ( fp == NULL ) + set_errno_and_return_minus_one( EBADF ); + + return (*fp)( fd, buffer, count ); + } + + /* + * Now process the write() request. + */ + + iop = rtems_libio_iop( fd ); + rtems_libio_check_fd( fd ); + rtems_libio_check_buffer( buffer ); + rtems_libio_check_count( count ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + + if ( !iop->handlers->write ) + set_errno_and_return_minus_one( ENOTSUP ); + + rc = (*iop->handlers->write)( iop, buffer, count ); + + if ( rc > 0 ) + iop->offset += rc; + + return rc; +} + +/* + * _write_r + * + * This is the Newlib dependent reentrant version of write(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +long _write_r( + struct _reent *ptr, + int fd, + const void *buf, + size_t nbytes +) +{ + return write( fd, buf, nbytes ); +} +#endif diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c new file mode 100644 index 0000000000..f954decf6e --- /dev/null +++ b/cpukit/libfs/src/imfs/deviceio.c @@ -0,0 +1,215 @@ +/* + * IMFS Device Node Handlers + * + * This file contains the set of handlers used to map operations on + * IMFS device nodes onto calls to the RTEMS Classic API IO Manager. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <rtems/libio.h> + +#include "imfs.h" + +/* + * device_open + * + * This handler maps an open() operation onto rtems_io_open(). + */ + +int device_open( + rtems_libio_t *iop, + const char *pathname, + unsigned32 flag, + unsigned32 mode +) +{ + rtems_libio_open_close_args_t args; + rtems_status_code status; + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + args.iop = iop; + args.flags = iop->flags; + args.mode = mode; + + status = rtems_io_open( + the_jnode->info.device.major, + the_jnode->info.device.minor, + (void *) &args + ); + if ( status ) + return RTEMS_UNSATISFIED; + + return 0; +} + +/* + * device_close + * + * This handler maps a close() operation onto rtems_io_close(). + */ + +int device_close( + rtems_libio_t *iop +) +{ + rtems_libio_open_close_args_t args; + rtems_status_code status; + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + args.iop = iop; + args.flags = 0; + args.mode = 0; + + status = rtems_io_close( + the_jnode->info.device.major, + the_jnode->info.device.minor, + (void *) &args + ); + if ( status ) + return RTEMS_UNSATISFIED; + + return 0; +} + +/* + * device_read + * + * This handler maps a read() operation onto rtems_io_read(). + */ + +int device_read( + rtems_libio_t *iop, + void *buffer, + unsigned32 count +) +{ + rtems_libio_rw_args_t args; + rtems_status_code status; + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + args.iop = iop; + args.offset = iop->offset; + args.buffer = buffer; + args.count = count; + args.flags = iop->flags; + args.bytes_moved = 0; + + status = rtems_io_read( + the_jnode->info.device.major, + the_jnode->info.device.minor, + (void *) &args + ); + + if ( status ) + return -1; + + return args.bytes_moved; +} + +/* + * device_write + * + * This handler maps a write() operation onto rtems_io_write(). + */ + +int device_write( + rtems_libio_t *iop, + const void *buffer, + unsigned32 count +) +{ + rtems_libio_rw_args_t args; + rtems_status_code status; + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + args.iop = iop; + args.offset = iop->offset; + args.buffer = (void *) buffer; + args.count = count; + args.flags = iop->flags; + args.bytes_moved = 0; + + status = rtems_io_write( + the_jnode->info.device.major, + the_jnode->info.device.minor, + (void *) &args + ); + + if ( status ) + return -1; + + return args.bytes_moved; +} + +/* + * device_ioctl + * + * This handler maps an ioctl() operation onto rtems_io_ioctl(). + */ + +int device_ioctl( + rtems_libio_t *iop, + unsigned32 command, + void *buffer +) +{ + rtems_libio_ioctl_args_t args; + rtems_status_code status; + IMFS_jnode_t *the_jnode; + + args.iop = iop; + args.command = command; + args.buffer = buffer; + + the_jnode = iop->file_info; + + status = rtems_io_control( + the_jnode->info.device.major, + the_jnode->info.device.minor, + (void *) &args + ); + + if ( status ) + return -1; + + return args.ioctl_return; +} + +/* + * device_lseek + * + * This handler eats all lseek() operations. + */ + +int device_lseek( + rtems_libio_t *iop, + off_t offset, + int whence +) +{ + return 0; +} + +/* + * device_stat + * + * This IMFS_stat() is used. + */ diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h new file mode 100644 index 0000000000..6eb535527d --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs.h @@ -0,0 +1,445 @@ +/* + * Header file for the In-Memory File System + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef __IMFS_h +#define __IMFS_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems.h> +#include <chain.h> + +#include <sys/types.h> +#include <limits.h> +#include <rtems/libio.h> + +/* + * File name macros + */ + +#define IMFS_is_valid_name_char( _ch ) ( 1 ) + +#define IMFS_is_separator( _ch ) \ + rtems_filesystem_is_separator( _ch ) + +/* + * Data types + */ + +struct IMFS_jnode_tt; +typedef struct IMFS_jnode_tt IMFS_jnode_t; + +typedef struct { + Chain_Control Entries; + rtems_filesystem_mount_table_entry_t *mt_fs; +} IMFS_directory_t; + +typedef struct { + rtems_device_major_number major; + rtems_device_minor_number minor; +} IMFS_device_t; + +typedef struct { + IMFS_jnode_t *link_node; +} IMFS_link_t; + +typedef struct { + const char *name; +} IMFS_sym_link_t; + +/* + * IMFS "memfile" information + * + * The data structure for the in-memory "memfiles" is based on classic UNIX. + * + * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in + * length which could be data or a table of pointers to blocks. + */ + +#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */ +#define IMFS_MEMFILE_BLOCK_SLOTS \ + (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *)) + +typedef unsigned char * block_p; +typedef block_p *block_ptr; + +typedef struct { + off_t size; /* size of file in bytes */ + block_ptr indirect; /* array of 128 data blocks pointers */ + block_ptr doubly_indirect; /* 128 indirect blocks */ + block_ptr triply_indirect; /* 128 doubly indirect blocks */ +} IMFS_memfile_t; + +/* + * Important block numbers for "memfiles" + */ + +#define FIRST_INDIRECT (0) +#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1) + +#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1) +#define LAST_DOUBLY_INDIRECT \ + (LAST_INDIRECT + \ + (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS)) + +#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1) +#define LAST_TRIPLY_INDIRECT \ + (LAST_DOUBLY_INDIRECT +\ + (IMFS_MEMFILE_BLOCK_SLOTS * \ + IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS)) + +#define IMFS_MEMFILE_MAXIMUM_SIZE \ + (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK) + +/* + * What types of IMFS file systems entities there can be. + */ + +#define IMFS_jnode_types_t rtems_filesystem_node_types_t +#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY +#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE +#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK +#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK +#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE + +#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1) + +typedef union { + IMFS_directory_t directory; + IMFS_device_t device; + IMFS_link_t hard_link; + IMFS_sym_link_t sym_link; + IMFS_memfile_t file; +} IMFS_types_union; + +/* + * The control structure for an IMFS jnode. + */ + +struct IMFS_jnode_tt { + Chain_Node Node; /* for chaining them together */ + IMFS_jnode_t *Parent; /* Parent node */ + char name[NAME_MAX+1]; /* "basename" */ + mode_t st_mode; /* File mode */ + nlink_t st_nlink; /* Link count */ + ino_t st_ino; /* inode */ + + uid_t st_uid; /* User ID of owner */ + gid_t st_gid; /* Group ID of owner */ + + time_t st_atime; /* Time of last access */ + time_t st_mtime; /* Time of last modification */ + time_t st_ctime; /* Time of last status change */ + IMFS_jnode_types_t type; /* Type of this entry */ + IMFS_types_union info; +}; + +#define IMFS_update_atime( _jnode ) \ + do { \ + struct timeval tv; \ + gettimeofday( &tv, 0 ); \ + _jnode->st_atime = (time_t) tv.tv_sec; \ + } while (0) + +#define IMFS_update_mtime( _jnode ) \ + do { \ + struct timeval tv; \ + gettimeofday( &tv, 0 ); \ + _jnode->st_mtime = (time_t) tv.tv_sec; \ + } while (0) + +#define IMFS_update_ctime( _jnode ) \ + do { \ + struct timeval tv; \ + gettimeofday( &tv, 0 ); \ + _jnode->st_ctime = (time_t) tv.tv_sec; \ + } while (0) + +#define IMFS_atime_mtime_update( _jnode ) \ + do { \ + struct timeval tv; \ + gettimeofday( &tv, 0 ); \ + _jnode->st_mtime = (time_t) tv.tv_sec; \ + _jnode->st_atime = (time_t) tv.tv_sec; \ + } while (0) + +typedef struct { + ino_t ino_count; +} IMFS_fs_info_t; + +#define increment_and_check_linkcounts( _fs_info ) \ + ((IMFS_fs_info_t * )_fs_info)->link_counts++; \ + if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \ + set_errno_and_return_minus_one( ELOOP ) + +#define decrement_linkcounts( _fs_info ) \ + ((IMFS_fs_info_t * )_fs_info)->link_counts--; + +/* + * Type defination for tokens returned from IMFS_get_token + */ + +typedef enum { + IMFS_NO_MORE_PATH, + IMFS_CURRENT_DIR, + IMFS_UP_DIR, + IMFS_NAME, + IMFS_INVALID_TOKEN +} IMFS_token_types; + +/* + * Shared Data + */ + +extern rtems_filesystem_file_handlers_r device_handlers; +extern rtems_filesystem_file_handlers_r memfile_handlers; +extern rtems_filesystem_file_handlers_r dir_handlers; +extern rtems_filesystem_file_handlers_r null_handlers; +extern rtems_filesystem_operations_table IMFS_ops; +extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS; + +/* + * Routines + */ + +int IMFS_initialize( + rtems_filesystem_mount_table_entry_t *mt_entry +); + +int IMFS_fsunmount( + rtems_filesystem_mount_table_entry_t *mt_entry +); + + +/* + * Returns the number of characters copied from path to token. + */ +IMFS_token_types IMFS_get_token( + const char *path, + char *token, + int *token_len +); + +void IMFS_dump( void ); + +void IMFS_initialize_jnode( + IMFS_jnode_t *the_jnode, + IMFS_jnode_types_t type, + IMFS_jnode_t *the_parent, + char *name, + mode_t mode +); + +IMFS_jnode_t *IMFS_find_match_in_dir( + IMFS_jnode_t *directory, /* IN */ + char *name /* IN */ +); + +rtems_filesystem_node_types_t IMFS_node_type( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +int IMFS_stat( + rtems_filesystem_location_info_t *loc, /* IN */ + struct stat *buf /* OUT */ +); + +int IMFS_evaluate_link( + rtems_filesystem_location_info_t *node, /* IN/OUT */ + int flags /* IN */ +); + +int IMFS_eval_path( + const char *pathname, /* IN */ + int flags, /* IN */ + rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +); + + +int IMFS_link( + rtems_filesystem_location_info_t *to_loc, /* IN */ + rtems_filesystem_location_info_t *parent_loc, /* IN */ + const char *token /* IN */ +); + +int IMFS_unlink( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +int IMFS_chown( + rtems_filesystem_location_info_t *pathloc, /* IN */ + uid_t owner, /* IN */ + gid_t group /* IN */ +); + +int IMFS_freenodinfo( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +int IMFS_rmnod( + rtems_filesystem_location_info_t *pathloc /* IN */ +); + +int IMFS_mknod( + const char *path, /* IN */ + mode_t mode, /* IN */ + dev_t dev, /* IN */ + rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +); + +IMFS_jnode_t *IMFS_create_node( + rtems_filesystem_location_info_t *parent_loc, /* IN */ + IMFS_jnode_types_t type, /* IN */ + char *name, /* IN */ + mode_t mode, /* IN */ + IMFS_types_union *info /* IN */ +); + +int IMFS_evaluate_for_make( + const char *path, /* IN */ + rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ + const char **name /* OUT */ +); + +int IMFS_mount( + rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ +); + +int IMFS_unmount( + rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ +); + +int IMFS_freenod( + rtems_filesystem_location_info_t *node /* IN/OUT */ +); + +int IMFS_memfile_remove( + IMFS_jnode_t *the_jnode /* IN/OUT */ +); + +int memfile_ftruncate( + rtems_libio_t *iop, /* IN */ + off_t length /* IN */ +); +int imfs_dir_open( + rtems_libio_t *iop, /* IN */ + const char *pathname, /* IN */ + unsigned32 flag, /* IN */ + unsigned32 mode /* IN */ +); +int imfs_dir_close( + rtems_libio_t *iop /* IN */ +); +int imfs_dir_read( + rtems_libio_t *iop, /* IN */ + void *buffer, /* IN */ + unsigned32 count /* IN */ +); +int imfs_dir_lseek( + rtems_libio_t *iop, /* IN */ + off_t offset, /* IN */ + int whence /* IN */ +); +int imfs_dir_fstat( + rtems_filesystem_location_info_t *loc, /* IN */ + struct stat *buf /* OUT */ +); +int memfile_open( + rtems_libio_t *iop, /* IN */ + const char *pathname, /* IN */ + unsigned32 flag, /* IN */ + unsigned32 mode /* IN */ +); +int memfile_close( + rtems_libio_t *iop /* IN */ +); +int memfile_read( + rtems_libio_t *iop, /* IN */ + void *buffer, /* IN */ + unsigned32 count /* IN */ +); +int memfile_write( + rtems_libio_t *iop, /* IN */ + const void *buffer, /* IN */ + unsigned32 count /* IN */ +); +int memfile_ioctl( + rtems_libio_t *iop, /* IN */ + unsigned32 command, /* IN */ + void *buffer /* IN */ +); +int memfile_lseek( + rtems_libio_t *iop, /* IN */ + off_t offset, /* IN */ + int whence /* IN */ +); +int device_open( + rtems_libio_t *iop, /* IN */ + const char *pathname, /* IN */ + unsigned32 flag, /* IN */ + unsigned32 mode /* IN */ +); +int device_close( + rtems_libio_t *iop /* IN */ +); +int device_read( + rtems_libio_t *iop, /* IN */ + void *buffer, /* IN */ + unsigned32 count /* IN */ +); +int device_write( + rtems_libio_t *iop, /* IN */ + const void *buffer, /* IN */ + unsigned32 count /* IN */ +); +int device_ioctl( + rtems_libio_t *iop, /* IN */ + unsigned32 command, /* IN */ + void *buffer /* IN */ +); +int device_lseek( + rtems_libio_t *iop, /* IN */ + off_t offset, /* IN */ + int whence /* IN */ +); +int IMFS_utime( + rtems_filesystem_location_info_t *pathloc, /* IN */ + time_t actime, /* IN */ + time_t modtime /* IN */ +); +int IMFS_fchmod( + rtems_filesystem_location_info_t *loc, + mode_t mode +); + +int IMFS_symlink( + rtems_filesystem_location_info_t *parent_loc, /* IN */ + const char *link_name, + const char *node_name +); + +int IMFS_readlink( + rtems_filesystem_location_info_t *loc, /* IN */ + char *buf, /* OUT */ + size_t bufsize +); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/libfs/src/imfs/imfs_chown.c b/cpukit/libfs/src/imfs/imfs_chown.c new file mode 100644 index 0000000000..816294ee34 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_chown.c @@ -0,0 +1,52 @@ +/* + * IMFS_chown + * + * This routine is the implementation of the chown() system + * call for the IMFS. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "libio_.h" +#include "imfs.h" + +int IMFS_chown( + rtems_filesystem_location_info_t *pathloc, /* IN */ + uid_t owner, /* IN */ + gid_t group /* IN */ +) +{ + IMFS_jnode_t *jnode; +#if defined(RTEMS_POSIX_API) + uid_t st_uid; +#endif + + jnode = (IMFS_jnode_t *) pathloc->node_access; + + /* + * Verify I am the owner of the node or the super user. + */ + +#if defined(RTEMS_POSIX_API) + st_uid = geteuid(); + + if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) ) + set_errno_and_return_minus_one( EPERM ); +#endif + + jnode->st_uid = owner; + jnode->st_gid = group; + + IMFS_update_ctime( jnode ); + + return 0; +} diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c new file mode 100644 index 0000000000..fd38e7f993 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_creat.c @@ -0,0 +1,130 @@ +/* + * IMFS_create_node() + * + * Routine to create a new in memory file system node. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "imfs.h" +#include "libio_.h" + +IMFS_jnode_t *IMFS_create_node( + rtems_filesystem_location_info_t *parent_loc, + IMFS_jnode_types_t type, + char *name, + mode_t mode, + IMFS_types_union *info +) +{ + IMFS_jnode_t *node; + struct timeval tv; + IMFS_jnode_t *parent = NULL; + IMFS_fs_info_t *fs_info; + char *sym_name; + + if ( parent_loc != NULL ) + parent = parent_loc->node_access; + + /* + * Allocate an IMFS jnode + */ + + node = calloc( 1, sizeof( IMFS_jnode_t ) ); + if ( !node ) + return NULL; + + /* + * Fill in the basic information + */ + + node->st_nlink = 1; + node->type = type; + strncpy( node->name, name, NAME_MAX ); + + /* + * Fill in the mode and permission information for the jnode structure. + */ + + node->st_mode = mode & ~rtems_filesystem_umask; + +#if defined(RTEMS_POSIX_API) + node->st_uid = geteuid(); + node->st_gid = getegid(); +#else + node->st_uid = 0; + node->st_gid = 0; +#endif + + /* + * Now set all the times. + */ + + gettimeofday( &tv, 0 ); + + node->st_atime = (time_t) tv.tv_sec; + node->st_mtime = (time_t) tv.tv_sec; + node->st_ctime = (time_t) tv.tv_sec; + + /* + * Set the type specific information + */ + + switch (type) { + case IMFS_DIRECTORY: + Chain_Initialize_empty(&node->info.directory.Entries); + break; + + case IMFS_HARD_LINK: + node->info.hard_link.link_node = info->hard_link.link_node; + break; + + case IMFS_SYM_LINK: + sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 ); + strcpy( sym_name, info->sym_link.name ); + node->info.sym_link.name = sym_name; + break; + + case IMFS_DEVICE: + node->info.device.major = info->device.major; + node->info.device.minor = info->device.minor; + break; + + case IMFS_MEMORY_FILE: + node->info.file.size = 0; + node->info.file.indirect = 0; + node->info.file.doubly_indirect = 0; + node->info.file.triply_indirect = 0; + break; + + default: + assert(0); + break; + } + + /* + * If this node has a parent, then put it in that directory list. + */ + + if ( parent ) { + Chain_Append( &parent->info.directory.Entries, &node->Node ); + node->Parent = parent; + + fs_info = parent_loc->mt_entry->fs_info; + node->st_ino = ++fs_info->ino_count; + } + + + return node; +} diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c new file mode 100644 index 0000000000..856f21317e --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_debug.c @@ -0,0 +1,160 @@ +/* + * IMFS debug support routines + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <assert.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> /* for close */ + +#include <stdio.h> +#include <sys/stat.h> + +#include "imfs.h" +#include "libio_.h" + +/* + * IMFS_types + * + * Printable names for each of the IMFS file system types. + */ + +char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = { + "directory", + "device", + "link", + "memory file" +}; + +/* + * IMFS_print_jnode + * + * This routine prints the contents of the specified jnode. + */ + +void IMFS_print_jnode( + IMFS_jnode_t *the_jnode +) +{ + assert( the_jnode ); + + printf( "%s", the_jnode->name ); + switch( the_jnode->type ) { + case IMFS_DIRECTORY: + printf( "/" ); + break; + + case IMFS_DEVICE: + printf( " (device %d, %d)", + the_jnode->info.device.major, the_jnode->info.device.minor ); + break; + + case IMFS_MEMORY_FILE: + printf( " (file %d %p %p %p)", + (int)the_jnode->info.file.size, + the_jnode->info.file.indirect, + the_jnode->info.file.doubly_indirect, + the_jnode->info.file.triply_indirect + ); + break; + + case IMFS_HARD_LINK: + printf( " links not printed\n" ); + assert(0); + break; + + case IMFS_SYM_LINK: + printf( " links not printed\n" ); + assert(0); + break; + + default: + printf( " bad type %d\n", the_jnode->type ); + assert(0); + break; + } + puts(""); +} + +/* + * IMFS_dump_directory + * + * This routine prints the contents of a directory in the IMFS. If a + * directory is encountered, then this routine will recurse to process + * the subdirectory. + */ + +void IMFS_dump_directory( + IMFS_jnode_t *the_directory, + int level +) +{ + Chain_Node *the_node; + Chain_Control *the_chain; + IMFS_jnode_t *the_jnode; + int i; + + assert( the_directory ); + + assert( level >= 0 ); + + assert( the_directory->type == IMFS_DIRECTORY ); + + the_chain = &the_directory->info.directory.Entries; + + for ( the_node = the_chain->first; + !_Chain_Is_tail( the_chain, the_node ); + the_node = the_node->next ) { + + the_jnode = (IMFS_jnode_t *) the_node; + + for ( i=0 ; i<=level ; i++ ) + printf( " " ); + IMFS_print_jnode( the_jnode ); + if ( the_jnode->type == IMFS_DIRECTORY ) + IMFS_dump_directory( the_jnode, level + 1 ); + } +} + +/* + * IMFS_dump + * + * This routine dumps the entire IMFS that is mounted at the root + * directory. + * + * NOTE: Assuming the "/" directory is bad. + * Not checking that the starting directory is in an IMFS is bad. + */ + +void IMFS_dump( void ) +{ + printf( "*************** Dump of Entire IMFS ***************\n" ); + printf( "/\n" ); + IMFS_dump_directory( rtems_filesystem_root.node_access, 0 ); + printf( "*************** End of Dump ***************\n" ); +} + +/* + * IMFS_memfile_maximum_size() + * + * This routine returns the size of the largest file which can be created + * using the IMFS memory file type. + * + */ + +int IMFS_memfile_maximum_size( void ) +{ + return IMFS_MEMFILE_MAXIMUM_SIZE; +} diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c new file mode 100644 index 0000000000..134204027a --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_directory.c @@ -0,0 +1,278 @@ +/* + * XXX + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <chain.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <dirent.h> + +#include "imfs.h" +#include "libio_.h" + +long getdents( + int dd_fd, + char *dd_buf, + int dd_len +); + +/* ----------------------------------------------------------------------- + * This rountine will verify that the node being opened as a directory is + * in fact a directory node. If it is then the offset into the directory + * will be set to 0 to position to the first directory entry. + */ + +int imfs_dir_open( + rtems_libio_t *iop, + const char *pathname, + unsigned32 flag, + unsigned32 mode +) +{ + IMFS_jnode_t *the_jnode; + + /* Is the node a directory ? */ + the_jnode = (IMFS_jnode_t *) iop->file_info; + + if ( the_jnode->type != IMFS_DIRECTORY ) + return -1; /* It wasn't a directory --> return error */ + + iop->offset = 0; + return 0; +} + + + +/* ----------------------------------------------------------------------- + * This routine will read the next directory entry based on the directory + * offset. The offset should be equal to -n- time the size of an individual + * dirent structure. If n is not an integer multiple of the sizeof a + * dirent structure, an integer division will be performed to determine + * directory entry that will be returned in the buffer. Count should reflect + * -m- times the sizeof dirent bytes to be placed in the buffer. + * If there are not -m- dirent elements from the current directory position + * to the end of the exisiting file, the remaining entries will be placed in + * the buffer and the returned value will be equal to -m actual- times the + * size of a directory entry. + */ + +int imfs_dir_read( + rtems_libio_t *iop, + void *buffer, + unsigned32 count +) +{ + /* + * Read up to element iop->offset in the directory chain of the + * imfs_jnode_t struct for this file descriptor. + */ + Chain_Node *the_node; + Chain_Control *the_chain; + IMFS_jnode_t *the_jnode; + int bytes_transferred; + int current_entry; + int first_entry; + int last_entry; + struct dirent tmp_dirent; + + the_jnode = (IMFS_jnode_t *)iop->file_info; + the_chain = &the_jnode->info.directory.Entries; + + if ( Chain_Is_empty( the_chain ) ) + return 0; + + /* Move to the first of the desired directory entries */ + the_node = the_chain->first; + + bytes_transferred = 0; + first_entry = iop->offset; + /* protect against using sizes that are not exact multiples of the */ + /* -dirent- size. These could result in unexpected results */ + last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent); + + /* The directory was not empty so try to move to the desired entry in chain*/ + for( + current_entry = 0; + current_entry < last_entry; + current_entry = current_entry + sizeof(struct dirent) ){ + + if ( Chain_Is_tail( the_chain, the_node ) ){ + /* We hit the tail of the chain while trying to move to the first */ + /* entry in the read */ + return bytes_transferred; /* Indicate that there are no more */ + /* entries to return */ + } + + if( current_entry >= first_entry ) { + /* Move the entry to the return buffer */ + tmp_dirent.d_ino = 1; + tmp_dirent.d_off = current_entry; + tmp_dirent.d_reclen = sizeof( struct dirent ); + the_jnode = (IMFS_jnode_t *) the_node; + tmp_dirent.d_namlen = strlen( the_jnode->name ); + sprintf( tmp_dirent.d_name, "%s", the_jnode->name ); + memcpy( + buffer + bytes_transferred, + (void *)&tmp_dirent, + sizeof( struct dirent ) + ); + iop->offset = iop->offset + sizeof(struct dirent); + bytes_transferred = bytes_transferred + sizeof( struct dirent ); + } + + the_node = the_node->next; + } + + /* Success */ + return bytes_transferred; +} + + + +/* ----------------------------------------------------------------------- + * This routine will be called by the generic close routine to cleanup any + * resources that have been allocated for the management of the file + */ + +int imfs_dir_close( + rtems_libio_t *iop +) +{ + /* The generic close routine handles the deallocation of the file control */ + /* and associated memory. At present the imfs_dir_close simply */ + /* returns a successful completion status */ + + return 0; +} + + + +/* ----------------------------------------------------------------------- + * This routine will behave in one of three ways based on the state of + * argument whence. Based on the state of its value the offset argument will + * be interpreted using one of the following methods: + * + * SEEK_SET - offset is the absolute byte offset from the start of the + * logical start of the dirent sequence that represents the + * directory + * SEEK_CUR - offset is used as the relative byte offset from the current + * directory position index held in the iop structure + * SEEK_END - N/A --> This will cause an assert. + */ + +int imfs_dir_lseek( + rtems_libio_t *iop, + off_t offset, + int whence +) +{ + off_t normal_offset; + + normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent); + + + switch( whence ) + { + case SEEK_SET: /* absolute move from the start of the file */ + iop->offset = normal_offset; + break; + + case SEEK_CUR: /* relative move */ + iop->offset = iop->offset + normal_offset; + break; + + case SEEK_END: /* Movement past the end of the directory via lseek */ + /* is not a permitted operation */ + default: + set_errno_and_return_minus_one( EINVAL ); + break; + + } + + return 0; +} + + + +/* ----------------------------------------------------------------------- + * This routine will obtain the following information concerning the current + * directory: + * st_dev 0ll + * st_ino 1 + * st_mode mode extracted from the jnode + * st_nlink number of links to this node + * st_uid uid extracted from the jnode + * st_gid gid extracted from the jnode + * st_rdev 0ll + * st_size the number of bytes in the directory + * This is calculated by taking the number of entries + * in the directory and multiplying by the size of a + * dirent structure + * st_blksize 0 + * st_blocks 0 + * st_atime time of last access + * st_mtime time of last modification + * st_ctime time of the last change + * + * This information will be returned to the calling function in a -stat- struct + * + */ + +int imfs_dir_fstat( + rtems_filesystem_location_info_t *loc, + struct stat *buf +) +{ + Chain_Node *the_node; + Chain_Control *the_chain; + IMFS_jnode_t *the_jnode; + + + the_jnode = (IMFS_jnode_t *) loc->node_access; + + buf->st_dev = 0ll; + buf->st_ino = the_jnode->st_ino; + buf->st_mode = the_jnode->st_mode; + buf->st_nlink = the_jnode->st_nlink; + buf->st_uid = the_jnode->st_uid; + buf->st_gid = the_jnode->st_gid; + buf->st_rdev = 0ll; + buf->st_blksize = 0; + buf->st_blocks = 0; + buf->st_atime = the_jnode->st_atime; + buf->st_mtime = the_jnode->st_mtime; + buf->st_ctime = the_jnode->st_ctime; + + buf->st_size = 0; + + the_chain = &the_jnode->info.directory.Entries; + + /* Run through the chain and count the number of directory entries */ + /* that are subordinate to this directory node */ + for ( the_node = the_chain->first ; + !_Chain_Is_tail( the_chain, the_node ) ; + the_node = the_node->next ) { + + buf->st_size = buf->st_size + sizeof( struct dirent ); + } + + return 0; +} + + diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c new file mode 100644 index 0000000000..eb770a58ce --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_eval.c @@ -0,0 +1,638 @@ +/* + * Evaluation IMFS Node Support Routines + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <assert.h> + +#include "imfs.h" +#include "libio_.h" + +#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ) +#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE) + +#define MAXSYMLINK 5 + +int IMFS_Set_handlers( + rtems_filesystem_location_info_t *loc +) +{ + IMFS_jnode_t *node = loc->node_access; + + switch( node->type ) { + case IMFS_DIRECTORY: + loc->handlers = &dir_handlers; + break; + case IMFS_DEVICE: + loc->handlers = &device_handlers; + break; + case IMFS_SYM_LINK: + case IMFS_HARD_LINK: + loc->handlers = &null_handlers; + break; + case IMFS_MEMORY_FILE: + loc->handlers = &memfile_handlers; + break; + } + + return 0; +} + +/* + * IMFS_evaluate_permission + * + * The following routine evaluates that we have permission + * to do flags on the node. + */ + +int IMFS_evaluate_permission( + rtems_filesystem_location_info_t *node, + int flags +) +{ + uid_t st_uid; + gid_t st_gid; + IMFS_jnode_t *jnode; + int flags_to_test; + + if (! rtems_libio_is_valid_perms( flags ) ) { + assert( 0 ); + set_errno_and_return_minus_one( EIO ); + } + + jnode = node->node_access; + +#if defined(RTEMS_POSIX_API) + st_uid = geteuid(); + st_gid = getegid(); +#else + st_uid = jnode->st_uid; + st_gid = jnode->st_gid; +#endif + + /* + * Check if I am owner or a group member or someone else. + */ + + flags_to_test = flags; + + if ( st_uid == jnode->st_uid ) + flags_to_test <<= 6; + else if ( st_gid == jnode->st_gid ) + flags_to_test <<= 3; + else + /* must be other - do nothing */; + + /* + * If all of the flags are set we have permission + * to do this. + */ + if ( ( flags_to_test & jnode->st_mode) == flags_to_test ) + return 1; + + return 0; +} + +/* + * IMFS_evaluate_hard_link + * + * The following routine evaluates a hardlink to the actual node. + */ + +int IMFS_evaluate_hard_link( + rtems_filesystem_location_info_t *node, /* IN/OUT */ + int flags /* IN */ +) +{ + IMFS_jnode_t *jnode = node->node_access; + int result = 0; + + /* + * Check for things that should never happen. + */ + + if ( jnode->type != IMFS_HARD_LINK ) + rtems_fatal_error_occurred (0xABCD0000); + + /* + * Set the hard link value and the handlers. + */ + + node->node_access = jnode->info.hard_link.link_node; + + IMFS_Set_handlers( node ); + + /* + * Verify we have the correct permissions for this node. + */ + + if (! IMFS_evaluate_permission( node, flags ) ) + set_errno_and_return_minus_one( EACCES ); + + return result; +} + + +/* + * IMFS_evaluate_sym_link + * + * The following routine evaluates a symbolic link to the actual node. + */ + +int IMFS_evaluate_sym_link( + rtems_filesystem_location_info_t *node, /* IN/OUT */ + int flags /* IN */ +) +{ + IMFS_jnode_t *jnode = node->node_access; + int result = 0; + int i; + + /* + * Check for things that should never happen. + */ + + if ( jnode->type != IMFS_SYM_LINK ) + rtems_fatal_error_occurred (0xABCD0000); + + if ( !jnode->Parent ) + rtems_fatal_error_occurred( 0xBAD00000 ); + + + /* + * Move the node_access to either the symbolic links parent or + * root depending on the symbolic links path. + */ + + node->node_access = jnode->Parent; + + rtems_filesystem_get_sym_start_loc( + jnode->info.sym_link.name, + &i, + node + ); + + /* + * Use eval path to evaluate the path of the symbolic link. + */ + + result = IMFS_eval_path( + &jnode->info.sym_link.name[i], + flags, + node + ); + + IMFS_Set_handlers( node ); + + /* + * Verify we have the correct permissions for this node. + */ + + if (! IMFS_evaluate_permission( node, flags ) ) + set_errno_and_return_minus_one( EACCES ); + + return result; +} + +/* + * IMFS_evaluate_link + * + * The following routine returns the real node pointed to by a link. + */ + +int IMFS_evaluate_link( + rtems_filesystem_location_info_t *node, /* IN/OUT */ + int flags /* IN */ +) +{ + IMFS_jnode_t *jnode; + int result = 0; + + do { + jnode = node->node_access; + + /* + * Increment and check the link counter. + */ + + rtems_filesystem_link_counts ++; + if ( rtems_filesystem_link_counts > MAXSYMLINK ) { + rtems_filesystem_link_counts = 0; + set_errno_and_return_minus_one( ELOOP ); + } + + /* + * Follow the Link node. + */ + + if ( jnode->type == IMFS_HARD_LINK ) + result = IMFS_evaluate_hard_link( node, flags ); + + else if (jnode->type == IMFS_SYM_LINK ) + result = IMFS_evaluate_sym_link( node, flags ); + + } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) || + ( jnode->type == IMFS_HARD_LINK ) ) ); + + /* + * Clear link counter. + */ + + rtems_filesystem_link_counts = 0; + + return result; +} + + +/* + * IMFS_evaluate_for_make + * + * The following routine evaluate path for a new node to be created. + * pathloc is returned with a pointer to the parent of the new node. + * name is returned with a pointer to the first character in the + * new node name. The parent node is verified to be a directory. + */ + +int IMFS_evaluate_for_make( + const char *path, /* IN */ + rtems_filesystem_location_info_t *pathloc, /* IN/OUT */ + const char **name /* OUT */ +) +{ + int i = 0; + int len; + IMFS_token_types type; + char token[ NAME_MAX + 1 ]; + rtems_filesystem_location_info_t newloc; + IMFS_jnode_t *node; + int done = 0; + int result; + + /* + * This was filled in by the caller and is valid in the + * mount table. + */ + node = pathloc->node_access; + + /* + * Evaluate all tokens until we are done or an error occurs. + */ + + while( !done ) { + + type = IMFS_get_token( &path[i], token, &len ); + i += len; + + if ( !pathloc->node_access ) + set_errno_and_return_minus_one( ENOENT ); + + /* + * I cannot move out of this directory without execute permission. + */ + + if ( type != IMFS_NO_MORE_PATH ) + if ( node->type == IMFS_DIRECTORY ) + if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) ) + set_errno_and_return_minus_one( EACCES ); + + node = pathloc->node_access; + + switch( type ) { + + case IMFS_UP_DIR: + + /* + * Am I at the root of this mounted filesystem? + */ + + if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){ + + /* + * Am I at the root of all filesystems? + */ + + if ( pathloc->node_access == rtems_filesystem_root.node_access ) { + break; + + } else { + newloc = pathloc->mt_entry->mt_point_node; + *pathloc = newloc; + return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name ); + } + } else { + + if ( !node->Parent ) + set_errno_and_return_minus_one( ENOENT ); + + node = node->Parent; + } + + pathloc->node_access = node; + break; + + case IMFS_NAME: + + if ( node->type == IMFS_HARD_LINK ) { + + result = IMFS_evaluate_link( pathloc, 0 ); + if ( result == -1 ) + return -1; + + } else if ( node->type == IMFS_SYM_LINK ) { + + result = IMFS_evaluate_link( pathloc, 0 ); + + if ( result == -1 ) + return -1; + } + + node = pathloc->node_access; + if ( !node ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * Only a directory can be decended into. + */ + + if ( node->type != IMFS_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * If we are at a node that is a mount point. Set loc to the + * new fs root node and let them finish evaluating the path. + */ + + if ( node->info.directory.mt_fs != NULL ) { + newloc = node->info.directory.mt_fs->mt_fs_root; + *pathloc = newloc; + return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name ); + } + + /* + * Otherwise find the token name in the present location. + */ + + node = IMFS_find_match_in_dir( node, token ); + + /* + * If there is no node we have found the name of the node we + * wish to create. + */ + + if ( ! node ) + done = TRUE; + else + pathloc->node_access = node; + + break; + + case IMFS_NO_MORE_PATH: + set_errno_and_return_minus_one( EEXIST ); + break; + + case IMFS_INVALID_TOKEN: + set_errno_and_return_minus_one( ENAMETOOLONG ); + break; + + case IMFS_CURRENT_DIR: + break; + } + } + + *name = &path[ i - len ]; + + /* + * We have evaluated the path as far as we can. + * Verify there is not any invalid stuff at the end of the name. + */ + + for( ; path[i] != '\0'; i++) { + if (! IMFS_is_separator( path[ i ] ) ) + set_errno_and_return_minus_one( ENOENT ); + } + + /* + * Verify we can execute and write to this directory. + */ + + result = IMFS_Set_handlers( pathloc ); + + /* + * The returned node must be a directory + */ + node = pathloc->node_access; + if ( node->type != IMFS_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * We must have Write and execute permission on the returned node. + */ + + if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) ) + set_errno_and_return_minus_one( EACCES ); + + return result; +} + + +/* + * IMFS_eval_path + * + * The following routine evaluate path for a node that wishes to be + * accessed with mode. pathloc is returned with a pointer to the + * node to be accessed. + */ + +int IMFS_eval_path( + const char *pathname, /* IN */ + int flags, /* IN */ + rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +) +{ + int i = 0; + int len; + IMFS_token_types type = IMFS_CURRENT_DIR; + char token[ NAME_MAX + 1 ]; + rtems_filesystem_location_info_t newloc; + IMFS_jnode_t *node; + int result; + + if (! rtems_libio_is_valid_perms( flags ) ) { + assert( 0 ); + set_errno_and_return_minus_one( EIO ); + } + + /* + * This was filled in by the caller and is valid in the + * mount table. + */ + + node = pathloc->node_access; + + /* + * Evaluate all tokens until we are done or an error occurs. + */ + + while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) { + + type = IMFS_get_token( &pathname[i], token, &len ); + i += len; + + if ( !pathloc->node_access ) + set_errno_and_return_minus_one( ENOENT ); + + /* + * I cannot move out of this directory without execute permission. + */ + if ( type != IMFS_NO_MORE_PATH ) + if ( node->type == IMFS_DIRECTORY ) + if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) ) + set_errno_and_return_minus_one( EACCES ); + + node = pathloc->node_access; + + switch( type ) { + case IMFS_UP_DIR: + + /* + * Am I at the root of this mounted filesystem? + */ + + if (pathloc->node_access == + pathloc->mt_entry->mt_fs_root.node_access) { + + /* + * Am I at the root of all filesystems? + */ + + if ( pathloc->node_access == rtems_filesystem_root.node_access ) { + break; /* Throw out the .. in this case */ + } else { + newloc = pathloc->mt_entry->mt_point_node; + *pathloc = newloc; + return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc); + } + } else { + + if ( !node->Parent ) + set_errno_and_return_minus_one( ENOENT ); + + node = node->Parent; + pathloc->node_access = node; + + } + + pathloc->node_access = node; + break; + + case IMFS_NAME: + /* + * If we are at a link follow it. + */ + + if ( node->type == IMFS_HARD_LINK ) { + + IMFS_evaluate_hard_link( pathloc, 0 ); + + node = pathloc->node_access; + if ( !node ) + set_errno_and_return_minus_one( ENOTDIR ); + + } else if ( node->type == IMFS_SYM_LINK ) { + + result = IMFS_evaluate_sym_link( pathloc, 0 ); + + node = pathloc->node_access; + if ( result == -1 ) + return -1; + } + + /* + * Only a directory can be decended into. + */ + + if ( node->type != IMFS_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * If we are at a node that is a mount point. Set loc to the + * new fs root node and let them finish evaluating the path. + */ + + if ( node->info.directory.mt_fs != NULL ) { + newloc = node->info.directory.mt_fs->mt_fs_root; + *pathloc = newloc; + return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc ); + } + + /* + * Otherwise find the token name in the present location. + */ + + node = IMFS_find_match_in_dir( node, token ); + if ( !node ) + set_errno_and_return_minus_one( ENOENT ); + + /* + * Set the node access to the point we have found. + */ + + pathloc->node_access = node; + break; + + case IMFS_NO_MORE_PATH: + case IMFS_CURRENT_DIR: + break; + + case IMFS_INVALID_TOKEN: + set_errno_and_return_minus_one( ENAMETOOLONG ); + break; + + } + } + + /* + * Only return root node if this is the base file system. + */ + + if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) && + (pathloc->node_access != rtems_filesystem_root.node_access) ) { + newloc = pathloc->mt_entry->mt_point_node; + *pathloc = newloc; + } + + result = IMFS_Set_handlers( pathloc ); + + /* + * Verify we have the correct permissions for this node. + */ + + if (! IMFS_evaluate_permission( pathloc, flags ) ) + set_errno_and_return_minus_one( EACCES ); + + return result; +} + + + + + + + + + diff --git a/cpukit/libfs/src/imfs/imfs_fchmod.c b/cpukit/libfs/src/imfs/imfs_fchmod.c new file mode 100644 index 0000000000..06c2969100 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_fchmod.c @@ -0,0 +1,55 @@ +/* + * IMFS file change mode routine. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> + +#include "libio_.h" +#include "imfs.h" + +int IMFS_fchmod( + rtems_filesystem_location_info_t *loc, + mode_t mode +) +{ + IMFS_jnode_t *jnode; +#if defined(RTEMS_POSIX_API) + uid_t st_uid; +#endif + + jnode = loc->node_access; + + /* + * Verify I am the owner of the node or the super user. + */ +#if defined(RTEMS_POSIX_API) + st_uid = geteuid(); + + if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) ) + set_errno_and_return_minus_one( EPERM ); +#endif + + /* + * Change only the RWX permissions on the jnode to mode. + */ + if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) ) + set_errno_and_return_minus_one( EPERM ); + + jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO); + jnode->st_mode |= mode; + + IMFS_update_ctime( jnode ); + + return 0; +} + diff --git a/cpukit/libfs/src/imfs/imfs_free.c b/cpukit/libfs/src/imfs/imfs_free.c new file mode 100644 index 0000000000..8216547c12 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_free.c @@ -0,0 +1,99 @@ +/* + * Free IMFS Node Support Routines + * + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> + +#include "libio_.h" +#include "imfs.h" + +/* + * IMFS_freenodinfo + * + * This routine is the IMFS free node handler for the file system + * operations table. + * + * The In Memory File System keeps its nodes in memory. This routine + * is for file sytems that do not. + */ + +int IMFS_freenodinfo( + rtems_filesystem_location_info_t *pathloc /* IN */ +) +{ + return 0; +} + + +/* + * IMFS_freenod + * + * The following routine frees a node if possible. + * + * The routine returns 0 if the node was not freed and 1 if it was. + * + * NOTE: This routine is for INTERNAL IMFS use only. + */ + +int IMFS_freenod( + rtems_filesystem_location_info_t *pathloc +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = pathloc->node_access; + + if ( the_jnode->type == IMFS_DIRECTORY ) { + + /* + * You cannot remove a node that still has children + */ + + if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) ) + return ENOTEMPTY; + + /* + * You cannot remove the file system root node. + */ + if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access ) + return EBUSY; + + /* + * You cannot remove a mountpoint. + */ + if ( the_jnode->info.directory.mt_fs != NULL ) + return EBUSY; + } + + if ( !rtems_libio_is_file_open( the_jnode ) && + (the_jnode->st_nlink < 1) ) { + + /* + * Is the rtems_filesystem_current is this node? + */ + if ( rtems_filesystem_current.node_access == pathloc->node_access ) { + rtems_filesystem_current.node_access = NULL; + } + + /* + * Free memory associated with a memory file. + */ + if ( the_jnode->type == IMFS_MEMORY_FILE ) + IMFS_memfile_remove( the_jnode ); + + free( the_jnode ); + } + + return 0; +} diff --git a/cpukit/libfs/src/imfs/imfs_getchild.c b/cpukit/libfs/src/imfs/imfs_getchild.c new file mode 100644 index 0000000000..3f37738ab4 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_getchild.c @@ -0,0 +1,68 @@ +/* + * IMFS_find_match_in_dir() + * + * This routine returns the child name in the given directory. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include <assert.h> +#include "imfs.h" + +static char dotname[2] = "."; +static char dotdotname[2] = ".."; + +IMFS_jnode_t *IMFS_find_match_in_dir( + IMFS_jnode_t *directory, + char *name +) +{ + Chain_Node *the_node; + Chain_Control *the_chain; + IMFS_jnode_t *the_jnode; + + /* + * Check for fatal errors + */ + + assert( directory ); + if ( !name ) + return 0; + + assert( name ); + if ( !directory ) + return 0; + + /* + * Check for "." and ".." + */ + + if ( !strcmp( name, dotname ) ) + return directory; + + if ( !strcmp( name, dotdotname ) ) + return directory->Parent; + + the_chain = &directory->info.directory.Entries; + + for ( the_node = the_chain->first; + !_Chain_Is_tail( the_chain, the_node ); + the_node = the_node->next ) { + + the_jnode = (IMFS_jnode_t *) the_node; + + if ( !strcmp( name, the_jnode->name ) ) + return the_jnode; + } + + return 0; +} diff --git a/cpukit/libfs/src/imfs/imfs_gtkn.c b/cpukit/libfs/src/imfs/imfs_gtkn.c new file mode 100644 index 0000000000..052c67ceba --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_gtkn.c @@ -0,0 +1,84 @@ +/* + * IMFS_get_token + * + * Routine to get a token (name or separator) from the path + * the length of the token is returned in token_len. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <stdlib.h> +#include "imfs.h" +#include "libio_.h" + +IMFS_token_types IMFS_get_token( + const char *path, + char *token, + int *token_len +) +{ + int i = 0; + IMFS_token_types type = IMFS_NAME; + + /* + * Copy a name into token. (Remember NULL is a token.) + */ + + while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) { + + token[i] = path[i]; + + if (i == NAME_MAX) + return IMFS_INVALID_TOKEN; + + if ( !IMFS_is_valid_name_char( token[i] ) ) + type = IMFS_INVALID_TOKEN; + + i++; + } + + /* + * Copy a seperator into token. + */ + + if ( i == 0 ) { + token[i] = path[i]; + + if ( token[i] != '\0' ) { + i++; + type = IMFS_CURRENT_DIR; + } else { + type = IMFS_NO_MORE_PATH; + } + } else if (token[ i-1 ] != '\0') { + token[i] = '\0'; + } + + /* + * Set token_len to the number of characters copied. + */ + + *token_len = i; + + /* + * If we copied something that was not a seperator see if + * it was a special name. + */ + + if ( type == IMFS_NAME ) { + if ( strcmp( token, "..") == 0 ) + type = IMFS_UP_DIR; + else if ( strcmp( token, "." ) == 0 ) + type = IMFS_CURRENT_DIR; + } + + return type; +} diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c new file mode 100644 index 0000000000..bb3a0f9aea --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_init.c @@ -0,0 +1,158 @@ +/* + * IMFS Initialization + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> /* for mkdir */ +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + +#include <assert.h> + +#include "imfs.h" +#include "libio_.h" + +#if defined(IMFS_DEBUG) +#include <stdio.h> +#endif + +/* + * IMFS file system operations table + */ + +rtems_filesystem_operations_table IMFS_ops = { + IMFS_eval_path, + IMFS_evaluate_for_make, + IMFS_link, + IMFS_unlink, + IMFS_node_type, + IMFS_mknod, + IMFS_rmnod, + IMFS_chown, + IMFS_freenodinfo, + IMFS_mount, + IMFS_initialize, + IMFS_unmount, + IMFS_fsunmount, + IMFS_utime, + IMFS_evaluate_link, + IMFS_symlink, + IMFS_readlink +}; + +/* + * IMFS_initialize + */ + +int IMFS_initialize( + rtems_filesystem_mount_table_entry_t *temp_mt_entry +) +{ + IMFS_fs_info_t *fs_info; + IMFS_jnode_t *jnode; + + /* + * Create the root node + */ + + temp_mt_entry->mt_fs_root.node_access = IMFS_create_node( + NULL, + IMFS_DIRECTORY, + "", + ( S_IRWXO | S_IRWXG| S_IRWXU ), + NULL + ); + + temp_mt_entry->mt_fs_root.handlers = &dir_handlers; + temp_mt_entry->mt_fs_root.ops = &IMFS_ops; + temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS; + + /* + * Create custom file system data. + */ + fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) ); + if ( !fs_info ){ + free(temp_mt_entry->mt_fs_root.node_access); + return 1; + } + temp_mt_entry->fs_info = fs_info; + + /* + * Set st_ino for the root to 1. + */ + + fs_info->ino_count = 1; + + jnode = temp_mt_entry->mt_fs_root.node_access; + jnode->st_ino = fs_info->ino_count; + + return 0; +} + +#define jnode_get_control( jnode ) \ + (&jnode->info.directory.Entries) + +#define jnode_has_no_children( jnode ) \ + Chain_Is_empty( jnode_get_control( jnode ) ) + +#define jnode_has_children( jnode ) \ + ( ! jnode_has_no_children( jnode ) ) + +#define jnode_get_first_child( jnode ) \ + ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next)) + + +int IMFS_fsunmount( + rtems_filesystem_mount_table_entry_t *temp_mt_entry +) +{ + IMFS_jnode_t *jnode; + IMFS_jnode_t *next; + rtems_filesystem_location_info_t loc; + int result = 0; + + /* + * Traverse tree that starts at the mt_fs_root and deallocate memory + * associated memory space + */ + + jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access; + + do { + next = jnode->Parent; + loc.node_access = (void *)jnode; + + if ( jnode->type != IMFS_DIRECTORY ) { + result = IMFS_unlink( &loc ); + if (result != 0) + return -1; + jnode = next; + } else if ( jnode_has_no_children( jnode ) ) { + result = IMFS_unlink( &loc ); + if (result != 0) + return -1; + jnode = next; + } + if ( jnode != NULL ) { + if ( jnode->type == IMFS_DIRECTORY ) { + if ( jnode_has_children( jnode ) ) + jnode = jnode_get_first_child( jnode ); + } + } + } while (jnode != NULL); + + return 0; +} + + + diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c new file mode 100644 index 0000000000..bb3a0f9aea --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_initsupp.c @@ -0,0 +1,158 @@ +/* + * IMFS Initialization + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> /* for mkdir */ +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + +#include <assert.h> + +#include "imfs.h" +#include "libio_.h" + +#if defined(IMFS_DEBUG) +#include <stdio.h> +#endif + +/* + * IMFS file system operations table + */ + +rtems_filesystem_operations_table IMFS_ops = { + IMFS_eval_path, + IMFS_evaluate_for_make, + IMFS_link, + IMFS_unlink, + IMFS_node_type, + IMFS_mknod, + IMFS_rmnod, + IMFS_chown, + IMFS_freenodinfo, + IMFS_mount, + IMFS_initialize, + IMFS_unmount, + IMFS_fsunmount, + IMFS_utime, + IMFS_evaluate_link, + IMFS_symlink, + IMFS_readlink +}; + +/* + * IMFS_initialize + */ + +int IMFS_initialize( + rtems_filesystem_mount_table_entry_t *temp_mt_entry +) +{ + IMFS_fs_info_t *fs_info; + IMFS_jnode_t *jnode; + + /* + * Create the root node + */ + + temp_mt_entry->mt_fs_root.node_access = IMFS_create_node( + NULL, + IMFS_DIRECTORY, + "", + ( S_IRWXO | S_IRWXG| S_IRWXU ), + NULL + ); + + temp_mt_entry->mt_fs_root.handlers = &dir_handlers; + temp_mt_entry->mt_fs_root.ops = &IMFS_ops; + temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS; + + /* + * Create custom file system data. + */ + fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) ); + if ( !fs_info ){ + free(temp_mt_entry->mt_fs_root.node_access); + return 1; + } + temp_mt_entry->fs_info = fs_info; + + /* + * Set st_ino for the root to 1. + */ + + fs_info->ino_count = 1; + + jnode = temp_mt_entry->mt_fs_root.node_access; + jnode->st_ino = fs_info->ino_count; + + return 0; +} + +#define jnode_get_control( jnode ) \ + (&jnode->info.directory.Entries) + +#define jnode_has_no_children( jnode ) \ + Chain_Is_empty( jnode_get_control( jnode ) ) + +#define jnode_has_children( jnode ) \ + ( ! jnode_has_no_children( jnode ) ) + +#define jnode_get_first_child( jnode ) \ + ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next)) + + +int IMFS_fsunmount( + rtems_filesystem_mount_table_entry_t *temp_mt_entry +) +{ + IMFS_jnode_t *jnode; + IMFS_jnode_t *next; + rtems_filesystem_location_info_t loc; + int result = 0; + + /* + * Traverse tree that starts at the mt_fs_root and deallocate memory + * associated memory space + */ + + jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access; + + do { + next = jnode->Parent; + loc.node_access = (void *)jnode; + + if ( jnode->type != IMFS_DIRECTORY ) { + result = IMFS_unlink( &loc ); + if (result != 0) + return -1; + jnode = next; + } else if ( jnode_has_no_children( jnode ) ) { + result = IMFS_unlink( &loc ); + if (result != 0) + return -1; + jnode = next; + } + if ( jnode != NULL ) { + if ( jnode->type == IMFS_DIRECTORY ) { + if ( jnode_has_children( jnode ) ) + jnode = jnode_get_first_child( jnode ); + } + } + } while (jnode != NULL); + + return 0; +} + + + diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c new file mode 100644 index 0000000000..2232209705 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_link.c @@ -0,0 +1,72 @@ +/* + * IMFS_link + * + * The following rouine creates a new link node under parent with the + * name given in name. The link node is set to point to the node at + * to_loc. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "imfs.h" +#include "libio_.h" + +int IMFS_link( + rtems_filesystem_location_info_t *to_loc, /* IN */ + rtems_filesystem_location_info_t *parent_loc, /* IN */ + const char *token /* IN */ +) +{ + IMFS_types_union info; + IMFS_jnode_t *new_node; + char new_name[ NAME_MAX + 1 ]; + int i; + + /* + * Verify this node can be linked to. + */ + + info.hard_link.link_node = to_loc->node_access; + if ( info.hard_link.link_node->st_nlink >= LINK_MAX ) + set_errno_and_return_minus_one( EMLINK ); + + /* + * Remove any separators at the end of the string. + */ + + IMFS_get_token( token, new_name, &i ); + + /* + * Create a new link node. + */ + + new_node = IMFS_create_node( + parent_loc, + IMFS_HARD_LINK, + new_name, + ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )), + &info + ); + + if ( !new_node ) + set_errno_and_return_minus_one( ENOMEM ); + + /* + * Increment the link count of the node being pointed to. + */ + + info.hard_link.link_node->st_nlink++; + IMFS_update_ctime( info.hard_link.link_node ); + + return 0; +} + diff --git a/cpukit/libfs/src/imfs/imfs_mknod.c b/cpukit/libfs/src/imfs/imfs_mknod.c new file mode 100644 index 0000000000..d4feef4f36 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_mknod.c @@ -0,0 +1,76 @@ +/* + * IMFS_mknod + * + * Routine to create a node in the IMFS file system. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <assert.h> + +#include "imfs.h" +#include "libio_.h" + +int IMFS_mknod( + const char *token, /* IN */ + mode_t mode, /* IN */ + dev_t dev, /* IN */ + rtems_filesystem_location_info_t *pathloc /* IN/OUT */ +) +{ + IMFS_token_types type = 0; + IMFS_jnode_t *new_node; + int result; + char new_name[ NAME_MAX + 1 ]; + IMFS_types_union info; + + IMFS_get_token( token, new_name, &result ); + + /* + * Figure out what type of IMFS node this is. + */ + + if ( S_ISDIR(mode) ) + type = IMFS_DIRECTORY; + else if ( S_ISREG(mode) ) + type = IMFS_MEMORY_FILE; + else if ( S_ISBLK(mode) || S_ISCHR(mode) ) { + type = IMFS_DEVICE; + rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor ); + } else { + assert( 0 ); + set_errno_and_return_minus_one( EINVAL ); + } + + /* + * Allocate and fill in an IMFS jnode + */ + + new_node = IMFS_create_node( + pathloc, + type, + new_name, + mode, + &info + ); + + if ( !new_node ) + set_errno_and_return_minus_one( ENOMEM ); + + return 0; +} + diff --git a/cpukit/libfs/src/imfs/imfs_mount.c b/cpukit/libfs/src/imfs/imfs_mount.c new file mode 100644 index 0000000000..a267b52576 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_mount.c @@ -0,0 +1,49 @@ +/* + * IMFS_mount + * + * This routine will look at a mount table entry that we are going to + * add to the mount table. If the mount point rtems_filesystem + * location_info_t struct refers to a node that is a directory, + * the node will be marked as a mount point by setting its directory.mt_fs + * pointer to point to the mount table entry that we are about to add + * to the mount table chain. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> + +#include "imfs.h" +#include "libio_.h" + +int IMFS_mount( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + IMFS_jnode_t *node; + + node = mt_entry->mt_point_node.node_access; + + /* + * Is the node that we are mounting onto a directory node ? + */ + + if ( node->type != IMFS_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * Set mt_fs pointer to point to the mount table entry for + * the mounted file system. + */ + + node->info.directory.mt_fs = mt_entry; + return 0; +} diff --git a/cpukit/libfs/src/imfs/imfs_ntype.c b/cpukit/libfs/src/imfs/imfs_ntype.c new file mode 100644 index 0000000000..bdf451a879 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_ntype.c @@ -0,0 +1,29 @@ +/* + * IMFS_node_type + * + * The following verifies that returns the type of node that the + * loc refers to. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "imfs.h" + +rtems_filesystem_node_types_t IMFS_node_type( + rtems_filesystem_location_info_t *pathloc /* IN */ +) +{ + IMFS_jnode_t *node; + + node = pathloc->node_access; + return node->type; +} diff --git a/cpukit/libfs/src/imfs/imfs_readlink.c b/cpukit/libfs/src/imfs/imfs_readlink.c new file mode 100644 index 0000000000..958118f42f --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_readlink.c @@ -0,0 +1,40 @@ +/* + * IMFS_readlink + * + * The following rouine puts the symblic links destination name into + * buff. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "imfs.h" +#include "libio_.h" + +int IMFS_readlink( + rtems_filesystem_location_info_t *loc, + char *buf, /* OUT */ + size_t bufsize +) +{ + IMFS_jnode_t *node; + int i; + + node = loc->node_access; + + if ( node->type != IMFS_SYM_LINK ) + set_errno_and_return_minus_one( EINVAL ); + + for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ ) + buf[i] = node->info.sym_link.name[i]; + + return i; +} diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c new file mode 100644 index 0000000000..f651622de4 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_rmnod.c @@ -0,0 +1,97 @@ +/* + * IMFS_rmnod + * + * This routine is available from the optable to remove a node + * from the IMFS file system. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "libio_.h" +#include "imfs.h" + + +int IMFS_rmnod( + rtems_filesystem_location_info_t *pathloc /* IN */ +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = (IMFS_jnode_t *) pathloc->node_access; + + if ( the_jnode->type == IMFS_DIRECTORY ) { + + /* + * You cannot remove a node that still has children + */ + + if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) ) + set_errno_and_return_minus_one( ENOTEMPTY ); + + /* + * You cannot remove the file system root node. + */ + + if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access ) + set_errno_and_return_minus_one( EBUSY ); + + /* + * You cannot remove a mountpoint. + */ + + if ( the_jnode->info.directory.mt_fs != NULL ) + set_errno_and_return_minus_one( EBUSY ); + } + + /* + * Take the node out of the parent's chain that contains this node + */ + if ( the_jnode->Parent != NULL ) { + Chain_Extract( (Chain_Node *) the_jnode ); + the_jnode->Parent = NULL; + } + + /* + * Decrement the link counter and see if we can free the space. + */ + + the_jnode->st_nlink--; + IMFS_update_ctime( the_jnode ); + + /* + * The file cannot be open and the link must be less than 1 to free. + */ + + if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) { + + /* + * Is the rtems_filesystem_current is this node? + */ + + if ( rtems_filesystem_current.node_access == pathloc->node_access ) + rtems_filesystem_current.node_access = NULL; + + /* + * Free memory associated with a memory file. + */ + + if ( the_jnode->type == IMFS_MEMORY_FILE ) + IMFS_memfile_remove( the_jnode ); + + free( the_jnode ); + } + + return 0; + +} + + diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c new file mode 100644 index 0000000000..4628736714 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_stat.c @@ -0,0 +1,59 @@ +/* + * IMFS_stat + * + * This routine provides a stat for the IMFS file system. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "imfs.h" +#include "libio_.h" + +int IMFS_stat( + rtems_filesystem_location_info_t *loc, + struct stat *buf +) +{ + IMFS_jnode_t *the_jnode; + IMFS_device_t *io; + + the_jnode = loc->node_access; + + + switch ( the_jnode->type ) { + + case IMFS_DEVICE: + io = &the_jnode->info.device; + buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor ); + break; + + case IMFS_MEMORY_FILE: + buf->st_size = the_jnode->info.file.size; + break; + + default: + set_errno_and_return_minus_one( ENOTSUP ); + break; + } + + buf->st_mode = the_jnode->st_mode; + buf->st_nlink = the_jnode->st_nlink; + buf->st_ino = the_jnode->st_ino; + buf->st_uid = the_jnode->st_uid; + buf->st_gid = the_jnode->st_gid; + + buf->st_atime = the_jnode->st_atime; + buf->st_mtime = the_jnode->st_mtime; + buf->st_ctime = the_jnode->st_ctime; + + return 0; +} diff --git a/cpukit/libfs/src/imfs/imfs_symlink.c b/cpukit/libfs/src/imfs/imfs_symlink.c new file mode 100644 index 0000000000..0d3ebbd670 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_symlink.c @@ -0,0 +1,60 @@ +/* + * IMFS_symlink + * + * The following rouine creates a new symbolic link node under parent + * with the name given in name. The node is set to point to the node at + * to_loc. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include "imfs.h" +#include "libio_.h" + +int IMFS_symlink( + rtems_filesystem_location_info_t *parent_loc, + const char *link_name, + const char *node_name +) +{ + IMFS_types_union info; + IMFS_jnode_t *new_node; + char new_name[ NAME_MAX + 1 ]; + int i; + + /* + * Remove any separators at the end of the string. + */ + + IMFS_get_token( node_name, new_name, &i ); + + info.sym_link.name = link_name; + + /* + * Create a new link node. + */ + + new_node = IMFS_create_node( + parent_loc, + IMFS_SYM_LINK, + new_name, + ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )), + &info + ); + + if ( !new_node ) + set_errno_and_return_minus_one( ENOMEM ); + + return 0; +} + + diff --git a/cpukit/libfs/src/imfs/imfs_unlink.c b/cpukit/libfs/src/imfs/imfs_unlink.c new file mode 100644 index 0000000000..4e0ca26b2a --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_unlink.c @@ -0,0 +1,67 @@ +/* + * IMFS_unlink + * + * Routine to remove a link node from the tree. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include <stdlib.h> + +#include "imfs.h" +#include "libio_.h" + +int IMFS_unlink( + rtems_filesystem_location_info_t *loc /* IN */ +) +{ + IMFS_jnode_t *node; + rtems_filesystem_location_info_t the_link; + int result; + + node = loc->node_access; + + /* + * Decrement the link counter of node pointed to and free the + * space. + */ + + /* + * If this is the last last pointer to the node + * free the node. + */ + + if ( node->type == IMFS_HARD_LINK ) { + + if ( !node->info.hard_link.link_node ) + set_errno_and_return_minus_one( EINVAL ); + + the_link = *loc; + the_link.node_access = node->info.hard_link.link_node; + + /* + * If this is the last referance to the node + * Free the node that the link points to. + */ + node->info.hard_link.link_node->st_nlink --; + IMFS_update_ctime( node->info.hard_link.link_node ); + if ( node->info.hard_link.link_node->st_nlink < 1) { + result = IMFS_rmnod( &the_link ); + if ( result != 0 ) + return -1; + } + } + + result = IMFS_rmnod( loc ); + + return result; +} diff --git a/cpukit/libfs/src/imfs/imfs_unmount.c b/cpukit/libfs/src/imfs/imfs_unmount.c new file mode 100644 index 0000000000..f29d720ab3 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_unmount.c @@ -0,0 +1,58 @@ +/* + * IMFS_unmount + * + * This routine will look at a mount table entry that we are going to + * add to the mount table. If the mount point + * rtems_filesystem_location_info_t struct refers to a node that is a + * directory that has a file system mounted on it, the node will be + * marked as a mount point by * setting its directory.mt_fs pointer + * to NULL. This indicates that a directory is no longer mounted on + * this node. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> + +#include "imfs.h" +#include "libio_.h" + +int IMFS_unmount( + rtems_filesystem_mount_table_entry_t *mt_entry +) +{ + IMFS_jnode_t *node; + + node = mt_entry->mt_point_node.node_access; + + /* + * Is the node that we are mounting onto a directory node ? + */ + + if ( node->type != IMFS_DIRECTORY ) + set_errno_and_return_minus_one( ENOTDIR ); + + /* + * Did the node indicate that there was a directory mounted here? + */ + + if ( node->info.directory.mt_fs == NULL ) + set_errno_and_return_minus_one( EINVAL ); /* XXX */ + + /* + * Set the mt_fs pointer to indicate that there is no longer + * a file system mounted to this point. + */ + + node->info.directory.mt_fs = NULL; + + return 0; +} diff --git a/cpukit/libfs/src/imfs/imfs_utime.c b/cpukit/libfs/src/imfs/imfs_utime.c new file mode 100644 index 0000000000..bc2639ef8c --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_utime.c @@ -0,0 +1,38 @@ +/* + * IMFS_utime + * + * This routine is the implementation of the utime() system + * call for the IMFS. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <errno.h> +#include <sys/time.h> + +#include "libio_.h" +#include "imfs.h" + +int IMFS_utime( + rtems_filesystem_location_info_t *pathloc, /* IN */ + time_t actime, /* IN */ + time_t modtime /* IN */ +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = (IMFS_jnode_t *) pathloc->node_access; + + the_jnode->st_atime = actime; + the_jnode->st_mtime = modtime; + + return 0; +} diff --git a/cpukit/libfs/src/imfs/ioman.c b/cpukit/libfs/src/imfs/ioman.c new file mode 100644 index 0000000000..f8b725e987 --- /dev/null +++ b/cpukit/libfs/src/imfs/ioman.c @@ -0,0 +1,83 @@ +/* + * This file emulates the old Classic RTEMS IO manager directives + * which register and lookup names using the in-memory filesystem. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include <assert.h> + +#include <rtems.h> +#include "libio_.h" +#include "imfs.h" + +/* + * rtems_io_register_name + * + * This assumes that all registered devices are character devices. + */ + +rtems_status_code rtems_io_register_name( + char *device_name, + rtems_device_major_number major, + rtems_device_minor_number minor +) +{ + int status; + dev_t dev; + + dev = rtems_filesystem_make_dev_t( major, minor ); + status = mknod( device_name, 0777 | S_IFCHR, dev ); + + /* this is the only error returned by the old version */ + if ( status ) + return RTEMS_TOO_MANY; + + return RTEMS_SUCCESSFUL; +} + +/* + * rtems_io_lookup_name + * + * This version is not reentrant. + */ + +rtems_status_code rtems_io_lookup_name( + const char *name, + rtems_driver_name_t **device_info +) +{ + IMFS_jnode_t *the_jnode; + rtems_filesystem_location_info_t temp_loc; + static rtems_driver_name_t device; + int result; + + result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE ); + the_jnode = temp_loc.node_access; + + if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) { + *device_info = 0; + return RTEMS_UNSATISFIED; + } + + device.device_name = (char *) name; + device.device_name_length = strlen( name ); + device.major = the_jnode->info.device.major; + device.minor = the_jnode->info.device.minor; + *device_info = &device; + return RTEMS_SUCCESSFUL; + +} diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c new file mode 100644 index 0000000000..01aee443f3 --- /dev/null +++ b/cpukit/libfs/src/imfs/memfile.c @@ -0,0 +1,1000 @@ +/* + * IMFS Device Node Handlers + * + * This file contains the set of handlers used to process operations on + * IMFS memory file nodes. The memory files are created in memory using + * malloc'ed memory. Thus any data stored in one of these files is lost + * at system shutdown unless special arrangements to copy the data to + * some type of non-volailte storage are made by the application. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <stdlib.h> +#include <assert.h> +#include <errno.h> + +#include <rtems.h> +#include <rtems/libio.h> +#include "imfs.h" +#include "libio_.h" + +#define MEMFILE_STATIC + +/* + * Prototypes of private routines + */ + +MEMFILE_STATIC int IMFS_memfile_extend( + IMFS_jnode_t *the_jnode, + off_t new_length +); + +MEMFILE_STATIC int IMFS_memfile_addblock( + IMFS_jnode_t *the_jnode, + unsigned int block +); + +MEMFILE_STATIC int IMFS_memfile_remove_block( + IMFS_jnode_t *the_jnode, + unsigned int block +); + +MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer( + IMFS_jnode_t *the_jnode, + unsigned int block, + int malloc_it +); + +MEMFILE_STATIC int IMFS_memfile_read( + IMFS_jnode_t *the_jnode, + off_t start, + unsigned char *destination, + unsigned int length +); + +MEMFILE_STATIC int IMFS_memfile_write( + IMFS_jnode_t *the_jnode, + off_t start, + const unsigned char *source, + unsigned int length +); + +void *memfile_alloc_block(void); + +void memfile_free_block( + void *memory +); + +/* + * memfile_open + * + * This routine processes the open() system call. Note that there is + * nothing special to be done at open() time. + */ + +int memfile_open( + rtems_libio_t *iop, + const char *pathname, + unsigned32 flag, + unsigned32 mode +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + return 0; +} + +/* + * memfile_close + * + * This routine processes the close() system call. Note that there is + * nothing to flush or memory to free at this point. + */ + +int memfile_close( + rtems_libio_t *iop +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + return 0; +} + +/* + * memfile_read + * + * This routine processes the read() system call. + */ + +int memfile_read( + rtems_libio_t *iop, + void *buffer, + unsigned32 count +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + return IMFS_memfile_read( the_jnode, iop->offset, buffer, count ); +} + +/* + * memfile_write + * + * This routine processes the write() system call. + */ + +int memfile_write( + rtems_libio_t *iop, + const void *buffer, + unsigned32 count +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + return IMFS_memfile_write( the_jnode, iop->offset, buffer, count ); +} + +/* + * memfile_ioctl + * + * This routine processes the ioctl() system call. + * + * NOTE: No ioctl()'s are supported for in-memory files. + */ + +int memfile_ioctl( + rtems_libio_t *iop, + unsigned32 command, + void *buffer +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + return 0; +} + +/* + * memfile_lseek + * + * This routine processes the lseek() system call. + */ + +int memfile_lseek( + rtems_libio_t *iop, + off_t offset, + int whence +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + if (IMFS_memfile_extend( the_jnode, iop->offset )) + set_errno_and_return_minus_one( ENOSPC ); + + return 0; +} + +/* + * memfile_stat + * + * This IMFS_stat() can be used. + */ + +/* + * memfile_ftruncate + * + * This routine processes the ftruncate() system call. + */ + +int memfile_ftruncate( + rtems_libio_t *iop, + off_t length +) +{ + IMFS_jnode_t *the_jnode; + + the_jnode = iop->file_info; + + /* + * POSIX 1003.1b does not specify what happens if you truncate a file + * and the new length is greater than the current size. We treat this + * as an extend operation. + */ + + if ( length > the_jnode->info.file.size ) + return IMFS_memfile_extend( the_jnode, length ); + + /* + * The in-memory files do not currently reclaim memory until the file is + * deleted. So we leave the previously allocated blocks in place for + * future use and just set the length. + */ + + the_jnode->info.file.size = length; + + IMFS_update_atime( the_jnode ); + + return 0; +} + +/* + * IMFS_memfile_extend + * + * This routine insures that the in-memory file is of the length + * specified. If necessary, it will allocate memory blocks to + * extend the file. + */ + +MEMFILE_STATIC int IMFS_memfile_extend( + IMFS_jnode_t *the_jnode, + off_t new_length +) +{ + unsigned int block; + unsigned int new_blocks; + unsigned int old_blocks; + + /* + * Perform internal consistency checks + */ + + assert( the_jnode ); + if ( !the_jnode ) + set_errno_and_return_minus_one( EIO ); + + assert( the_jnode->type == IMFS_MEMORY_FILE ); + if ( the_jnode->type != IMFS_MEMORY_FILE ) + set_errno_and_return_minus_one( EIO ); + + if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE ) + set_errno_and_return_minus_one( EINVAL ); + + if ( new_length <= the_jnode->info.file.size ) + return 0; + + /* + * Calculate the number of range of blocks to allocate + */ + + new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK; + old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK; + + /* + * Now allocate each of those blocks. + */ + + for ( block=old_blocks ; block<=new_blocks ; block++ ) { + if ( IMFS_memfile_addblock( the_jnode, block ) ) { + for ( ; block>=old_blocks ; block-- ) { + IMFS_memfile_remove_block( the_jnode, block ); + } + set_errno_and_return_minus_one( ENOSPC ); + } + } + + /* + * Set the new length of the file. + */ + + the_jnode->info.file.size = new_length; + return 0; +} + +/* + * IMFS_memfile_addblock + * + * This routine adds a single block to the specified in-memory file. + */ + +MEMFILE_STATIC int IMFS_memfile_addblock( + IMFS_jnode_t *the_jnode, + unsigned int block +) +{ + block_p memory; + block_p *block_entry_ptr; + + assert( the_jnode ); + if ( !the_jnode ) + set_errno_and_return_minus_one( EIO ); + + assert( the_jnode->type == IMFS_MEMORY_FILE ); + if ( the_jnode->type != IMFS_MEMORY_FILE ) + set_errno_and_return_minus_one( EIO ); + + block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 ); + if ( *block_entry_ptr ) + return 0; + +#if 0 + printf( "%d %p", block, block_entry_ptr ); + fflush(stdout); +#endif + + memory = memfile_alloc_block(); + assert( memory ); + if ( !memory ) + return 1; + *block_entry_ptr = memory; + + return 0; +} + +/* + * IMFS_memfile_remove_block + * + * This routine removes the specified block from the in-memory file. + * + * NOTE: This is a support routine and is called only to remove + * the last block or set of blocks in a file. Removing a + * block from the middle of a file would be exceptionally + * dangerous and the results unpredictable. + */ + +MEMFILE_STATIC int IMFS_memfile_remove_block( + IMFS_jnode_t *the_jnode, + unsigned int block +) +{ + block_p *block_entry_ptr; + block_p ptr; + + block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + ptr = *block_entry_ptr; + *block_entry_ptr = 0; + + memfile_free_block( ptr ); + + return 1; +} + +/* + * memfile_free_blocks_in_table + * + * This is a support routine for IMFS_memfile_remove. It frees all the + * blocks in one of the indirection tables. + */ + +void memfile_free_blocks_in_table( + block_p **block_table, + int entries +) +{ + int i; + block_p *b; + + /* + * Perform internal consistency checks + */ + + assert( block_table ); + if ( !block_table ) + return; + + /* + * Now go through all the slots in the table and free the memory. + */ + + b = *block_table; + + for ( i=0 ; i<entries ; i++ ) { + if ( b[i] ) { + memfile_free_block( b[i] ); + b[i] = 0; + } + } + + /* + * Now that all the blocks in the block table are free, we can + * free the block table itself. + */ + + memfile_free_block( *block_table ); + *block_table = 0; +} + +/* + * IMFS_memfile_remove + * + * This routine frees all memory associated with an in memory file. + * + * NOTE: This is an exceptionally conservative implementation. + * It will check EVERY pointer which is non-NULL and insure + * any child non-NULL pointers are freed. Optimistically, all that + * is necessary is to scan until a NULL pointer is found. There + * should be no allocated data past that point. + * + * In experimentation on the powerpc simulator, it was noted + * that using blocks which held 128 slots versus 16 slots made + * a significant difference in the performance of this routine. + * + * Regardless until the IMFS implementation is proven, it + * is better to stick to simple, easy to understand algorithms. + */ + +int IMFS_memfile_remove( + IMFS_jnode_t *the_jnode +) +{ + IMFS_memfile_t *info; + int i; + int j; + unsigned int to_free; + block_p *p; + + /* + * Perform internal consistency checks + */ + + assert( the_jnode ); + if ( !the_jnode ) + set_errno_and_return_minus_one( EIO ); + + assert( the_jnode->type == IMFS_MEMORY_FILE ); + if ( the_jnode->type != IMFS_MEMORY_FILE ) + set_errno_and_return_minus_one( EIO ); + + /* + * Eventually this could be set smarter at each call to + * memfile_free_blocks_in_table to greatly speed this up. + */ + + to_free = IMFS_MEMFILE_BLOCK_SLOTS; + + /* + * Now start freeing blocks in this order: + * + indirect + * + doubly indirect + * + triply indirect + */ + + info = &the_jnode->info.file; + + if ( info->indirect ) { + memfile_free_blocks_in_table( &info->indirect, to_free ); + } + + if ( info->doubly_indirect ) { + + for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) { + if ( info->doubly_indirect[i] ) { + memfile_free_blocks_in_table( + (block_p **)&info->doubly_indirect[i], to_free ); + } + } + memfile_free_blocks_in_table( &info->doubly_indirect, to_free ); + + } + + if ( info->triply_indirect ) { + for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) { + p = (block_p *) info->triply_indirect[i]; + for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) { + if ( p[j] ) { + memfile_free_blocks_in_table( (block_p **)&p[j], to_free); + } + } + memfile_free_blocks_in_table( + (block_p **)&info->triply_indirect[i], to_free ); + } + memfile_free_blocks_in_table( + (block_p **)&info->triply_indirect, to_free ); + } + + return 0; +} + +/* + * IMFS_memfile_read + * + * This routine read from memory file pointed to by the_jnode into + * the specified data buffer specified by destination. The file + * is NOT extended. An offset greater than the length of the file + * is considered an error. Read from an offset for more bytes than + * are between the offset and the end of the file will result in + * reading the data between offset and the end of the file (truncated + * read). + */ + +MEMFILE_STATIC int IMFS_memfile_read( + IMFS_jnode_t *the_jnode, + off_t start, + unsigned char *destination, + unsigned int length +) +{ + block_p *block_ptr; + unsigned int block; + unsigned int my_length; + unsigned int to_copy = 0; + unsigned int last_byte; + unsigned int copied; + unsigned int start_offset; + unsigned char *dest; + + dest = destination; + + /* + * Perform internal consistency checks + */ + + assert( the_jnode ); + if ( !the_jnode ) + set_errno_and_return_minus_one( EIO ); + + assert( the_jnode->type == IMFS_MEMORY_FILE ); + if ( the_jnode->type != IMFS_MEMORY_FILE ) + set_errno_and_return_minus_one( EIO ); + + /* + * Error checks on arguments + */ + + assert( dest ); + if ( !dest ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * If there is nothing to read, then quick exit. + */ + + my_length = length; + if ( !my_length ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * If the last byte we are supposed to read is past the end of this + * in memory file, then shorten the length to read. + */ + + last_byte = start + length; + if ( last_byte > the_jnode->info.file.size ) + my_length = the_jnode->info.file.size - start; + + copied = 0; + + /* + * Three phases to the read: + * + possibly the last part of one block + * + all of zero of more blocks + * + possibly the first part of one block + */ + + /* + * Phase 1: possibly the last part of one block + */ + + start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK; + block = start / IMFS_MEMFILE_BYTES_PER_BLOCK; + if ( start_offset ) { + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset; + if ( to_copy > my_length ) + to_copy = my_length; + block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + assert( block_ptr ); + if ( !block_ptr ) + return copied; + memcpy( dest, &(*block_ptr)[ start_offset ], to_copy ); + dest += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 2: all of zero of more blocks + */ + + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK; + while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) { + block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + assert( block_ptr ); + if ( !block_ptr ) + return copied; + memcpy( dest, &(*block_ptr)[ 0 ], to_copy ); + dest += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 3: possibly the first part of one block + */ + + assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK ); + + if ( my_length ) { + block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + assert( block_ptr ); + if ( !block_ptr ) + return copied; + memcpy( dest, &(*block_ptr)[ 0 ], my_length ); + copied += my_length; + } + + IMFS_update_atime( the_jnode ); + + return copied; +} + +/* + * IMFS_memfile_write + * + * This routine writes the specified data buffer into the in memory + * file pointed to by the_jnode. The file is extended as needed. + */ + +MEMFILE_STATIC int IMFS_memfile_write( + IMFS_jnode_t *the_jnode, + off_t start, + const unsigned char *source, + unsigned int length +) +{ + block_p *block_ptr; + unsigned int block; + int status; + unsigned int my_length; + unsigned int to_copy = 0; + unsigned int last_byte; + unsigned int start_offset; + int copied; + const unsigned char *src; + + src = source; + + /* + * Perform internal consistency checks + */ + + assert( the_jnode ); + if ( !the_jnode ) + set_errno_and_return_minus_one( EIO ); + + assert( the_jnode->type == IMFS_MEMORY_FILE ); + if ( the_jnode->type != IMFS_MEMORY_FILE ) + set_errno_and_return_minus_one( EIO ); + + /* + * Error check arguments + */ + + assert( source ); + if ( !source ) + set_errno_and_return_minus_one( EINVAL ); + + + /* + * If there is nothing to write, then quick exit. + */ + + my_length = length; + if ( !my_length ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * If the last byte we are supposed to write is past the end of this + * in memory file, then extend the length. + */ + + last_byte = start + length; + if ( last_byte > the_jnode->info.file.size ) { + status = IMFS_memfile_extend( the_jnode, last_byte ); + if ( status ) + set_errno_and_return_minus_one( ENOSPC ); + } + + copied = 0; + + /* + * Three phases to the write: + * + possibly the last part of one block + * + all of zero of more blocks + * + possibly the first part of one block + */ + + /* + * Phase 1: possibly the last part of one block + */ + + start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK; + block = start / IMFS_MEMFILE_BYTES_PER_BLOCK; + if ( start_offset ) { + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset; + if ( to_copy > my_length ) + to_copy = my_length; + block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + assert( block_ptr ); + if ( !block_ptr ) + return copied; + memcpy( &(*block_ptr)[ start_offset ], src, to_copy ); + src += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 2: all of zero of more blocks + */ + + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK; + while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) { + block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + assert( block_ptr ); + if ( !block_ptr ) + return copied; + memcpy( &(*block_ptr)[ 0 ], src, to_copy ); + src += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 3: possibly the first part of one block + */ + + assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK ); + + to_copy = my_length; + if ( my_length ) { + block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 ); + assert( block_ptr ); + if ( !block_ptr ) + return copied; + memcpy( &(*block_ptr)[ 0 ], src, my_length ); + my_length = 0; + copied += to_copy; + } + + IMFS_atime_mtime_update( the_jnode ); + + return copied; +} + +/* + * IMFS_memfile_get_block_pointer + * + * This routine looks up the block pointer associated with the given block + * number. If that block has not been allocated and "malloc_it" is + * TRUE, then the block is allocated. Otherwise, it is an error. + */ + +block_p *IMFS_memfile_get_block_pointer( + IMFS_jnode_t *the_jnode, + unsigned int block, + int malloc_it +) +{ + unsigned int my_block; + IMFS_memfile_t *info; + unsigned int singly; + unsigned int doubly; + unsigned int triply; + block_p *p; + block_p *p1; + block_p *p2; + + /* + * Perform internal consistency checks + */ + + assert( the_jnode ); + if ( !the_jnode ) + return NULL; + + assert( the_jnode->type == IMFS_MEMORY_FILE ); + if ( the_jnode->type != IMFS_MEMORY_FILE ) + return NULL; + + info = &the_jnode->info.file; + + my_block = block; + + /* + * Is the block number in the simple indirect portion? + */ + + if ( my_block <= LAST_INDIRECT ) { +#if 0 +printf( "(s %d) ", block ); +fflush(stdout); +#endif + p = info->indirect; + + if ( malloc_it ) { + + if ( !p ) { + p = memfile_alloc_block(); + if ( !p ) + return 0; + info->indirect = p; + } + return &info->indirect[ my_block ]; + } + + if ( !p ) + return 0; + + return &info->indirect[ my_block ]; + } + + /* + * Is the block number in the doubly indirect portion? + */ + + if ( my_block <= LAST_DOUBLY_INDIRECT ) { +#if 0 +printf( "(d %d) ", block ); +fflush(stdout); +#endif + + my_block -= FIRST_DOUBLY_INDIRECT; + + singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS; + doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS; + + p = info->doubly_indirect; + if ( malloc_it ) { + + if ( !p ) { + p = memfile_alloc_block(); + if ( !p ) + return 0; + info->doubly_indirect = p; + } + + p1 = (block_p *)p[ doubly ]; + if ( !p1 ) { + p1 = memfile_alloc_block(); + if ( !p1 ) + return 0; + p[ doubly ] = (block_p) p1; + } + + return (block_p *)&p[ singly ]; + } + + if ( !p ) + return 0; + + p = (block_p *)p[ doubly ]; + if ( !p ) + return 0; + +#if 0 +printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly, + singly, p, &p[singly] ); +fflush(stdout); +#endif + return (block_p *)&p[ singly ]; + } + +#if 0 +printf( "(t %d) ", block ); +fflush(stdout); +#endif + /* + * Is the block number in the triply indirect portion? + */ + + if ( my_block <= LAST_TRIPLY_INDIRECT ) { + my_block -= FIRST_TRIPLY_INDIRECT; + + singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS; + doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS; + triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS; + doubly %= IMFS_MEMFILE_BLOCK_SLOTS; + + p = info->triply_indirect; + + if ( malloc_it ) { + if ( !p ) { + p = memfile_alloc_block(); + if ( !p ) + return 0; + info->triply_indirect = p; + } + + p1 = (block_p *) p[ triply ]; + if ( !p1 ) { + p1 = memfile_alloc_block(); + if ( !p1 ) + return 0; + p[ triply ] = (block_p) p1; + } + + p2 = (block_p *)p1[ doubly ]; + if ( !p2 ) { + p2 = memfile_alloc_block(); + if ( !p2 ) + return 0; + p1[ doubly ] = (block_p) p2; + } + return (block_p *)&p2[ singly ]; + } + + if ( !p ) + return 0; + +#if 0 +printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly ); +fflush(stdout); +#endif + p1 = (block_p *) p[ triply ]; + if ( !p1 ) + return 0; + + p2 = (block_p *)p1[ doubly ]; + if ( !p ) + return 0; + + return (block_p *)&p2[ singly ]; + } + + /* + * This means the requested block number is out of range. + */ + + return 0; +} + +/* + * memfile_alloc_block + * + * Allocate a block for an in-memory file. + */ + +int memfile_blocks_allocated = 0; + +void *memfile_alloc_block(void) +{ + void *memory; + + memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK); + if ( memory ) + memfile_blocks_allocated++; + + return memory; +} + +/* + * memfile_free_blocK + * + * Free a block from an in-memory file. + */ + +void memfile_free_block( + void *memory +) +{ +#if 0 +printf( "(d %p) ", memory ); +fflush(stdout); +#endif + free(memory); + memfile_blocks_allocated--; +} + diff --git a/cpukit/posix/src/getpid.c b/cpukit/posix/src/getpid.c index b42981398a..8e912adf39 100644 --- a/cpukit/posix/src/getpid.c +++ b/cpukit/posix/src/getpid.c @@ -20,3 +20,22 @@ pid_t getpid( void ) { return _Objects_Local_node; } + +/* + * _getpid_r + * + * This is the Newlib dependent reentrant version of getpid(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +pid_t _getpid_r( + struct _reent *ptr +) +{ + return getpid(); +} +#endif + diff --git a/cpukit/posix/src/psignal.c b/cpukit/posix/src/psignal.c index 5db634a924..1450164021 100644 --- a/cpukit/posix/src/psignal.c +++ b/cpukit/posix/src/psignal.c @@ -1222,6 +1222,26 @@ int kill( } /* + * _kill_r + * + * This is the Newlib dependent reentrant version of kill(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _kill_r( + struct _reent *ptr, + pid_t pid, + int sig +) +{ + return kill( pid, sig ); +} +#endif + +/* * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 */ diff --git a/cpukit/sapi/src/io.c b/cpukit/sapi/src/io.c index 92de490885..d6e669c4fc 100644 --- a/cpukit/sapi/src/io.c +++ b/cpukit/sapi/src/io.c @@ -92,6 +92,7 @@ void _IO_Initialize_all_drivers( void ) * error code - if unsuccessful */ +#if 0 rtems_status_code rtems_io_register_name( char *device_name, rtems_device_major_number major, @@ -124,6 +125,7 @@ rtems_status_code rtems_io_register_name( return RTEMS_TOO_MANY; } +#endif /*PAGE * @@ -140,6 +142,7 @@ rtems_status_code rtems_io_register_name( * error code - if unsuccessful */ +#if 0 rtems_status_code rtems_io_lookup_name( const char *name, rtems_driver_name_t **device_info @@ -161,6 +164,7 @@ rtems_status_code rtems_io_lookup_name( *device_info = 0; return RTEMS_UNSATISFIED; } +#endif /*PAGE |