Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2012 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include "tmacros.h"
0033 
0034 #include <fcntl.h>
0035 #include <inttypes.h>
0036 #include <sys/statvfs.h>
0037 #include <rtems/libio.h>
0038 #include <rtems/blkdev.h>
0039 #include <rtems/dosfs.h>
0040 #include <rtems/sparse-disk.h>
0041 
0042 #include <bsp.h>
0043 
0044 const char rtems_test_name[] = "FSDOSFSFORMAT 1";
0045 
0046 #define MAX_PATH_LENGTH 100 /* Maximum number of characters per path */
0047 #define SECTOR_SIZE 512 /* sector size (bytes) */
0048 #define FAT12_MAX_CLN 4085 /* maximum + 1 number of clusters for FAT12 */
0049 #define FAT16_MAX_CLN 65525 /* maximum + 1 number of clusters for FAT16 */
0050 #define FAT12_DEFAULT_SECTORS_PER_CLUSTER 8 /* Default number of sectors per cluster for FAT12 */
0051 #define FAT16_DEFAULT_SECTORS_PER_CLUSTER 32 /* Default number of sectors per cluster for FAT16 */
0052 
0053 static void test_disk_params(
0054   const char     *dev_name,
0055   const char     *mount_dir,
0056   const blksize_t sector_size,
0057   const blksize_t cluster_size,
0058   const blkcnt_t  sectors_per_cluster )
0059 {
0060   int          rv;
0061   int          fildes;
0062   struct stat  stat_buff;
0063   char         file_name[MAX_PATH_LENGTH + 1];
0064   ssize_t      num_bytes;
0065   unsigned int value = (unsigned int) -1;
0066 
0067 
0068   snprintf( file_name, MAX_PATH_LENGTH, "%s/file1.txt", mount_dir );
0069   memset( &stat_buff, 0, sizeof( stat_buff ) );
0070 
0071   rv = mount( dev_name,
0072               mount_dir,
0073               RTEMS_FILESYSTEM_TYPE_DOSFS,
0074               RTEMS_FILESYSTEM_READ_WRITE,
0075               NULL );
0076   rtems_test_assert( 0 == rv );
0077 
0078   fildes = open( file_name,
0079                  O_RDWR | O_CREAT | O_TRUNC,
0080                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
0081   rtems_test_assert( -1 != fildes );
0082 
0083   num_bytes = write( fildes, &value, sizeof( value ) );
0084   rtems_test_assert( sizeof( value ) == num_bytes );
0085 
0086   rv = fstat( fildes, &stat_buff );
0087   rtems_test_assert( 0 == rv );
0088   rtems_test_assert( S_ISREG( stat_buff.st_mode ) );
0089   rtems_test_assert( sizeof( value ) == stat_buff.st_size );
0090   rtems_test_assert( cluster_size == stat_buff.st_blksize );
0091   rtems_test_assert( sectors_per_cluster
0092                      == ( stat_buff.st_blocks * sector_size / 512 ) );
0093   rtems_test_assert( ( ( ( stat_buff.st_size + cluster_size
0094                            - 1 ) / cluster_size ) * cluster_size / 512 )
0095                      == stat_buff.st_blocks );
0096   rv = close( fildes );
0097   rtems_test_assert( 0 == rv );
0098 
0099   rv = unmount( mount_dir );
0100   rtems_test_assert( 0 == rv );
0101 
0102   /* See if we can re-mount the file system */
0103   rv = mount( dev_name,
0104               mount_dir,
0105               RTEMS_FILESYSTEM_TYPE_DOSFS,
0106               RTEMS_FILESYSTEM_READ_WRITE,
0107               NULL );
0108   rtems_test_assert( 0 == rv );
0109 
0110   rv = unmount( mount_dir );
0111   rtems_test_assert( 0 == rv );
0112 }
0113 
0114 static void test_create_file(
0115   const char *mount_dir,
0116   uint32_t    file_idx,
0117   bool        expect_ok )
0118 {
0119   char file_name[MAX_PATH_LENGTH + 1];
0120   int  fd;
0121 
0122 
0123   snprintf( file_name,
0124             MAX_PATH_LENGTH,
0125             "%s/file%" PRIu32 ".txt",
0126             mount_dir,
0127             file_idx );
0128   fd = open( file_name,
0129              O_RDWR | O_CREAT | O_TRUNC,
0130              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
0131 
0132   if ( expect_ok ) {
0133     int rv;
0134 
0135     rtems_test_assert( fd >= 0 );
0136 
0137     rv = close( fd );
0138     rtems_test_assert( rv == 0 );
0139   } else {
0140     rtems_test_assert( fd == -1 );
0141   }
0142 }
0143 
0144 static void test_file_creation(
0145   const char    *dev_name,
0146   const char    *mount_dir,
0147   const uint32_t number_of_files )
0148 {
0149   int      rv;
0150   uint32_t file_idx;
0151   char     file_name[MAX_PATH_LENGTH + 1];
0152 
0153 
0154   rv = mount( dev_name,
0155               mount_dir,
0156               RTEMS_FILESYSTEM_TYPE_DOSFS,
0157               RTEMS_FILESYSTEM_READ_WRITE,
0158               NULL );
0159   rtems_test_assert( 0 == rv );
0160 
0161   for ( file_idx = 0; file_idx < number_of_files; ++file_idx ) {
0162     test_create_file( mount_dir, file_idx, true );
0163   }
0164 
0165   test_create_file( mount_dir, file_idx, false );
0166 
0167   for ( file_idx = 0; file_idx < number_of_files; ++file_idx ) {
0168     snprintf( file_name,
0169               MAX_PATH_LENGTH,
0170               "%s/file%" PRIu32 ".txt",
0171               mount_dir,
0172               file_idx );
0173     rv = unlink( file_name );
0174     rtems_test_assert( 0 == rv );
0175   }
0176 
0177   rv = unmount( mount_dir );
0178   rtems_test_assert( 0 == rv );
0179 }
0180 
0181 static void test( void )
0182 {
0183   rtems_status_code            sc;
0184   int                          rv;
0185   const char                   dev_name[]  = "/dev/rda";
0186   const char                   mount_dir[] = "/mnt";
0187   msdos_format_request_param_t rqdata;
0188   rtems_blkdev_bnum            media_block_count;
0189 
0190   memset( &rqdata, 0, sizeof( rqdata ) );
0191 
0192   rv = mkdir( mount_dir, S_IRWXU | S_IRWXG | S_IRWXO );
0193   rtems_test_assert( 0 == rv );
0194 
0195   /* FAT12 */
0196   /* For 1.44 MB disks */
0197   sc = rtems_sparse_disk_create_and_register(
0198     dev_name,
0199     SECTOR_SIZE,
0200     64,
0201     2880,
0202     0
0203     );
0204   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0205 
0206   /* Optimized for disk space */
0207   rqdata.OEMName             = NULL;
0208   rqdata.VolLabel            = NULL;
0209   rqdata.sectors_per_cluster = 1;
0210   rqdata.fat_num             = 1;
0211   rqdata.files_per_root_dir  = 32;
0212   rqdata.media               = 0; /* Media code. 0 == Default */
0213   rqdata.quick_format        = true;
0214   rqdata.skip_alignment      = true;
0215   rv                         = msdos_format( dev_name, &rqdata );
0216   rtems_test_assert( rv == 0 );
0217   test_disk_params( dev_name, mount_dir, SECTOR_SIZE, SECTOR_SIZE, 1 );
0218   test_file_creation( dev_name, mount_dir, rqdata.files_per_root_dir );
0219 
0220   /* Try formatting with invalid values */
0221   rqdata.OEMName             = NULL;
0222   rqdata.VolLabel            = NULL;
0223   rqdata.sectors_per_cluster = 1;
0224   rqdata.fat_num             = 7; /* Invalid number of fats */
0225   rqdata.files_per_root_dir  = 32;
0226   rqdata.media               = 0; /* Media code. 0 == Default */
0227   rqdata.quick_format        = true;
0228   rqdata.skip_alignment      = true;
0229   rv                         = msdos_format( dev_name, &rqdata );
0230   rtems_test_assert( rv != 0 );
0231 
0232   rqdata.OEMName             = NULL;
0233   rqdata.VolLabel            = NULL;
0234   rqdata.sectors_per_cluster = 1;
0235   rqdata.fat_num             = 1;
0236   rqdata.files_per_root_dir  = 32;
0237   rqdata.media               = 0x11; /* Invalid media code */
0238   rqdata.quick_format        = true;
0239   rqdata.skip_alignment      = true;
0240   rv                         = msdos_format( dev_name, &rqdata );
0241   rtems_test_assert( rv != 0 );
0242 
0243   /* Optimized for read/write speed */
0244   rqdata.OEMName             = NULL;
0245   rqdata.VolLabel            = NULL;
0246   rqdata.sectors_per_cluster = 8;
0247   rqdata.fat_num             = 0;
0248   rqdata.files_per_root_dir  = 0;
0249   rqdata.media               = 0; /* Media code. 0 == Default */
0250   rqdata.quick_format        = true;
0251   rqdata.skip_alignment      = false;
0252   rv                         = msdos_format( dev_name, &rqdata );
0253   rtems_test_assert( rv == 0 );
0254   test_disk_params( dev_name,
0255                     mount_dir,
0256                     SECTOR_SIZE,
0257                     SECTOR_SIZE * rqdata.sectors_per_cluster,
0258                     rqdata.sectors_per_cluster );
0259 
0260   /* The same disk formatted with FAT16 because sectors per cluster is too high
0261    * for FAT12 */
0262   rqdata.OEMName             = NULL;
0263   rqdata.VolLabel            = NULL;
0264   rqdata.sectors_per_cluster = 16;
0265   rqdata.fat_num             = 1;
0266   rqdata.files_per_root_dir  = 32;
0267   rqdata.media               = 0; /* Media code. 0 == Default */
0268   rqdata.quick_format        = true;
0269   rqdata.skip_alignment      = false;
0270   rv                         = msdos_format( dev_name, &rqdata );
0271   rtems_test_assert( rv == 0 );
0272   test_disk_params( dev_name,
0273                     mount_dir,
0274                     SECTOR_SIZE,
0275                     SECTOR_SIZE * rqdata.sectors_per_cluster,
0276                     rqdata.sectors_per_cluster );
0277 
0278   rv = unlink( dev_name );
0279   rtems_test_assert( rv == 0 );
0280 
0281   /* Largest FAT12 disk */
0282   sc = rtems_sparse_disk_create_and_register(
0283     dev_name,
0284     SECTOR_SIZE,
0285     64,
0286     ( FAT12_MAX_CLN * FAT12_DEFAULT_SECTORS_PER_CLUSTER ) - 1L,
0287     0
0288     );
0289   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0290 
0291   /* Default parameters (corresponds to optimization for read/write speed) */
0292   rv = msdos_format( dev_name, NULL );
0293   rtems_test_assert( rv == 0 );
0294   test_disk_params( dev_name,
0295                     mount_dir,
0296                     SECTOR_SIZE,
0297                     SECTOR_SIZE * FAT12_DEFAULT_SECTORS_PER_CLUSTER,
0298                     FAT12_DEFAULT_SECTORS_PER_CLUSTER );
0299 
0300   rv = unlink( dev_name );
0301   rtems_test_assert( rv == 0 );
0302 
0303   /* FAT16 */
0304   sc = rtems_sparse_disk_create_and_register(
0305     dev_name,
0306     SECTOR_SIZE,
0307     1024,
0308     ( FAT12_MAX_CLN * FAT12_DEFAULT_SECTORS_PER_CLUSTER ) + 1L,
0309     0
0310     );
0311   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0312 
0313   /* Optimized for disk space */
0314   rqdata.OEMName             = NULL;
0315   rqdata.VolLabel            = NULL;
0316   rqdata.sectors_per_cluster = 1;
0317   rqdata.fat_num             = 1;
0318   rqdata.files_per_root_dir  = 32;
0319   rqdata.media               = 0; /* Media code. 0 == Default */
0320   rqdata.quick_format        = true;
0321   rqdata.skip_alignment      = true;
0322   rv                         = msdos_format( dev_name, &rqdata );
0323   rtems_test_assert( rv == 0 );
0324   test_disk_params( dev_name,
0325                     mount_dir,
0326                     SECTOR_SIZE,
0327                     rqdata.sectors_per_cluster * SECTOR_SIZE,
0328                     rqdata.sectors_per_cluster );
0329 
0330   rv = unlink( dev_name );
0331   rtems_test_assert( rv == 0 );
0332 
0333   sc = rtems_sparse_disk_create_and_register(
0334     dev_name,
0335     SECTOR_SIZE,
0336     1024,
0337     ( FAT16_MAX_CLN * FAT16_DEFAULT_SECTORS_PER_CLUSTER ) - 1L,
0338     0
0339     );
0340   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0341 
0342   /* Optimized for read/write speed */
0343   rqdata.OEMName             = NULL;
0344   rqdata.VolLabel            = NULL;
0345   rqdata.sectors_per_cluster = 64;
0346   rqdata.fat_num             = 0;
0347   rqdata.files_per_root_dir  = 0;
0348   rqdata.media               = 0; /* Media code. 0 == Default */
0349   rqdata.quick_format        = true;
0350   rqdata.skip_alignment      = false;
0351   rv                         = msdos_format( dev_name, &rqdata );
0352   rtems_test_assert( rv == 0 );
0353   test_disk_params( dev_name,
0354                     mount_dir,
0355                     SECTOR_SIZE,
0356                     SECTOR_SIZE * rqdata.sectors_per_cluster,
0357                     rqdata.sectors_per_cluster );
0358 
0359   /* Default parameters (corresponds to optimization for read/write speed) */
0360   rv = msdos_format( dev_name, NULL );
0361   rtems_test_assert( rv == 0 );
0362   test_disk_params( dev_name,
0363                     mount_dir,
0364                     SECTOR_SIZE,
0365                     SECTOR_SIZE * FAT16_DEFAULT_SECTORS_PER_CLUSTER,
0366                     FAT16_DEFAULT_SECTORS_PER_CLUSTER );
0367 
0368   rv = unlink( dev_name );
0369   rtems_test_assert( rv == 0 );
0370 
0371   sc = rtems_sparse_disk_create_and_register(
0372     dev_name,
0373     SECTOR_SIZE,
0374     1024,
0375     ( FAT16_MAX_CLN + 10 ) * 64,
0376     0
0377     );
0378   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0379 
0380   rqdata.OEMName             = NULL;
0381   rqdata.VolLabel            = NULL;
0382   rqdata.sectors_per_cluster = 64;
0383   rqdata.fat_num             = 0;
0384   rqdata.files_per_root_dir  = 0;
0385   rqdata.media               = 0; /* Media code. 0 == Default */
0386   rqdata.quick_format        = true;
0387   rqdata.skip_alignment      = false;
0388   rv                         = msdos_format( dev_name, &rqdata );
0389   rtems_test_assert( rv == 0 );
0390   test_disk_params( dev_name,
0391                     mount_dir,
0392                     SECTOR_SIZE,
0393                     SECTOR_SIZE * rqdata.sectors_per_cluster,
0394                     rqdata.sectors_per_cluster );
0395   rv = unlink( dev_name );
0396   rtems_test_assert( rv == 0 );
0397 
0398   /* Format some disks from 1MB up to 128GB */
0399   rqdata.OEMName             = NULL;
0400   rqdata.VolLabel            = NULL;
0401   rqdata.sectors_per_cluster = 64;
0402   rqdata.fat_num             = 0;
0403   rqdata.files_per_root_dir  = 0;
0404   rqdata.media               = 0;
0405   rqdata.quick_format        = true;
0406   rqdata.skip_alignment      = false;
0407   for (
0408     media_block_count = 1 * 1024 * ( 1024 / SECTOR_SIZE );
0409     media_block_count <= 128 * 1024 * 1024 * ( 1024 / SECTOR_SIZE );
0410     media_block_count *= 2
0411   ) {
0412     sc = rtems_sparse_disk_create_and_register(
0413       dev_name,
0414       SECTOR_SIZE,
0415       64,
0416       media_block_count,
0417       0
0418     );
0419     rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0420 
0421     rv = msdos_format( dev_name, &rqdata );
0422     rtems_test_assert( rv == 0 );
0423 
0424     test_disk_params(
0425       dev_name,
0426       mount_dir,
0427       SECTOR_SIZE,
0428       SECTOR_SIZE * rqdata.sectors_per_cluster,
0429       rqdata.sectors_per_cluster
0430     );
0431 
0432     rv = unlink( dev_name );
0433     rtems_test_assert( rv == 0 );
0434   }
0435 
0436   /* FAT32 */
0437 
0438   sc = rtems_sparse_disk_create_and_register(
0439     dev_name,
0440     SECTOR_SIZE,
0441     1024,
0442     ( FAT16_MAX_CLN * FAT16_DEFAULT_SECTORS_PER_CLUSTER ) + 41L,
0443     0
0444     );
0445   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0446 
0447   /* Default parameters */
0448   rv = msdos_format( dev_name, NULL );
0449   rtems_test_assert( rv == 0 );
0450   test_disk_params( dev_name, mount_dir, SECTOR_SIZE, SECTOR_SIZE, 1 );
0451   rv = unlink( dev_name );
0452   rtems_test_assert( rv == 0 );
0453 
0454   sc = rtems_sparse_disk_create_and_register(
0455     dev_name,
0456     SECTOR_SIZE,
0457     1024,
0458     ( FAT16_MAX_CLN + 20 ) * 64L,
0459     0
0460     );
0461   rtems_test_assert( RTEMS_SUCCESSFUL == sc );
0462 
0463   /* Optimized for read/write speed */
0464   rqdata.OEMName             = NULL;
0465   rqdata.VolLabel            = NULL;
0466   rqdata.sectors_per_cluster = 64;
0467   rqdata.fat_num             = 0;
0468   rqdata.files_per_root_dir  = 0;
0469   rqdata.media               = 0; /* Media code. 0 == Default */
0470   rqdata.quick_format        = true;
0471   rqdata.skip_alignment      = false;
0472   rv                         = msdos_format( dev_name, &rqdata );
0473   rtems_test_assert( rv == 0 );
0474   test_disk_params( dev_name,
0475                     mount_dir,
0476                     SECTOR_SIZE,
0477                     SECTOR_SIZE * rqdata.sectors_per_cluster,
0478                     rqdata.sectors_per_cluster );
0479 
0480   rv = unlink( dev_name );
0481   rtems_test_assert( rv == 0 );
0482 
0483   /* FAT32 with cluster size of 64KiB */
0484 
0485   sc = rtems_sparse_disk_create_and_register(
0486     dev_name,
0487     SECTOR_SIZE,
0488     1024,
0489     16777216, /* 8GiB */
0490     0
0491   );
0492   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0493 
0494   memset( &rqdata, 0, sizeof( rqdata ) );
0495   rqdata.sectors_per_cluster = 128;
0496   rqdata.quick_format = true;
0497   rv = msdos_format( dev_name, &rqdata );
0498   rtems_test_assert( rv == 0 );
0499 
0500   test_disk_params(
0501     dev_name,
0502     mount_dir,
0503     SECTOR_SIZE,
0504     SECTOR_SIZE * rqdata.sectors_per_cluster,
0505     rqdata.sectors_per_cluster
0506   );
0507 
0508   rv = unlink( dev_name );
0509   rtems_test_assert( rv == 0 );
0510 }
0511 
0512 static void Init( rtems_task_argument arg )
0513 {
0514   TEST_BEGIN();
0515 
0516   test();
0517 
0518   TEST_END();
0519   rtems_test_exit( 0 );
0520 }
0521 
0522 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0523 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0524 #define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
0525 
0526 /* one active file + stdin + stdout + stderr + device file when mounted */
0527 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 5
0528 
0529 #define CONFIGURE_FILESYSTEM_DOSFS
0530 
0531 #define CONFIGURE_MAXIMUM_TASKS 1
0532 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0533 
0534 #define CONFIGURE_INIT_TASK_STACK_SIZE ( 32 * 1024 )
0535 
0536 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0537 
0538 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0539 
0540 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
0541 
0542 #define CONFIGURE_BDBUF_BUFFER_MAX_SIZE ( 32 * 1024 )
0543 
0544 #define CONFIGURE_INIT
0545 
0546 #include <rtems/confdefs.h>