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 Format
0009  * 
0010  * Format the file system ready for use.
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include <string.h>
0043 #include <stdlib.h>
0044 #include <stdio.h>
0045 #include <inttypes.h>
0046 
0047 #include <rtems/rfs/rtems-rfs-data.h>
0048 #include <rtems/rfs/rtems-rfs-file-system.h>
0049 #include <rtems/rfs/rtems-rfs-inode.h>
0050 #include <rtems/rtems-rfs-format.h>
0051 #include <rtems/rfs/rtems-rfs-dir.h>
0052 
0053 /**
0054  * Return the number of gigabytes.
0055  */
0056 #define GIGS(_g) (((uint64_t)(_g)) * 1024 * 1024)
0057 
0058 /**
0059  * Return the number of bits that fit in the block size.
0060  */
0061 static int
0062 rtems_rfs_bits_per_block (rtems_rfs_file_system* fs)
0063 {
0064   return rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs));
0065 }
0066 
0067 /**
0068  * Return a rounded up integer quotient given a dividend and divisor. That is:
0069  * "quotient = dividend / divisor"
0070  */
0071 static int
0072 rtems_rfs_rup_quotient (uint32_t dividend, uint32_t divisor)
0073 {
0074   if (dividend == 0)
0075     return 1;
0076   return ((dividend - 1) / divisor) + 1;
0077 }
0078 
0079 /**
0080  * Return the number of inodes as a percentage of the total number that can fit
0081  * in a blocl.
0082  */
0083 static int
0084 rtems_rfs_inodes_from_percent (rtems_rfs_file_system* fs,
0085                                int                    percentage)
0086 {
0087   int blocks;
0088   blocks = ((rtems_rfs_fs_blocks (fs) -
0089              RTEMS_RFS_SUPERBLOCK_SIZE) * percentage) / 100;
0090   blocks = rtems_rfs_rup_quotient (blocks, fs->group_count);
0091   return blocks * (rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE);
0092 }
0093 
0094 /**
0095  * Return the inode overhead given a number of inodes.
0096  */
0097 static int
0098 rtems_rfs_inode_overhead (rtems_rfs_file_system* fs)
0099 {
0100   int blocks;
0101   int bits_per_block;
0102   blocks = rtems_rfs_rup_quotient(fs->group_inodes * RTEMS_RFS_INODE_SIZE,
0103                                   rtems_rfs_fs_block_size (fs));
0104   bits_per_block = rtems_rfs_bits_per_block (fs);
0105   /*
0106    * There could be more bits than blocks, eg 512K disk with 512 blocks.
0107    */
0108   if (bits_per_block > (rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE))
0109     bits_per_block = rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE;
0110   return ((blocks + 1) * 100 * 10) / bits_per_block;
0111 }
0112 
0113 static bool
0114 rtems_rfs_check_config (rtems_rfs_file_system*         fs,
0115                         const rtems_rfs_format_config* config)
0116 {
0117   fs->block_size = config->block_size;
0118   if (!fs->block_size)
0119   {
0120     uint64_t total_size = rtems_rfs_fs_media_size (fs);
0121 
0122     if (total_size >= GIGS (1))
0123     {
0124       uint32_t gigs = (total_size + GIGS (1)) / GIGS (1);
0125       int      b;
0126       for (b = 31; b > 0; b--)
0127         if ((gigs & (1 << b)) != 0)
0128           break;
0129       fs->block_size = 1 << b;
0130     }
0131 
0132     if (fs->block_size < 512)
0133       fs->block_size = 512;
0134 
0135     if (fs->block_size > (4 * 1024))
0136       fs->block_size = (4 * 1024);
0137   }
0138 
0139   if ((fs->block_size % rtems_rfs_fs_media_block_size (fs)) != 0)
0140   {
0141     printf ("block size (%zd) is not a multiple of media block size (%" PRId32 ")\n",
0142             fs->block_size, rtems_rfs_fs_media_block_size (fs));
0143     return false;
0144   }
0145 
0146   fs->group_blocks = config->group_blocks;
0147   if (!fs->group_blocks)
0148   {
0149     /*
0150      * The number of blocks per group is defined by the number of bits in a
0151      * block.
0152      */
0153     fs->group_blocks = rtems_rfs_bitmap_numof_bits (fs->block_size);
0154   }
0155 
0156   if (fs->group_blocks > rtems_rfs_bitmap_numof_bits (fs->block_size))
0157   {
0158     printf ("group block count is higher than bits in block\n");
0159     return false;
0160   }
0161 
0162   fs->blocks = rtems_rfs_fs_media_size (fs) / fs->block_size;
0163 
0164   /*
0165    * The bits per block sets the upper limit for the number of blocks in a
0166    * group. The disk will be divided into groups which are the number of bits
0167    * per block.
0168    */
0169   fs->group_count = rtems_rfs_rup_quotient (rtems_rfs_fs_blocks (fs),
0170                                             rtems_rfs_bits_per_block (fs));
0171 
0172   fs->group_inodes = config->group_inodes;
0173   if (!fs->group_inodes)
0174   {
0175     int inode_overhead = RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE;
0176 
0177     /*
0178      * The number of inodes per group is set as a percentage.
0179      */
0180     if (config->inode_overhead)
0181       inode_overhead = config->inode_overhead;
0182 
0183     fs->group_inodes = rtems_rfs_inodes_from_percent (fs, inode_overhead);
0184   }
0185 
0186   /*
0187    * Round up to fill a block because the minimum allocation unit is a block.
0188    */
0189   fs->inodes_per_block = rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE;
0190   fs->group_inodes =
0191     rtems_rfs_rup_quotient (fs->group_inodes,
0192                             fs->inodes_per_block) * fs->inodes_per_block;
0193 
0194   if (fs->group_inodes > rtems_rfs_bitmap_numof_bits (fs->block_size))
0195     fs->group_inodes = rtems_rfs_bitmap_numof_bits (fs->block_size);
0196 
0197   fs->max_name_length = config->max_name_length;
0198   if (!fs->max_name_length)
0199   {
0200     fs->max_name_length = 512;
0201   }
0202 
0203   return true;
0204 }
0205 
0206 static bool
0207 rtems_rfs_write_group (rtems_rfs_file_system* fs,
0208                        int                    group,
0209                        bool                   initialise_inodes,
0210                        bool                   verbose)
0211 {
0212   rtems_rfs_buffer_handle  handle;
0213   rtems_rfs_bitmap_control bitmap;
0214   rtems_rfs_buffer_block   group_base;
0215   size_t                   group_size;
0216   int                      blocks;
0217   int                      b;
0218   int                      rc;
0219 
0220   group_base = rtems_rfs_fs_block (fs, group, 0);
0221 
0222   if (group_base > rtems_rfs_fs_blocks (fs))
0223   {
0224     printf ("rtems-rfs: write-group: group %d base beyond disk limit\n",
0225             group);
0226     return false;
0227   }
0228 
0229   group_size = fs->group_blocks;
0230 
0231   /*
0232    * Be nice to strange sizes of disks. These are embedded systems after all
0233    * and nice numbers do not always work out. Let the last block pick up the
0234    * remainder of the blocks.
0235    */
0236   if ((group_base + group_size) > rtems_rfs_fs_blocks (fs))
0237     group_size = rtems_rfs_fs_blocks (fs) - group_base;
0238 
0239   if (verbose)
0240     printf ("\rrtems-rfs: format: group %3d: base = %" PRId32 ", size = %zd",
0241             group, group_base, group_size);
0242 
0243   /*
0244    * Open a handle and request an empty buffer.
0245    */
0246   rc = rtems_rfs_buffer_handle_open (fs, &handle);
0247   if (rc > 0)
0248   {
0249     printf ("\nrtems-rfs: write-group: handle open failed: %d: %s\n",
0250             rc, strerror (rc));
0251     return false;
0252   }
0253 
0254   if (verbose)
0255     printf (", blocks");
0256 
0257   /*
0258    * Open the block bitmap using the new buffer.
0259    */
0260   rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
0261                               group_base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
0262   if (rc > 0)
0263   {
0264     rtems_rfs_buffer_handle_close (fs, &handle);
0265     printf ("\nrtems-rfs: write-group: group %3d: open block bitmap failed: %d: %s\n",
0266             group, rc, strerror (rc));
0267     return false;
0268   }
0269 
0270   /*
0271    * Force the whole buffer to a known state. The bit map may not occupy the
0272    * whole block.
0273    */
0274   memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
0275 
0276   /*
0277    * Clear the bitmap.
0278    */
0279   rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
0280   if (rc > 0)
0281   {
0282     rtems_rfs_bitmap_close (&bitmap);
0283     rtems_rfs_buffer_handle_close (fs, &handle);
0284     printf ("\nrtems-rfs: write-group: group %3d: block bitmap clear all failed: %d: %s\n",
0285             group, rc, strerror (rc));
0286     return false;
0287   }
0288 
0289   /*
0290    * Forced allocation of the block bitmap.
0291    */
0292   rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
0293 
0294   /*
0295    * Forced allocation of the inode bitmap.
0296    */
0297   rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
0298 
0299   /*
0300    * Determine the number of inodes blocks in the group.
0301    */
0302   blocks = rtems_rfs_rup_quotient (fs->group_inodes, fs->inodes_per_block);
0303 
0304   /*
0305    * Forced allocation of the inode blocks which follow the block bitmap.
0306    */
0307   for (b = 0; b < blocks; b++)
0308     rtems_rfs_bitmap_map_set (&bitmap, b + RTEMS_RFS_GROUP_INODE_BLOCK);
0309 
0310   /*
0311    * Close the block bitmap.
0312    */
0313   rc = rtems_rfs_bitmap_close (&bitmap);
0314   if (rc > 0)
0315   {
0316     rtems_rfs_buffer_handle_close (fs, &handle);
0317     printf ("\nrtems-rfs: write-group: group %3d: close block bitmap failed: %d: %s\n",
0318             group, rc, strerror (rc));
0319     return false;
0320   }
0321 
0322   rtems_rfs_buffer_mark_dirty (&handle);
0323 
0324   if (verbose)
0325     printf (", inodes");
0326 
0327   /*
0328    * Open the inode bitmap using the old buffer. Should release any changes.
0329    */
0330   rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
0331                               group_base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
0332   if (rc > 0)
0333   {
0334     rtems_rfs_buffer_handle_close (fs, &handle);
0335     printf ("\nrtems-rfs: write-group: group %3d: open inode bitmap failed: %d: %s\n",
0336             group, rc, strerror (rc));
0337     return false;
0338   }
0339 
0340   /*
0341    * Force the whole buffer to a known state. The bit map may not occupy the
0342    * whole block.
0343    */
0344   memset (rtems_rfs_buffer_data (&handle), 0x00, rtems_rfs_fs_block_size (fs));
0345 
0346   /*
0347    * Clear the inode bitmap.
0348    */
0349   rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
0350   if (rc > 0)
0351   {
0352     rtems_rfs_bitmap_close (&bitmap);
0353     rtems_rfs_buffer_handle_close (fs, &handle);
0354     printf ("\nrtems-rfs: write-group: group %3d: inode bitmap" \
0355             " clear all failed: %d: %s\n", group, rc, strerror (rc));
0356     return false;
0357   }
0358 
0359   /*
0360    * Close the inode bitmap.
0361    */
0362   rc = rtems_rfs_bitmap_close (&bitmap);
0363   if (rc > 0)
0364   {
0365     rtems_rfs_buffer_handle_close (fs, &handle);
0366     printf ("\nrtems-rfs: write-group: group %3d: close inode" \
0367             " bitmap failed: %d: %s\n", group, rc, strerror (rc));
0368     return false;
0369   }
0370 
0371   rtems_rfs_buffer_mark_dirty (&handle);
0372 
0373   /*
0374    * Initialise the inode tables if required to do so.
0375    */
0376   if (initialise_inodes)
0377   {
0378     for (b = 0; b < blocks; b++)
0379     {
0380       rc = rtems_rfs_buffer_handle_request (fs, &handle,
0381                                             group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
0382                                             false);
0383       if (rc > 0)
0384       {
0385         rtems_rfs_buffer_handle_close (fs, &handle);
0386         printf ("\nrtems-rfs: write-group: group %3d: block %" PRId32 " request failed: %d: %s\n",
0387                 group, group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
0388                 rc, strerror (rc));
0389         return false;
0390       }
0391 
0392       /*
0393        * Force the whole buffer to a known state. The bit map may not occupy the
0394        * whole block.
0395        */
0396       memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
0397 
0398       rtems_rfs_buffer_mark_dirty (&handle);
0399     }
0400   }
0401 
0402   rc = rtems_rfs_buffer_handle_close (fs, &handle);
0403   if (rc > 0)
0404   {
0405     printf ("\nrtems-rfs: write-group: buffer handle close failed: %d: %s\n",
0406             rc, strerror (rc));
0407     return false;
0408   }
0409 
0410   return true;
0411 }
0412 
0413 static bool
0414 rtems_rfs_write_superblock (rtems_rfs_file_system* fs)
0415 {
0416   rtems_rfs_buffer_handle handle;
0417   uint8_t*                sb;
0418   int                     rc;
0419 
0420   rc = rtems_rfs_buffer_handle_open (fs, &handle);
0421   if (rc > 0)
0422   {
0423     printf ("rtems-rfs: write-superblock: handle open failed: %d: %s\n",
0424             rc, strerror (rc));
0425     return false;
0426   }
0427 
0428   rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, false);
0429   if (rc > 0)
0430   {
0431     rtems_rfs_buffer_handle_close (fs, &handle);
0432     printf ("rtems-rfs: write-superblock: request failed: %d: %s\n",
0433             rc, strerror (rc));
0434     return false;
0435   }
0436 
0437   sb = rtems_rfs_buffer_data (&handle);
0438 
0439 #define write_sb(_o, _d) rtems_rfs_write_u32(sb + (_o), _d)
0440 
0441   memset (sb, 0xff, rtems_rfs_fs_block_size (fs));
0442 
0443   write_sb (RTEMS_RFS_SB_OFFSET_MAGIC, RTEMS_RFS_SB_MAGIC);
0444   write_sb (RTEMS_RFS_SB_OFFSET_VERSION, RTEMS_RFS_VERSION);
0445   write_sb (RTEMS_RFS_SB_OFFSET_BLOCKS, rtems_rfs_fs_blocks (fs));
0446   write_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE, rtems_rfs_fs_block_size (fs));
0447   write_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS, fs->bad_blocks);
0448   write_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH, fs->max_name_length);
0449   write_sb (RTEMS_RFS_SB_OFFSET_GROUPS, fs->group_count);
0450   write_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS, fs->group_blocks);
0451   write_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES, fs->group_inodes);
0452   write_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE, RTEMS_RFS_INODE_SIZE);
0453 
0454   rtems_rfs_buffer_mark_dirty (&handle);
0455 
0456   rc = rtems_rfs_buffer_handle_release (fs, &handle);
0457   if (rc > 0)
0458   {
0459     rtems_rfs_buffer_handle_close (fs, &handle);
0460     printf ("rtems-rfs: write-superblock: buffer release failed: %d: %s\n",
0461             rc, strerror (rc));
0462     return false;
0463   }
0464 
0465   rc = rtems_rfs_buffer_handle_close (fs, &handle);
0466   if (rc > 0)
0467   {
0468     printf ("rtems-rfs: write-superblock: buffer handle close failed: %d: %s\n",
0469             rc, strerror (rc));
0470     return false;
0471   }
0472 
0473   return true;
0474 }
0475 
0476 static int
0477 rtems_rfs_write_root_dir (const char* name)
0478 {
0479   rtems_rfs_file_system* fs;
0480   rtems_rfs_inode_handle inode;
0481   rtems_rfs_ino          ino;
0482   int                    rc;
0483 
0484   /*
0485    * External API so returns -1.
0486    */
0487   rc = rtems_rfs_fs_open (name, NULL,
0488                           RTEMS_RFS_FS_FORCE_OPEN | RTEMS_RFS_FS_NO_LOCAL_CACHE,
0489                           0, &fs);
0490   if (rc != 0)
0491   {
0492     rc = errno;
0493 
0494     printf ("rtems-rfs: format: file system open failed: %d: %s\n",
0495             rc, strerror (rc));
0496 
0497     return rc;
0498   }
0499 
0500   rc = rtems_rfs_inode_alloc (fs, RTEMS_RFS_ROOT_INO, &ino);
0501   if (rc != 0)
0502   {
0503     printf ("rtems-rfs: format: inode allocation failed: %d: %s\n",
0504             rc, strerror (rc));
0505     rtems_rfs_fs_close (fs);
0506     return rc;
0507   }
0508 
0509   if (ino != RTEMS_RFS_ROOT_INO)
0510   {
0511     printf ("rtems-rfs: format: allocated inode not root ino: %" PRId32 "\n", ino);
0512     rtems_rfs_fs_close (fs);
0513     return EINVAL;
0514   }
0515 
0516   rc = rtems_rfs_inode_open (fs, ino, &inode, true);
0517   if (rc != 0)
0518   {
0519     printf ("rtems-rfs: format: inode open failed: %d: %s\n",
0520             rc, strerror (rc));
0521     rtems_rfs_group_bitmap_free (fs, true, ino);
0522     rtems_rfs_fs_close (fs);
0523     return rc;
0524   }
0525 
0526   rc = rtems_rfs_inode_initialise (&inode, 0,
0527                                    (RTEMS_RFS_S_IFDIR | RTEMS_RFS_S_IRWXU |
0528                                     RTEMS_RFS_S_IXGRP | RTEMS_RFS_S_IXOTH),
0529                                    0, 0);
0530   if (rc != 0)
0531     printf ("rtems-rfs: format: inode initialise failed: %d: %s\n",
0532             rc, strerror (rc));
0533 
0534   rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, ino);
0535   if (rc != 0)
0536     printf ("rtems-rfs: format: directory add failed: %d: %s\n",
0537             rc, strerror (rc));
0538 
0539   rc = rtems_rfs_inode_close (fs, &inode);
0540   if (rc != 0)
0541     printf ("rtems-rfs: format: inode close failed: %d: %s\n",
0542             rc, strerror (rc));
0543 
0544   rc = rtems_rfs_fs_close (fs);
0545   if (rc != 0)
0546   {
0547     rc = errno;
0548 
0549     printf ("rtems-rfs: format: file system close failed: %d: %s\n",
0550             rc, strerror (rc));
0551 
0552     return rc;
0553   }
0554 
0555   return 0;
0556 }
0557 
0558 int
0559 rtems_rfs_format (const char* name, const rtems_rfs_format_config* config)
0560 {
0561   rtems_rfs_file_system fs;
0562   int                   group;
0563   int                   rc;
0564 
0565   if (config->verbose)
0566     printf ("rtems-rfs: format: %s\n", name);
0567 
0568   memset (&fs, 0, sizeof (rtems_rfs_file_system));
0569 
0570   rtems_chain_initialize_empty (&fs.buffers);
0571   rtems_chain_initialize_empty (&fs.release);
0572   rtems_chain_initialize_empty (&fs.release_modified);
0573   rtems_chain_initialize_empty (&fs.file_shares);
0574 
0575   fs.max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
0576 
0577   fs.release_count = 0;
0578   fs.release_modified_count = 0;
0579 
0580   fs.flags = RTEMS_RFS_FS_NO_LOCAL_CACHE;
0581 
0582   /*
0583    * Open the buffer interface.
0584    */
0585   rc = rtems_rfs_buffer_open (name, &fs);
0586   if (rc != 0)
0587   {
0588     printf ("rtems-rfs: format: buffer open failed: %d: %s\n",
0589             rc, strerror (rc));
0590 
0591     errno = rc;
0592     return -1;
0593   }
0594 
0595   /*
0596    * Check the media.
0597    */
0598   if (rtems_rfs_fs_media_block_size (&fs) == 0)
0599   {
0600     printf ("rtems-rfs: media block is invalid: %" PRIu32 "\n",
0601             rtems_rfs_fs_media_block_size (&fs));
0602 
0603     errno = EINVAL;
0604     return -1;
0605   }
0606 
0607   /*
0608    * Check the configuration data.
0609    */
0610   if (!rtems_rfs_check_config (&fs, config))
0611   {
0612     errno = EINVAL;
0613     return -1;
0614   }
0615 
0616   if (config->verbose)
0617   {
0618     printf ("rtems-rfs: format: media size = %" PRIu64 "\n",
0619             rtems_rfs_fs_media_size (&fs));
0620     printf ("rtems-rfs: format: media blocks = %" PRIu32 "\n",
0621             rtems_rfs_fs_media_blocks (&fs));
0622     printf ("rtems-rfs: format: media block size = %" PRIu32 "\n",
0623             rtems_rfs_fs_media_block_size (&fs));
0624     printf ("rtems-rfs: format: size = %" PRIu64 "\n",
0625             rtems_rfs_fs_size (&fs));
0626     printf ("rtems-rfs: format: blocks = %zu\n",
0627             rtems_rfs_fs_blocks (&fs));
0628     printf ("rtems-rfs: format: block size = %zu\n",
0629             rtems_rfs_fs_block_size (&fs));
0630     printf ("rtems-rfs: format: bits per block = %u\n",
0631             rtems_rfs_bits_per_block (&fs));
0632     printf ("rtems-rfs: format: inode size = %zu\n", RTEMS_RFS_INODE_SIZE);
0633     printf ("rtems-rfs: format: inodes = %zu (%d.%d%%)\n",
0634             fs.group_inodes * fs.group_count,
0635             rtems_rfs_inode_overhead (&fs) / 10,
0636             rtems_rfs_inode_overhead (&fs) % 10);
0637     printf ("rtems-rfs: format: groups = %u\n", fs.group_count);
0638     printf ("rtems-rfs: format: group blocks = %zu\n", fs.group_blocks);
0639     printf ("rtems-rfs: format: group inodes = %zu\n", fs.group_inodes);
0640   }
0641 
0642   rc = rtems_rfs_buffer_setblksize (&fs, rtems_rfs_fs_block_size (&fs));
0643   if (rc != 0)
0644   {
0645     printf ("rtems-rfs: format: setting block size failed: %d: %s\n",
0646             rc, strerror (rc));
0647 
0648     errno = rc;
0649     return -1;
0650   }
0651 
0652   if (!rtems_rfs_write_superblock (&fs))
0653   {
0654     printf ("rtems-rfs: format: superblock write failed\n");
0655 
0656     errno = EIO;
0657     return -1;
0658   }
0659 
0660   for (group = 0; group < fs.group_count; group++)
0661     if (!rtems_rfs_write_group (&fs, group,
0662                                 config->initialise_inodes, config->verbose))
0663       {
0664         errno = EIO;
0665         return -1;
0666       }
0667 
0668   if (config->verbose)
0669     printf ("\n");
0670 
0671   rc = rtems_rfs_buffer_close (&fs);
0672   if (rc != 0)
0673   {
0674     printf ("rtems-rfs: format: buffer close failed: %d: %s\n",
0675             rc, strerror (rc));
0676 
0677     errno = rc;
0678     return -1;
0679   }
0680 
0681   rc = rtems_rfs_write_root_dir (name);
0682   if (rc != 0)
0683   {
0684     printf ("rtems-rfs: format: writing root dir failed: %d: %s\n",
0685             rc, strerror (rc));
0686 
0687     errno = rc;
0688     return -1;
0689   }
0690 
0691   return 0;
0692 }