Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief This header file defines the API of the In-Memory File System.
0007  */
0008 
0009 /*
0010  * COPYRIGHT (C) 1989, 2021 On-Line Applications Research Corporation (OAR).
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 #ifndef _RTEMS_IMFS_H
0035 #define _RTEMS_IMFS_H
0036 
0037 #include <sys/time.h>
0038 #include <limits.h>
0039 
0040 #include <rtems/libio_.h>
0041 #include <rtems/pipe.h>
0042 
0043 /**
0044  * @brief In-Memory File System Support.
0045  *
0046  * @defgroup IMFS In-Memory File System Support
0047  *
0048  * @ingroup FileSystemTypesAndMount
0049  */
0050 /**@{*/
0051 
0052 #ifdef __cplusplus
0053 extern "C" {
0054 #endif
0055 
0056 /*
0057  *  Data types
0058  */
0059 
0060 struct IMFS_jnode_tt;
0061 typedef struct IMFS_jnode_tt IMFS_jnode_t;
0062 
0063 /**
0064  *  IMFS "memfile" information
0065  *
0066  *  The data structure for the in-memory "memfiles" is based on classic UNIX.
0067  *
0068  *  block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
0069  *  length which could be data or a table of pointers to blocks.
0070  *
0071  *  Setting IMFS_MEMFILE_BYTES_PER_BLOCK to different values has a significant
0072  *  impact on the maximum file size supported as well as the amount of
0073  *  memory wasted due to internal file fragmentation.  The following
0074  *  is a list of maximum file sizes based on various settings
0075  *
0076  *  @code
0077  *    max_filesize with blocks of   16 is         1,328
0078  *    max_filesize with blocks of   32 is        18,656
0079  *    max_filesize with blocks of   64 is       279,488
0080  *    max_filesize with blocks of  128 is     4,329,344
0081  *    max_filesize with blocks of  256 is    68,173,568
0082  *    max_filesize with blocks of  512 is 1,082,195,456
0083  *  @endcode
0084  */
0085 #define IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK     128
0086   extern const int imfs_memfile_bytes_per_block;
0087 
0088 #define IMFS_MEMFILE_BYTES_PER_BLOCK imfs_memfile_bytes_per_block
0089 #define IMFS_MEMFILE_BLOCK_SLOTS \
0090   (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
0091 
0092 typedef uint8_t *block_p;
0093 typedef block_p *block_ptr;
0094 
0095 /*
0096  *  Important block numbers for "memfiles"
0097  */
0098 #define FIRST_INDIRECT           (0)
0099 #define LAST_INDIRECT            (IMFS_MEMFILE_BLOCK_SLOTS - 1)
0100 
0101 #define FIRST_DOUBLY_INDIRECT    (LAST_INDIRECT + 1)
0102 #define LAST_DOUBLY_INDIRECT     \
0103    (LAST_INDIRECT + \
0104      (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
0105 
0106 #define FIRST_TRIPLY_INDIRECT    (LAST_DOUBLY_INDIRECT + 1)
0107 #define LAST_TRIPLY_INDIRECT \
0108    (LAST_DOUBLY_INDIRECT +\
0109      (IMFS_MEMFILE_BLOCK_SLOTS * \
0110         IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
0111 
0112 #define IMFS_MEMFILE_MAXIMUM_SIZE \
0113   (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
0114 
0115 /** @} */
0116 
0117 /**
0118  * @addtogroup IMFSGenericNodes
0119  */
0120 /**@{*/
0121 
0122 /**
0123  * @brief Initializes an IMFS node.
0124  *
0125  * @param[in] node The IMFS node.
0126  * @param[in] arg The user provided argument pointer.  It may contain node
0127  *   specific initialization information.
0128  *
0129  * @retval node Successful operation.
0130  * @retval NULL An error occurred.  The @c errno indicates the error.  This
0131  * will abort the make operation.
0132  *
0133  * @see IMFS_node_control, IMFS_node_initialize_default(), and
0134  * IMFS_node_initialize_generic().
0135  */
0136 typedef IMFS_jnode_t *(*IMFS_node_control_initialize)(
0137   IMFS_jnode_t *node,
0138   void *arg
0139 );
0140 
0141 /**
0142  * @brief Returns the node and does nothing else.
0143  *
0144  * @param[in] node The IMFS node.
0145  * @param[in] arg The user provided argument pointer.  It is not used.
0146  *
0147  * @retval node Returns always the node passed as parameter.
0148  *
0149  * @see IMFS_node_control.
0150  */
0151 IMFS_jnode_t *IMFS_node_initialize_default(
0152   IMFS_jnode_t *node,
0153   void *arg
0154 );
0155 
0156 IMFS_jnode_t *IMFS_node_initialize_directory(
0157   IMFS_jnode_t *node,
0158   void *arg
0159 );
0160 
0161 /**
0162  * @brief Returns the node and sets the generic node context.
0163  *
0164  * @param[in] node The IMFS node.
0165  * @param[in] arg The user provided argument pointer.  It must contain the
0166  *   generic context.
0167  *
0168  * @retval node Returns always the node passed as parameter.
0169  *
0170  * @see IMFS_node_control.
0171  */
0172 IMFS_jnode_t *IMFS_node_initialize_generic(
0173   IMFS_jnode_t *node,
0174   void *arg
0175 );
0176 
0177 /**
0178  * @brief Prepares the removal of an IMFS node from its parent directory.
0179  *
0180  * @param[in] node The IMFS node.
0181  *
0182  * @retval node Successful operation.
0183  * @retval NULL An error occurred.  The @c errno indicates the error.  This
0184  * will abort the removal operation.
0185  *
0186  * @see IMFS_node_control and IMFS_node_remove_default().
0187  */
0188 typedef IMFS_jnode_t *(*IMFS_node_control_remove)(
0189   IMFS_jnode_t *node
0190 );
0191 
0192 /**
0193  * @brief Returns the node and does nothing else.
0194  *
0195  * @param[in] node The IMFS node.
0196  *
0197  * @retval node Returns always the node passed as parameter.
0198  *
0199  * @see IMFS_node_control.
0200  */
0201 IMFS_jnode_t *IMFS_node_remove_default(
0202   IMFS_jnode_t *node
0203 );
0204 
0205 IMFS_jnode_t *IMFS_node_remove_directory( IMFS_jnode_t *node );
0206 
0207 /**
0208  * @brief Destroys an IMFS node.
0209  *
0210  * @param[in] node The IMFS node.
0211  *
0212  * @see IMFS_node_control and IMFS_node_destroy_default().
0213  */
0214 typedef void (*IMFS_node_control_destroy)( IMFS_jnode_t *node );
0215 
0216 /**
0217  * @brief Frees the node.
0218  *
0219  * @param[in] node The IMFS node.
0220  *
0221  * @see IMFS_node_control.
0222  */
0223 void IMFS_node_destroy_default( IMFS_jnode_t *node );
0224 
0225 /**
0226  * @brief Does nothing.
0227  *
0228  * @param node The IMFS node.
0229  *
0230  * @see IMFS_node_control.
0231  */
0232 void IMFS_do_nothing_destroy( IMFS_jnode_t *node );
0233 
0234 /**
0235  * @brief IMFS node control.
0236  */
0237 typedef struct {
0238   const rtems_filesystem_file_handlers_r *handlers;
0239   IMFS_node_control_initialize node_initialize;
0240   IMFS_node_control_remove node_remove;
0241   IMFS_node_control_destroy node_destroy;
0242 } IMFS_node_control;
0243 
0244 typedef struct {
0245   IMFS_node_control node_control;
0246   size_t node_size;
0247 } IMFS_mknod_control;
0248 
0249 /** @} */
0250 
0251 /**
0252  * @addtogroup IMFS
0253  */
0254 /**@{*/
0255 
0256 /*
0257  *  Maximum length of a "basename" of an IMFS file/node.
0258  */
0259 
0260 #define IMFS_NAME_MAX _POSIX_NAME_MAX
0261 
0262 /*
0263 
0264  *  The control structure for an IMFS jnode.
0265  */
0266 
0267 struct IMFS_jnode_tt {
0268   rtems_chain_node    Node;                  /* for chaining them together */
0269   IMFS_jnode_t       *Parent;                /* Parent node */
0270   const char         *name;                  /* "basename" (not \0 terminated) */
0271   uint16_t            namelen;               /* Length of "basename" */
0272   mode_t              st_mode;               /* File mode */
0273   unsigned short      reference_count;
0274   nlink_t             st_nlink;              /* Link count */
0275 
0276   uid_t               st_uid;                /* User ID of owner */
0277   gid_t               st_gid;                /* Group ID of owner */
0278 
0279   time_t              stat_atime;            /* Time of last access */
0280   time_t              stat_mtime;            /* Time of last modification */
0281   time_t              stat_ctime;            /* Time of last status change */
0282   const IMFS_node_control *control;
0283 };
0284 
0285 typedef struct {
0286   IMFS_jnode_t                          Node;
0287   rtems_chain_control                   Entries;
0288   rtems_filesystem_mount_table_entry_t *mt_fs;
0289 } IMFS_directory_t;
0290 
0291 typedef struct {
0292   IMFS_jnode_t              Node;
0293   rtems_device_major_number major;
0294   rtems_device_minor_number minor;
0295 } IMFS_device_t;
0296 
0297 typedef struct {
0298   IMFS_jnode_t  Node;
0299   IMFS_jnode_t *link_node;
0300 } IMFS_link_t;
0301 
0302 typedef struct {
0303   IMFS_jnode_t  Node;
0304   char         *name;
0305 } IMFS_sym_link_t;
0306 
0307 typedef struct {
0308   IMFS_jnode_t Node;
0309   size_t       size;             /* size of file in bytes */
0310 } IMFS_filebase_t;
0311 
0312 typedef struct {
0313   IMFS_filebase_t File;
0314   block_ptr       indirect;         /* array of 128 data blocks pointers */
0315   block_ptr       doubly_indirect;  /* 128 indirect blocks */
0316   block_ptr       triply_indirect;  /* 128 doubly indirect blocks */
0317 } IMFS_memfile_t;
0318 
0319 typedef struct {
0320   IMFS_filebase_t File;
0321   block_p         direct;           /* pointer to file image */
0322 } IMFS_linearfile_t;
0323 
0324 /* Support copy on write for linear files */
0325 typedef union {
0326   IMFS_jnode_t      Node;
0327   IMFS_filebase_t   File;
0328   IMFS_memfile_t    Memfile;
0329   IMFS_linearfile_t Linearfile;
0330 } IMFS_file_t;
0331 
0332 typedef struct {
0333   IMFS_jnode_t    Node;
0334   pipe_control_t *pipe;
0335 } IMFS_fifo_t;
0336 
0337 typedef struct {
0338   IMFS_jnode_t  Node;
0339   void         *context;
0340 } IMFS_generic_t;
0341 
0342 typedef struct {
0343   const void *data;
0344   size_t      size;
0345 } IMFS_linearfile_context;
0346 
0347 static inline IMFS_jnode_t *IMFS_iop_to_node( const rtems_libio_t *iop )
0348 {
0349   return (IMFS_jnode_t *) iop->pathinfo.node_access;
0350 }
0351 
0352 static inline IMFS_directory_t *IMFS_iop_to_directory(
0353   const rtems_libio_t *iop
0354 )
0355 {
0356   return (IMFS_directory_t *) iop->pathinfo.node_access;
0357 }
0358 
0359 static inline IMFS_device_t *IMFS_iop_to_device( const rtems_libio_t *iop )
0360 {
0361   return (IMFS_device_t *) iop->pathinfo.node_access;
0362 }
0363 
0364 static inline IMFS_file_t *IMFS_iop_to_file( const rtems_libio_t *iop )
0365 {
0366   return (IMFS_file_t *) iop->pathinfo.node_access;
0367 }
0368 
0369 static inline IMFS_memfile_t *IMFS_iop_to_memfile( const rtems_libio_t *iop )
0370 {
0371   return (IMFS_memfile_t *) iop->pathinfo.node_access;
0372 }
0373 
0374 typedef struct {
0375   const IMFS_mknod_control *directory;
0376   const IMFS_mknod_control *device;
0377   const IMFS_mknod_control *file;
0378   const IMFS_mknod_control *fifo;
0379 } IMFS_mknod_controls;
0380 
0381 typedef struct {
0382   IMFS_directory_t Root_directory;
0383   const IMFS_mknod_controls *mknod_controls;
0384 } IMFS_fs_info_t;
0385 
0386 typedef struct {
0387   IMFS_fs_info_t *fs_info;
0388   const rtems_filesystem_operations_table *ops;
0389   const IMFS_mknod_controls *mknod_controls;
0390 } IMFS_mount_data;
0391 
0392 /*
0393  *  Shared Data
0394  */
0395 
0396 extern const IMFS_mknod_control IMFS_mknod_control_dir_default;
0397 extern const IMFS_mknod_control IMFS_mknod_control_dir_minimal;
0398 extern const IMFS_mknod_control IMFS_mknod_control_device;
0399 extern const IMFS_mknod_control IMFS_mknod_control_memfile;
0400 extern const IMFS_node_control IMFS_node_control_linfile;
0401 extern const IMFS_mknod_control IMFS_mknod_control_fifo;
0402 extern const IMFS_mknod_control IMFS_mknod_control_enosys;
0403 
0404 extern const rtems_filesystem_limits_and_options_t  IMFS_LIMITS_AND_OPTIONS;
0405 
0406 /*
0407  *  Routines
0408  */
0409 
0410 extern int IMFS_initialize(
0411    rtems_filesystem_mount_table_entry_t *mt_entry,
0412    const void                           *data
0413 );
0414 
0415 extern int IMFS_initialize_support(
0416   rtems_filesystem_mount_table_entry_t *mt_entry,
0417   const void                           *data
0418 );
0419 
0420 /**
0421  * @brief Unmount this instance of IMFS.
0422  */
0423 extern void IMFS_fsunmount(
0424    rtems_filesystem_mount_table_entry_t *mt_entry
0425 );
0426 
0427 /**
0428  * @brief RTEMS load tarfs.
0429  * 
0430  * This file implements the "mount" procedure for tar-based IMFS
0431  * extensions.  The TAR is not actually mounted under the IMFS.
0432  * Directories from the TAR file are created as usual in the IMFS.
0433  * File entries are created as IMFS_LINEAR_FILE nodes with their nods
0434  * pointing to addresses in the TAR image.
0435  *
0436  * Here we create the mountpoint directory and load the tarfs at
0437  * that node.  Once the IMFS has been mounted, we work through the
0438  * tar image and perform as follows:
0439  *  - For directories, simply call mkdir().  The IMFS creates nodes as
0440  *    needed.
0441  *  - For files, we make our own calls to IMFS eval_for_make and
0442  *    create_node.
0443  * 
0444  * TAR file format:
0445  *
0446  * @code
0447  *   Offset   Length                 Contents
0448  *     0    100  bytes  File name ('\0' terminated, 99 maxmum length)
0449  *   100      8  bytes  File mode (in octal ascii)
0450  *   108      8  bytes  User ID (in octal ascii)
0451  *   116      8  bytes  Group ID (in octal ascii)
0452  *   124     12  bytes  File size (s) (in octal ascii)
0453  *   136     12  bytes  Modify time (in octal ascii)
0454  *   148      8  bytes  Header checksum (in octal ascii)
0455  *   156      1  bytes  Link flag
0456  *   157    100  bytes  Linkname ('\0' terminated, 99 maxmum length)
0457  *   257      8  bytes  Magic PAX ("ustar\0" + 2 bytes padding)
0458  *   257      8  bytes  Magic GNU tar ("ustar  \0")
0459  *   265     32  bytes  User name ('\0' terminated, 31 maxmum length)
0460  *   297     32  bytes  Group name ('\0' terminated, 31 maxmum length)
0461  *   329      8  bytes  Major device ID (in octal ascii)
0462  *   337      8  bytes  Minor device ID (in octal ascii)
0463  *   345    167  bytes  Padding
0464  *   512   (s+p) bytes  File contents (s+p) := (((s) + 511) & ~511),
0465  *                      round up to 512 bytes
0466  * @endcode
0467  *
0468  *  Checksum:
0469  *  @code
0470  *    int   i, sum;
0471  *    char *header = tar_header_pointer;
0472  *
0473  *    sum = 0;
0474  *    for (i = 0; i < 512; i++)
0475  *        sum += 0xFF & header[i];
0476  * @endcode
0477  */
0478 extern int rtems_tarfs_load(
0479    const char *mountpoint,
0480    const void *tar_image,
0481    size_t tar_size
0482 );
0483 
0484 /**
0485  * @brief Destroy an IMFS node.
0486  */
0487 extern void IMFS_node_destroy( IMFS_jnode_t *node );
0488 
0489 /**
0490  * @brief Clone an IMFS node.
0491  */
0492 extern int IMFS_node_clone( rtems_filesystem_location_info_t *loc );
0493 
0494 /**
0495  * @brief Free an IMFS node.
0496  */
0497 extern void IMFS_node_free( const rtems_filesystem_location_info_t *loc );
0498 
0499 /**
0500  * @brief Perform a status processing for the IMFS.
0501  * 
0502  * This routine provides a stat for the IMFS file system.
0503  */
0504 extern int IMFS_stat(
0505   const rtems_filesystem_location_info_t *loc,
0506   struct stat *buf
0507 );
0508 
0509 extern int IMFS_stat_file(
0510   const rtems_filesystem_location_info_t *loc,
0511   struct stat *buf
0512 );
0513 
0514 /**
0515  * @brief IMFS evaluation node support.
0516  */
0517 extern void IMFS_eval_path(
0518   rtems_filesystem_eval_path_context_t *ctx
0519 );
0520 
0521 /**
0522  * @brief IMFS device filesystem evaluation node support.
0523  */
0524 extern void IMFS_eval_path_devfs(
0525   rtems_filesystem_eval_path_context_t *ctx
0526 );
0527 
0528 /**
0529  * @brief Create a new IMFS link node.
0530  * 
0531  * The following rouine creates a new link node under parent with the
0532  * name given in name.  The link node is set to point to the node at
0533  * to_loc.
0534  */
0535 extern int IMFS_link(
0536   const rtems_filesystem_location_info_t *parentloc,
0537   const rtems_filesystem_location_info_t *targetloc,
0538   const char *name,
0539   size_t namelen
0540 );
0541 
0542 /**
0543  * @brief Change the owner of IMFS.
0544  * 
0545  * This routine is the implementation of the chown() system
0546  * call for the IMFS.
0547  */
0548 extern int IMFS_chown(
0549   const rtems_filesystem_location_info_t *loc,
0550   uid_t owner,
0551   gid_t group
0552 );
0553 
0554 /**
0555  * @brief Create an IMFS node.
0556  * 
0557  * Routine to create a node in the IMFS file system.
0558  */
0559 extern int IMFS_mknod(
0560   const rtems_filesystem_location_info_t *parentloc,
0561   const char *name,
0562   size_t namelen,
0563   mode_t mode,
0564   dev_t dev
0565 );
0566 
0567 extern IMFS_jnode_t *IMFS_initialize_node(
0568   IMFS_jnode_t *node,
0569   const IMFS_node_control *node_control,
0570   const char *name,
0571   size_t namelen,
0572   mode_t mode,
0573   void *arg
0574 );
0575 
0576 /**
0577  * @brief Create an IMFS node.
0578  * 
0579  * Create an IMFS filesystem node of an arbitrary type that is NOT
0580  * the root directory node.
0581  */
0582 extern IMFS_jnode_t *IMFS_create_node(
0583   const rtems_filesystem_location_info_t *parentloc,
0584   const IMFS_node_control *node_control,
0585   size_t node_size,
0586   const char *name,
0587   size_t namelen,
0588   mode_t mode,
0589   void *arg
0590 );
0591 
0592 static inline bool IMFS_is_imfs_instance(
0593   const rtems_filesystem_location_info_t *loc
0594 )
0595 {
0596   return loc->mt_entry->ops->clonenod_h == IMFS_node_clone;
0597 }
0598 
0599 /**
0600  * @brief Initializer for an IMFS node control.
0601  *
0602  * @param handlers The file system node handlers.
0603  * @param init The node initialization method.
0604  * @param destroy The node destruction method.
0605  */
0606 #define IMFS_NODE_CONTROL_INITIALIZER( handlers, init, destroy ) \
0607   { \
0608     ( handlers ), \
0609     ( init ), \
0610     IMFS_node_remove_default, \
0611     ( destroy ) \
0612   }
0613 
0614 /**
0615  * @brief Initializer for an IMFS node.
0616  *
0617  * Initialize the node control with IMFS_NODE_CONTROL_INITIALIZER().
0618  *
0619  * @param node_control The node control of the IMFS node.
0620  * @param name The name of the IMFS node.
0621  * @param namelen The length of the name of the IMFS node.
0622  * @param mode The mode of the IMFS node.
0623  *
0624  * @see IMFS_node_preinitialize().
0625  */
0626 #define IMFS_NODE_INITIALIZER( node_control, name, namelen, mode ) \
0627   { \
0628     { NULL, NULL }, \
0629     NULL, \
0630     ( name ), \
0631     ( namelen ), \
0632     ( mode ), \
0633     0, \
0634     0, \
0635     0, \
0636     0, \
0637     0, \
0638     0, \
0639     0, \
0640     ( node_control ) \
0641   }
0642 
0643 /**
0644  * @brief Preinitializes an IMFS node.
0645  *
0646  * Initialize the node control with IMFS_NODE_CONTROL_INITIALIZER().
0647  *
0648  * @param node The IMFS node to preinitialize.
0649  * @param node_control The node control of the IMFS node.
0650  * @param name The name of the IMFS node.
0651  * @param namelen The length of the name of the IMFS node.
0652  * @param mode The mode of the IMFS node.
0653  *
0654  * @see IMFS_NODE_INITIALIZER().
0655  */
0656 static inline void IMFS_node_preinitialize(
0657   IMFS_jnode_t            *node,
0658   const IMFS_node_control *node_control,
0659   const char              *name,
0660   size_t                   namelen,
0661   mode_t                   mode
0662 )
0663 {
0664   node->control = node_control;
0665   node->name = name;
0666   node->namelen = namelen;
0667   node->st_mode = mode;
0668 }
0669 
0670 /**
0671  * @brief Adds an IMFS node.
0672  *
0673  * Initialize the node with IMFS_NODE_INITIALIZER(), IMFS_node_preinitialize(),
0674  * IMFS_GENERIC_NODE_INITIALIZER(), or IMFS_generic_node_preinitialize().
0675  *
0676  * @param path The path of parent directories for the IMFS node to add.
0677  * @param node The IMFS node to add.
0678  * @param arg The argument passed to the node initialization method.
0679  *
0680  * @retval 0 Successful operation.
0681  * @retval -1 An error occurred.  The @c errno indicates the error.
0682  */
0683 int IMFS_add_node( const char *path, IMFS_jnode_t *node, void *arg );
0684 
0685 extern int IMFS_make_node(
0686   const char              *path,
0687   mode_t                   mode,
0688   const IMFS_node_control *node_control,
0689   size_t                   node_size,
0690   void                    *context
0691 );
0692 
0693 /**
0694  * @brief Makes a linear IMFS file.
0695  *
0696  * @param path The path to the new linear IMFS file.
0697  * @param mode The file mode permissions.  S_IFREG is set by the function.
0698  * @param data The begin of linear file data area.
0699  * @param size The size of the linear file data area in bytes.
0700  *
0701  * @retval 0 Successful operation.
0702  * @retval -1 An error occurred.  The @c errno indicates the error.
0703  */
0704 extern int IMFS_make_linearfile(
0705   const char *path,
0706   mode_t      mode,
0707   const void *data,
0708   size_t      size
0709 );
0710 
0711 /** @} */
0712 
0713 /**
0714  * @defgroup IMFSGenericNodes IMFS Generic Nodes
0715  *
0716  * @ingroup LibIO
0717  *
0718  * @brief Generic nodes are an alternative to standard drivers in RTEMS.
0719  *
0720  * The handlers of a generic node are called with less overhead compared to the
0721  * standard driver operations.  The usage of file system node handlers enable
0722  * more features like support for fsync() and fdatasync().  The generic nodes
0723  * use the reference counting of the IMFS.  This provides automatic node
0724  * destruction when the last reference vanishes.
0725  *
0726  * @{
0727  */
0728 
0729 /* Provided for backward compatibility */
0730 #define IMFS_GENERIC_INITIALIZER( handlers, init, destroy ) \
0731   IMFS_NODE_CONTROL_INITIALIZER( handlers, init, destroy )
0732 
0733 /**
0734  * @brief Initializer for a generic node control.
0735  *
0736  * @param handlers The file system node handlers.
0737  * @param init The node initialization method.
0738  * @param destroy The node destruction method.
0739  */
0740 #define IMFS_GENERIC_CONTROL_INITIALIZER( handlers, init, destroy ) \
0741   IMFS_NODE_CONTROL_INITIALIZER( handlers, init, destroy )
0742 
0743 /**
0744  * @brief Initializer for a generic node.
0745  *
0746  * Initialize the node control with IMFS_GENERIC_CONTROL_INITIALIZER().
0747  *
0748  * @param node_control The node control of the IMFS generic node.
0749  * @param name The name of the IMFS generic node.
0750  * @param namelen The length of the name of the IMFS generic node.
0751  * @param mode The mode of the IMFS generic node.
0752  */
0753 #define IMFS_GENERIC_NODE_INITIALIZER( node_control, name, namelen, mode ) \
0754   { IMFS_NODE_INITIALIZER( node_control, name, namelen, mode ), NULL }
0755 
0756 /**
0757  * @brief Preinitializes a generic IMFS node.
0758  *
0759  * Initialize the node control with IMFS_GENERIC_CONTROL_INITIALIZER().
0760  *
0761  * @param node The generic IMFS node to preinitialize.
0762  * @param node_control The node control of the generic IMFS node.
0763  * @param name The name of the generic IMFS node.
0764  * @param namelen The length of the name of the generic IMFS node.
0765  * @param mode The mode of the generic IMFS node.
0766  *
0767  * @see IMFS_GENERIC_NODE_INITIALIZER().
0768  */
0769 static inline void IMFS_generic_node_preinitialize(
0770   IMFS_generic_t          *node,
0771   const IMFS_node_control *node_control,
0772   const char              *name,
0773   size_t                   namelen,
0774   mode_t                   mode
0775 )
0776 {
0777   IMFS_node_preinitialize( &node->Node, node_control, name, namelen, mode );
0778 }
0779 
0780 /**
0781  * @brief Makes a generic IMFS node.
0782  *
0783  * @param[in] path The path to the new generic IMFS node.
0784  * @param[in] mode The node mode.
0785  * @param[in] node_control The node control.
0786  * @param[in] context The node control handler context.
0787  *
0788  * @retval 0 Successful operation.
0789  * @retval -1 An error occurred.  The @c errno indicates the error.
0790  *
0791  * @code
0792  * #include <sys/stat.h>
0793  * #include <assert.h>
0794  * #include <fcntl.h>
0795  *
0796  * #include <rtems/imfs.h>
0797  *
0798  * static const rtems_filesystem_file_handlers_r some_node_handlers = {
0799  *   ...
0800  * };
0801  *
0802  * static IMFS_jnode_t *some_node_init(IMFS_jnode_t *node, void *arg)
0803  * {
0804  *   void *context;
0805  *
0806  *   node = IMFS_node_initialize_generic(node, arg);
0807  *   context = IMFS_generic_get_context_by_node(node);
0808  *
0809  *   return node;
0810  * }
0811  *
0812  * static void some_node_destroy(IMFS_jnode_t *node)
0813  * {
0814  *   void *context = IMFS_generic_get_context_by_node(node);
0815  *
0816  *   IMFS_node_destroy_default(node);
0817  * }
0818  *
0819  * static const IMFS_node_control
0820  * some_node_control = IMFS_GENERIC_CONTROL_INITIALIZER(
0821  *   &some_node_handlers,
0822  *   some_node_init,
0823  *   some_node_destroy
0824  * );
0825  *
0826  * void example(void *some_node_context)
0827  * {
0828  *   int rv;
0829  *
0830  *   rv = IMFS_make_generic_node(
0831  *     "/path/to/some/generic/node",
0832  *     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0833  *     &some_node_control,
0834  *     some_node_context
0835  *   );
0836  *   assert(rv == 0);
0837  * }
0838  * @endcode
0839  */
0840 extern int IMFS_make_generic_node(
0841   const char *path,
0842   mode_t mode,
0843   const IMFS_node_control *node_control,
0844   void *context
0845 );
0846 
0847 /** @} */
0848 
0849 /**
0850  * @addtogroup IMFS
0851  */
0852 /**@{*/
0853 
0854 /**
0855  * @brief Mount an IMFS.
0856  */
0857 extern int IMFS_mount(
0858   rtems_filesystem_mount_table_entry_t *mt_entry  /* IN */
0859 );
0860 
0861 /**
0862  * @brief Unmount an IMFS.
0863  */
0864 extern int IMFS_unmount(
0865   rtems_filesystem_mount_table_entry_t *mt_entry  /* IN */
0866 );
0867 
0868 /**
0869  * @name IMFS Memory File Handlers
0870  *
0871  * This section contains the set of handlers used to process operations on
0872  * IMFS memory file nodes.  The memory files are created in memory using
0873  * malloc'ed memory.  Thus any data stored in one of these files is lost
0874  * at system shutdown unless special arrangements to copy the data to
0875  * some type of non-volailte storage are made by the application.
0876  */
0877 /**@{*/
0878 
0879 extern ssize_t IMFS_memfile_write(
0880   IMFS_memfile_t      *memfile,
0881   off_t                start,
0882   const unsigned char *source,
0883   unsigned int         length
0884 );
0885 
0886 /** @} */
0887 
0888 /**
0889  * @name IMFS Device Node Handlers
0890  *
0891  * This section contains the set of handlers used to map operations on
0892  * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
0893  */
0894 /**@{*/
0895 
0896 extern int device_open(
0897   rtems_libio_t *iop,            /* IN  */
0898   const char    *pathname,       /* IN  */
0899   int            oflag,          /* IN  */
0900   mode_t         mode            /* IN  */
0901 );
0902 
0903 extern int device_close(
0904   rtems_libio_t *iop             /* IN  */
0905 );
0906 
0907 extern ssize_t device_read(
0908   rtems_libio_t *iop,            /* IN  */
0909   void          *buffer,         /* IN  */
0910   size_t         count           /* IN  */
0911 );
0912 
0913 extern ssize_t device_write(
0914   rtems_libio_t *iop,               /* IN  */
0915   const void    *buffer,            /* IN  */
0916   size_t         count              /* IN  */
0917 );
0918 
0919 extern int device_ioctl(
0920   rtems_libio_t   *iop,
0921   ioctl_command_t  command,
0922   void            *buffer
0923 );
0924 
0925 extern int device_ftruncate(
0926   rtems_libio_t *iop,               /* IN  */
0927   off_t          length             /* IN  */
0928 );
0929 
0930 /** @} */
0931 
0932 /**
0933  * @brief Set IMFS file access and modification times.
0934  * 
0935  * 
0936  * This routine is the implementation of the utime() system
0937  * call for the IMFS.
0938  */
0939 extern int IMFS_utimens(
0940   const rtems_filesystem_location_info_t *loc,
0941   struct timespec times[2]
0942 );
0943 
0944 /**
0945  * @brief Change the IMFS file mode.
0946  */
0947 extern int IMFS_fchmod(
0948   const rtems_filesystem_location_info_t *loc,
0949   mode_t mode
0950 );
0951 
0952 /**
0953  * @brief Create a new IMFS symbolic link node.
0954  * 
0955  * The following rouine creates a new symbolic link node under parent
0956  * with the name given in name.  The node is set to point to the node at
0957  * to_loc.
0958  */
0959 extern int IMFS_symlink(
0960   const rtems_filesystem_location_info_t *parentloc,
0961   const char *name,
0962   size_t namelen,
0963   const char *target
0964 );
0965 
0966 /**
0967  * @brief Put IMFS symbolic link into buffer.
0968  * 
0969  * The following rouine puts the symbolic links destination name into
0970  * buff.
0971  * 
0972  */
0973 extern ssize_t IMFS_readlink(
0974   const rtems_filesystem_location_info_t *loc,
0975   char *buf,
0976   size_t bufsize
0977 );
0978 
0979 /**
0980  * @brief Rename the IMFS.
0981  * 
0982  * The following rouine creates a new link node under parent with the
0983  * name given in name and removes the old.
0984  */
0985 extern int IMFS_rename(
0986   const rtems_filesystem_location_info_t *oldparentloc,
0987   const rtems_filesystem_location_info_t *oldloc,
0988   const rtems_filesystem_location_info_t *newparentloc,
0989   const char *name,
0990   size_t namelen
0991 );
0992 /**
0993  * @brief IMFS node removal handler.
0994  * 
0995  * This file contains the handler used to remove a node when a file type
0996  * does not require special actions.
0997  */
0998 extern int IMFS_rmnod(
0999   const rtems_filesystem_location_info_t *parentloc,
1000   const rtems_filesystem_location_info_t *loc
1001 );
1002 
1003 /*
1004  *  Turn on IMFS assertions when RTEMS_DEBUG is defined.
1005  */
1006 #ifdef RTEMS_DEBUG
1007   #include <assert.h>
1008 
1009   #define IMFS_assert(_x) assert(_x)
1010 #else
1011   #define IMFS_assert(_x)
1012 #endif
1013 
1014 static inline void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc )
1015 {
1016   IMFS_jnode_t *node = (IMFS_jnode_t *) loc->node_access;
1017 
1018   loc->handlers = node->control->handlers;
1019 }
1020 
1021 static inline void IMFS_add_to_directory(
1022   IMFS_jnode_t *dir_node,
1023   IMFS_jnode_t *entry_node
1024 )
1025 {
1026   IMFS_directory_t *dir = (IMFS_directory_t *) dir_node;
1027 
1028   entry_node->Parent = dir_node;
1029   rtems_chain_append_unprotected( &dir->Entries, &entry_node->Node );
1030 }
1031 
1032 static inline void IMFS_remove_from_directory( IMFS_jnode_t *node )
1033 {
1034   IMFS_assert( node->Parent != NULL );
1035   node->Parent = NULL;
1036   rtems_chain_extract_unprotected( &node->Node );
1037 }
1038 
1039 static inline bool IMFS_is_directory( const IMFS_jnode_t *node )
1040 {
1041   return S_ISDIR( node->st_mode );
1042 }
1043 
1044 #define IMFS_STAT_FMT_HARD_LINK 0
1045 
1046 static inline bool IMFS_is_hard_link( mode_t mode )
1047 {
1048   return ( mode & S_IFMT ) == IMFS_STAT_FMT_HARD_LINK;
1049 }
1050 
1051 static inline ino_t IMFS_node_to_ino( const IMFS_jnode_t *node )
1052 {
1053   return (ino_t) ((uintptr_t) node);
1054 }
1055 
1056 /** @} */
1057 
1058 /**
1059  * @addtogroup IMFSGenericNodes
1060  */
1061 /**@{*/
1062 
1063 static inline void *IMFS_generic_get_context_by_node(
1064   const IMFS_jnode_t *node
1065 )
1066 {
1067   const IMFS_generic_t *generic = (const IMFS_generic_t *) node;
1068 
1069   return generic->context;
1070 }
1071 
1072 static inline void *IMFS_generic_get_context_by_location(
1073   const rtems_filesystem_location_info_t *loc
1074 )
1075 {
1076   return loc->node_access_2;
1077 }
1078 
1079 static inline void *IMFS_generic_get_context_by_iop(
1080   const rtems_libio_t *iop
1081 )
1082 {
1083   return IMFS_generic_get_context_by_location( &iop->pathinfo );
1084 }
1085 
1086 static inline dev_t IMFS_generic_get_device_identifier_by_node(
1087   const IMFS_jnode_t *node
1088 )
1089 {
1090   return rtems_filesystem_make_dev_t_from_pointer( node );
1091 }
1092 
1093 #ifdef __cplusplus
1094 }
1095 #endif
1096 /** @} */
1097 #endif
1098 /* end of include file */