Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup rtems_rfs
0007  *
0008  * @brief RTEMS File Systems Open
0009  * 
0010  * Open the file system by reading the superblock and then the group data.
0011  */
0012 /*
0013  *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040 
0041 #include <inttypes.h>
0042 #include <stdlib.h>
0043 #include <string.h>
0044 
0045 #include <rtems/rfs/rtems-rfs-data.h>
0046 #include <rtems/rfs/rtems-rfs-file-system.h>
0047 #include <rtems/rfs/rtems-rfs-inode.h>
0048 #include <rtems/rfs/rtems-rfs-trace.h>
0049 
0050 uint64_t
0051 rtems_rfs_fs_size (rtems_rfs_file_system* fs)
0052 {
0053   uint64_t blocks = rtems_rfs_fs_blocks (fs);
0054   uint64_t block_size = rtems_rfs_fs_block_size (fs);
0055   return blocks * block_size;
0056 }
0057 
0058 uint64_t
0059 rtems_rfs_fs_media_size (rtems_rfs_file_system* fs)
0060 {
0061   uint64_t media_blocks = (uint64_t) rtems_rfs_fs_media_blocks (fs);
0062   uint64_t media_block_size = (uint64_t) rtems_rfs_fs_media_block_size (fs);
0063   return media_blocks * media_block_size;
0064 }
0065 
0066 static int
0067 rtems_rfs_fs_read_superblock (rtems_rfs_file_system* fs)
0068 {
0069   rtems_rfs_buffer_handle handle;
0070   uint8_t*                sb;
0071   int                     group;
0072   int                     rc;
0073 
0074   rc = rtems_rfs_buffer_handle_open (fs, &handle);
0075   if (rc > 0)
0076   {
0077     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0078       printf ("rtems-rfs: read-superblock: handle open failed: %d: %s\n",
0079               rc, strerror (rc));
0080     return rc;
0081   }
0082 
0083   rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, true);
0084   if (rc > 0)
0085   {
0086     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0087       printf ("rtems-rfs: read-superblock: request failed%d: %s\n",
0088               rc, strerror (rc));
0089     return rc;
0090   }
0091 
0092   sb = rtems_rfs_buffer_data (&handle);
0093 
0094 #define read_sb(_o) rtems_rfs_read_u32 (sb + (_o))
0095 
0096   if (read_sb (RTEMS_RFS_SB_OFFSET_MAGIC) != RTEMS_RFS_SB_MAGIC)
0097   {
0098     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0099       printf ("rtems-rfs: read-superblock: invalid superblock, bad magic\n");
0100     rtems_rfs_buffer_handle_close (fs, &handle);
0101     return EIO;
0102   }
0103 
0104   fs->blocks     = read_sb (RTEMS_RFS_SB_OFFSET_BLOCKS);
0105   fs->block_size = read_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE);
0106 
0107   if (rtems_rfs_fs_size(fs) > rtems_rfs_fs_media_size (fs))
0108   {
0109     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0110       printf ("rtems-rfs: read-superblock: invalid superblock block/size count\n");
0111     rtems_rfs_buffer_handle_close (fs, &handle);
0112     return EIO;
0113   }
0114 
0115   if ((read_sb (RTEMS_RFS_SB_OFFSET_VERSION) & RTEMS_RFS_VERSION_MASK) !=
0116       (RTEMS_RFS_VERSION * RTEMS_RFS_VERSION_MASK))
0117   {
0118     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0119       printf ("rtems-rfs: read-superblock: incompatible version: %08" PRIx32 " (%08" PRIx32 ")\n",
0120               read_sb (RTEMS_RFS_SB_OFFSET_VERSION), RTEMS_RFS_VERSION_MASK);
0121     rtems_rfs_buffer_handle_close (fs, &handle);
0122     return EIO;
0123   }
0124 
0125   if (read_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE) != RTEMS_RFS_INODE_SIZE)
0126   {
0127     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0128       printf ("rtems-rfs: read-superblock: inode size mismatch: fs:%" PRId32 " target:%" PRId32 "\n",
0129               read_sb (RTEMS_RFS_SB_OFFSET_VERSION), RTEMS_RFS_VERSION_MASK);
0130     rtems_rfs_buffer_handle_close (fs, &handle);
0131     return EIO;
0132   }
0133 
0134   fs->bad_blocks      = read_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS);
0135   fs->max_name_length = read_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH);
0136   fs->group_count     = read_sb (RTEMS_RFS_SB_OFFSET_GROUPS);
0137   fs->group_blocks    = read_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS);
0138   fs->group_inodes    = read_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES);
0139 
0140   fs->blocks_per_block =
0141     rtems_rfs_fs_block_size (fs) / sizeof (rtems_rfs_inode_block);
0142 
0143   fs->block_map_singly_blocks =
0144     fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS;
0145   fs->block_map_doubly_blocks =
0146     fs->blocks_per_block * fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS;
0147 
0148   fs->inodes = fs->group_count * fs->group_inodes;
0149 
0150   fs->inodes_per_block = fs->block_size / RTEMS_RFS_INODE_SIZE;
0151 
0152   if (fs->group_blocks >
0153       rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs)))
0154   {
0155     rtems_rfs_buffer_handle_close (fs, &handle);
0156     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0157       printf ("rtems-rfs: read-superblock: groups blocks larger than block bits\n");
0158     return EIO;
0159   }
0160 
0161   rtems_rfs_buffer_handle_close (fs, &handle);
0162 
0163   /*
0164    * Change the block size to the value in the superblock.
0165    */
0166   rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_block_size (fs));
0167   if (rc > 0)
0168   {
0169     rtems_rfs_buffer_handle_close (fs, &handle);
0170     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0171       printf ("rtems-rfs: read-superblock: invalid superblock block size%d: %s\n",
0172               rc, strerror (rc));
0173     return rc;
0174   }
0175 
0176   fs->groups = calloc (fs->group_count, sizeof (rtems_rfs_group));
0177 
0178   if (!fs->groups)
0179   {
0180     rtems_rfs_buffer_handle_close (fs, &handle);
0181     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0182       printf ("rtems-rfs: read-superblock: no memory for group table\n");
0183     return ENOMEM;
0184   }
0185 
0186   /*
0187    * Perform each phase of group initialisation at the same time. This way we
0188    * know how far the initialisation has gone if an error occurs and we need to
0189    * close everything.
0190    */
0191   for (group = 0; group < fs->group_count; group++)
0192   {
0193     rc = rtems_rfs_group_open (fs,
0194                                rtems_rfs_fs_block (fs, group, 0),
0195                                fs->group_blocks,
0196                                fs->group_inodes,
0197                                &fs->groups[group]);
0198     if (rc > 0)
0199     {
0200       int g;
0201       for (g = 0; g < group; g++)
0202         rtems_rfs_group_close (fs, &fs->groups[g]);
0203       rtems_rfs_buffer_handle_close (fs, &handle);
0204       if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0205         printf ("rtems-rfs: read-superblock: no memory for group table%d: %s\n",
0206                 rc, strerror (rc));
0207       return rc;
0208     }
0209   }
0210 
0211   return 0;
0212 }
0213 
0214 int
0215 rtems_rfs_fs_open (const char*             name,
0216                    void*                   user,
0217                    uint32_t                flags,
0218                    uint32_t                max_held_buffers,
0219                    rtems_rfs_file_system** fs)
0220 {
0221 #if UNUSED
0222   rtems_rfs_group*       group;
0223   size_t                 group_base;
0224 #endif
0225   rtems_rfs_inode_handle inode;
0226   uint16_t               mode;
0227   int                    rc;
0228 
0229   if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0230     printf ("rtems-rfs: open: %s\n", name);
0231 
0232   *fs = malloc (sizeof (rtems_rfs_file_system));
0233   if (!*fs)
0234   {
0235     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0236       printf ("rtems-rfs: open: no memory for file system data\n");
0237     errno = ENOMEM;
0238     return -1;
0239   }
0240 
0241   memset (*fs, 0, sizeof (rtems_rfs_file_system));
0242 
0243   (*fs)->user = user;
0244   rtems_chain_initialize_empty (&(*fs)->buffers);
0245   rtems_chain_initialize_empty (&(*fs)->release);
0246   rtems_chain_initialize_empty (&(*fs)->release_modified);
0247   rtems_chain_initialize_empty (&(*fs)->file_shares);
0248 
0249   (*fs)->max_held_buffers = max_held_buffers;
0250   (*fs)->buffers_count = 0;
0251   (*fs)->release_count = 0;
0252   (*fs)->release_modified_count = 0;
0253   (*fs)->flags = flags;
0254 
0255 #if UNUSED
0256   group = &(*fs)->groups[0];
0257   group_base = 0;
0258 #endif
0259 
0260   /*
0261    * Open the buffer interface.
0262    */
0263   rc = rtems_rfs_buffer_open (name, *fs);
0264   if (rc > 0)
0265   {
0266     free (*fs);
0267     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0268       printf ("rtems-rfs: open: buffer open failed: %d: %s\n",
0269               rc, strerror (rc));
0270     errno = rc;
0271     return -1;
0272   }
0273 
0274   rc = rtems_rfs_fs_read_superblock (*fs);
0275   if (rc > 0)
0276   {
0277     rtems_rfs_buffer_close (*fs);
0278     free (*fs);
0279     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0280       printf ("rtems-rfs: open: reading superblock: %d: %s\n",
0281               rc, strerror (rc));
0282     errno = rc;
0283     return -1;
0284   }
0285 
0286   rc = rtems_rfs_inode_open (*fs, RTEMS_RFS_ROOT_INO, &inode, true);
0287   if (rc > 0)
0288   {
0289     rtems_rfs_buffer_close (*fs);
0290     free (*fs);
0291     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0292       printf ("rtems-rfs: open: reading root inode: %d: %s\n",
0293               rc, strerror (rc));
0294     errno = rc;
0295     return -1;
0296   }
0297 
0298   if (((*fs)->flags & RTEMS_RFS_FS_FORCE_OPEN) == 0)
0299   {
0300     mode = rtems_rfs_inode_get_mode (&inode);
0301 
0302     if ((mode == 0xffff) || !RTEMS_RFS_S_ISDIR (mode))
0303     {
0304       rtems_rfs_inode_close (*fs, &inode);
0305       rtems_rfs_buffer_close (*fs);
0306       free (*fs);
0307       if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0308         printf ("rtems-rfs: open: invalid root inode mode\n");
0309       errno = EIO;
0310       return -1;
0311     }
0312   }
0313 
0314   rc = rtems_rfs_inode_close (*fs, &inode);
0315   if (rc > 0)
0316   {
0317     rtems_rfs_buffer_close (*fs);
0318     free (*fs);
0319     if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
0320       printf ("rtems-rfs: open: closing root inode: %d: %s\n", rc, strerror (rc));
0321     errno = rc;
0322     return -1;
0323   }
0324 
0325   return 0;
0326 }
0327 
0328 int
0329 rtems_rfs_fs_close (rtems_rfs_file_system* fs)
0330 {
0331   int group;
0332 
0333   if (rtems_rfs_trace (RTEMS_RFS_TRACE_CLOSE))
0334     printf ("rtems-rfs: close\n");
0335 
0336   for (group = 0; group < fs->group_count; group++)
0337     rtems_rfs_group_close (fs, &fs->groups[group]);
0338 
0339   rtems_rfs_buffer_close (fs);
0340 
0341   free (fs);
0342   return 0;
0343 }