source: rtems/testsuites/fstests/fsdosfsname01/init.c @ ccd212e

4.115
Last change on this file since ccd212e was ccd212e, checked in by Ralf Kirchner <ralf.kirchner@…>, on 02/26/13 at 10:18:32

fsdosfsname01: New test

Test handling of file names and directory names according to Microsofts
specification for the FAT file system. So far tested only for the
default character set (code page 850).

  • Property mode set to 100644
File size: 15.5 KB
Line 
1/*
2 * Copyright (c) 2012, 2013 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include "tmacros.h"
20
21#include <fcntl.h>
22#include <dirent.h>
23
24#include <bsp.h>
25#include <rtems/io.h>
26#include <rtems/libio.h>
27#include <rtems/dosfs.h>
28#include <rtems/ramdisk.h>
29#include <rtems/libcsupport.h>
30#include "ramdisk_support.h"
31
32#define MOUNT_DIR "/mnt"
33#define MOUNT_DIR_SIZE 4
34#define START_DIR_SIZE 4
35
36#define NUMBER_OF_DIRECTORIES 8
37#define NUMBER_OF_FILES 13
38#define NUMBER_OF_DIRECTORIES_INVALID 18
39#define NUMBER_OF_DIRECTORIES_DUPLICATED 2
40#define NUMBER_OF_FILES_DUPLICATED 2
41#define MAX_NAME_LENGTH ( 255 + 1 )
42#define MAX_NAME_LENGTH_INVALID ( 255 + 2 )
43#define MAX_DUPLICATES_PER_NAME 3
44
45#define BLOCK_SIZE 512
46
47#define BLOCK_COUNT ( sizeof( image_bin ) / BLOCK_SIZE )
48
49static rtems_resource_snapshot            before_mount;
50
51static const msdos_format_request_param_t rqdata = {
52  .OEMName             = "RTEMS",
53  .VolLabel            = "RTEMSDisk",
54  .sectors_per_cluster = 2,
55  .fat_num             = 0,
56  .files_per_root_dir  = 0,
57  .media               = 0,
58  .quick_format        = true,
59  .skip_alignment      = 0,
60  .info_level          = 0
61};
62
63static const char                         DIRECTORY_NAMES[NUMBER_OF_DIRECTORIES]
64[MAX_NAME_LENGTH] = {
65  "a dir",
66  "Shortdir",
67  "shrtdir",
68  "shrt.dir",
69  "long_conventional_dir",
70  "long_conventional.dir",
71  "LongConventionalDir",
72  "This is a directory name with with 255 characters. The following numbers are aligned in that way, that the character 0 is the mentioned one. xxxxxx150xxxxxxx160xxxxxxx170xxxxxxx180xxxxxxx190xxxxxxx200xxxxxxx210xxxxxxx220xxxxxxx230xxxxxxx240xxxxxxx250xxxxx"
73};
74
75static const char DIRECTORY_NAMES_INVALID[
76  NUMBER_OF_DIRECTORIES_INVALID][MAX_NAME_LENGTH_INVALID] = {
77  "This is a directory name with with 256 characters. The following numbers are aligned in that way, that the character 0 is the mentioned one. xxxxxx150xxxxxxx160xxxxxxx170xxxxxxx180xxxxxxx190xxxxxxx200xxxxxxx210xxxxxxx220xxxxxxx230xxxxxxx240xxxxxxx250xxxxxx",
78  ".",
79  "..",
80  "...",
81  " ",
82  "... ...",
83  " ... ",
84  "",
85  "*",
86  "/",
87  ":",
88  "<",
89  ">",
90  "?",
91  "\\",
92  "|",
93  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
94    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
95    20, 21, 22, 23, 24, 25, 26, 17, 28, 29, 30, 31},
96  {127}
97};
98
99static const char FILE_NAMES[NUMBER_OF_FILES][
100  MAX_NAME_LENGTH] = {
101  "a file",
102  "shrtfile",
103  "ShrtFle",
104  "The quick brown.fox",
105  "long_conventional_file",
106  "This is a filename with with 255 characters. The following numbers are aligned in that way, that the character 0 is the mentioned one. xx140xxxxxxx150xxxxxxx160xxxxxxx170xxxxxxx180xxxxxxx190xxxxxxx200xxxxxxx210xxxxxxx220xxxxxxx230xxxxxxx240xxxxxxx250xxxxx",
107  "+",
108  ",",
109  "a.a",
110  ";",
111  "=",
112  "[",
113  "]"
114};
115
116typedef struct {
117  char name[MAX_NAME_LENGTH];
118  unsigned int number_of_duplicates;
119  char name_duplicates[MAX_DUPLICATES_PER_NAME][MAX_NAME_LENGTH];
120} name_duplicates;
121
122static const name_duplicates DIRECTORY_DUPLICATES[
123  NUMBER_OF_DIRECTORIES_DUPLICATED] = {
124  {
125    "shrtdir",
126    3,
127    {
128      "shrtdir",
129      "SHRTDIR",
130      "Shrtdir"
131    }
132  },
133  {
134    "long_conventional_dir",
135    3,
136    {
137      "long_conventional_dir",
138      "LONG_CONVENTIONAL_DIR",
139      "Long_conventional_dir"
140    }
141  }
142};
143
144static const name_duplicates MULTIBYTE_DUPLICATES[
145  NUMBER_OF_MULTIBYTE_NAMES_DUPLICATED] = {
146  {
147    /* The angstroem encoded differently. These encodings might become short entries */
148    {0xc3, 0x85}, /* '̊A' */
149    2,
150    {
151      {0xc3, 0x85}, /* '̊A' */
152      {0xe2, 0x84, 0xab} /* 'Å' */
153    }
154  },
155
156  /* Again the angstroem encoded differently,
157   * but this time with additional characters in order to enforce a long entry. */
158  {
159    {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', 0xc3,
160     0x85},
161    2,
162    {
163      {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', 0xc3,
164       0x85},
165      {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', 0xe2,
166       0x84, 0xab}
167    }
168  }
169};
170
171static const name_duplicates FILES_DUPLICATES[NUMBER_OF_FILES_DUPLICATED] = {
172  {
173    "shrtfile",
174    3,
175    {
176      "shrtfile",
177      "SHRTFILE",
178      "Shrtfile"
179    }
180  },
181  {
182    "long_conventional_file",
183    3,
184    {
185      "long_conventional_file",
186      "LONG_CONVENTIONAL_FILE",
187      "Long_conventional_file"
188    }
189  }
190};
191
192static int path_is_directory( const char *path )
193{
194  struct stat s_buf;
195
196
197  if ( stat( path, &s_buf ) )
198    return 0;
199
200  return S_ISDIR( s_buf.st_mode );
201}
202
203static void delete_folder_tree( const char *directory_name )
204{
205  DIR           *dp;
206  struct dirent *ep;
207  char           p_buf[1024] = {0};
208  int            rc          = 0;
209
210
211  dp = opendir( directory_name );
212  rtems_test_assert( dp != NULL );
213
214  while ( ( ep = readdir( dp ) ) != NULL && rc == 0 ) {
215    if ( 0 != strcmp( ".", ep->d_name )
216         && 0 != strcmp( "..", ep->d_name ) ) {
217      snprintf( p_buf, sizeof( p_buf ), "%s/%s", directory_name, ep->d_name );
218
219      if ( path_is_directory( p_buf ) ) {
220        delete_folder_tree( p_buf );
221        rc = rmdir( p_buf );
222        rtems_test_assert( rc == 0 );
223        rewinddir( dp );
224      } else {
225        rc = unlink( p_buf );
226        rtems_test_assert( rc == 0 );
227        rewinddir( dp );
228      }
229    }
230  }
231
232  rc = closedir( dp );
233  rtems_test_assert( rc == 0 );
234}
235
236static void mount_device( const char *start_dir,
237  const rtems_dosfs_mount_options    *mount_opts )
238{
239  int rc;
240
241  rc = mount(
242    RAMDISK_PATH,
243    MOUNT_DIR,
244    "dosfs",
245    RTEMS_FILESYSTEM_READ_WRITE,
246    mount_opts );
247  rtems_test_assert( rc == 0 );
248
249  rc = mkdir( start_dir, S_IRWXU | S_IRWXG | S_IRWXO );
250  rtems_test_assert( rc == 0 || ( rc == -1 && errno == EEXIST ) );
251}
252
253static void mount_device_with_defaults( const char *start_dir )
254{
255  int rc;
256
257
258  rc = msdos_format( RAMDISK_PATH, &rqdata );
259  rtems_test_assert( rc == 0 );
260
261  rtems_resource_snapshot_take( &before_mount );
262
263  mount_device( start_dir, NULL );
264}
265
266static void unmount_and_close_device( void )
267{
268  int                     rc;
269  rtems_resource_snapshot now;
270  bool                    are_resources_freed;
271
272
273  delete_folder_tree( MOUNT_DIR );
274
275  rc = unmount( MOUNT_DIR );
276  rtems_test_assert( rc == 0 );
277
278  are_resources_freed = rtems_resource_snapshot_check( &before_mount );
279
280  if ( !are_resources_freed )
281    rtems_resource_snapshot_take( &now );
282
283  rtems_test_assert( are_resources_freed );
284}
285
286/*
287 * Simply create a few directories. These tests should all succeed
288 */
289static void test_creating_directories(
290  const char        *start_dir,
291  const char        *directories,
292  const unsigned int number_of_directories )
293{
294  unsigned int   index;
295  int            rc;
296  char           dirname[MAX_NAME_LENGTH + strlen( start_dir ) + 1];
297  DIR           *dirp;
298  struct dirent *dp;
299
300
301  for ( index = 0; index < number_of_directories; ++index ) {
302    snprintf( dirname, sizeof( dirname ), "%s/%s", start_dir, directories
303              + ( index * MAX_NAME_LENGTH ) );
304    rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
305    rtems_test_assert( rc == 0 );
306  }
307
308  dirp = opendir( start_dir );
309  rtems_test_assert( NULL != dirp );
310
311  index = 0;
312  dp    = readdir( dirp );
313  rtems_test_assert( dp != NULL );
314  rtems_test_assert( 0 == strcmp( ".", dp->d_name ) );
315
316  dp = readdir( dirp );
317  rtems_test_assert( dp != NULL );
318  rtems_test_assert( 0 == strcmp( "..", dp->d_name ) );
319
320  dp = readdir( dirp );
321  rtems_test_assert( dp != NULL );
322
323  while ( dp != NULL ) {
324    rtems_test_assert( 0
325                       == strcmp( directories + ( index * MAX_NAME_LENGTH ),
326                                  dp->d_name ) );
327    ++index;
328    dp = readdir( dirp );
329  }
330
331  rtems_test_assert( number_of_directories == index );
332
333  rc = closedir( dirp );
334  rtems_test_assert( rc == 0 );
335}
336
337/*
338 * Try creating directories with invalid names.
339 */
340static void test_creating_invalid_directories( void )
341{
342  unsigned int index;
343  int          rc;
344  char         dirname[MAX_NAME_LENGTH_INVALID + MOUNT_DIR_SIZE + 1];
345
346
347  for ( index = 0; index < NUMBER_OF_DIRECTORIES_INVALID; ++index ) {
348    snprintf( dirname,
349              sizeof( dirname ),
350              "%s/%s",
351              MOUNT_DIR,
352              DIRECTORY_NAMES_INVALID[index] );
353    rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
354    rtems_test_assert( rc == -1 );
355  }
356}
357
358/*
359 * Try creating directories which do already exist
360 * (although names may have different capitalization/encoding)
361 */
362static void test_creating_duplicate_directories(
363  const char            *start_dir,
364  const name_duplicates *duplicates,
365  const unsigned int     number_of_duplicates )
366{
367  unsigned int index_dir;
368  unsigned int index_duplicate;
369  int          rc;
370  char         dirname[MAX_NAME_LENGTH + MOUNT_DIR_SIZE + START_DIR_SIZE + 2];
371
372
373  for ( index_dir = 0; index_dir < number_of_duplicates; ++index_dir ) {
374    snprintf( dirname, sizeof( dirname ), "%s/%s", start_dir,
375              duplicates[index_dir].name );
376    rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
377    rtems_test_assert( rc == 0 );
378
379    for ( index_duplicate = 0;
380          index_duplicate < duplicates[index_dir].number_of_duplicates;
381          ++index_duplicate ) {
382      snprintf( dirname, sizeof( dirname ), "%s/%s", start_dir,
383                duplicates[index_dir].name_duplicates[index_duplicate] );
384      rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
385      rtems_test_assert( rc < 0 );
386    }
387  }
388}
389
390/*
391 * Try creating and opening files with valid names
392 */
393static void test_handling_files(
394  const char        *dirname,
395  const char        *file_names,
396  const unsigned int number_of_files )
397{
398  unsigned int index;
399  int          rc;
400  char         filename[MAX_NAME_LENGTH * 2 + MOUNT_DIR_SIZE + START_DIR_SIZE
401                        + 4];
402  int          fd;
403
404
405  for ( index = 0; index < number_of_files; ++index ) {
406    snprintf(
407      filename,
408      sizeof( filename ) - 1,
409      "%s/%s",
410      dirname,
411      file_names + index * MAX_NAME_LENGTH );
412    fd = open( filename,
413               O_RDWR | O_CREAT,
414               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
415    rtems_test_assert( fd >= 0 );
416
417    rc = close( fd );
418    rtems_test_assert( rc == 0 );
419
420    /* See if the file still exists and can be found */
421    fd = open( filename, O_RDWR );
422    rtems_test_assert( fd >= 0 );
423
424    rc = close( fd );
425    rtems_test_assert( rc == 0 );
426  }
427}
428
429/*
430 * Try opening files which do already exist (with different capitalization in their names)
431 */
432static void test_duplicated_files( const char *dirname,
433  const name_duplicates                       *files_duplicated,
434  const unsigned int                           number_of_files_duplicated )
435{
436  unsigned int index_file;
437  unsigned int index_duplicate;
438  int          rc;
439  char         filename[MAX_NAME_LENGTH + strlen( dirname ) + 1];
440  int          fd;
441
442
443  for ( index_file = 0; index_file < number_of_files_duplicated;
444        ++index_file ) {
445    snprintf( filename,
446              sizeof( filename ) - 1,
447              "%s/%s",
448              dirname,
449              files_duplicated[index_file].name );
450    fd = open( filename,
451               O_RDWR | O_CREAT,
452               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
453    rtems_test_assert( fd >= 0 );
454
455    rc = close( fd );
456    rtems_test_assert( rc == 0 );
457
458    for ( index_duplicate = 0;
459          index_duplicate < files_duplicated[index_file].number_of_duplicates;
460          ++index_duplicate ) {
461      snprintf( filename,
462                sizeof( filename ) - 1,
463                "%s/%s",
464                dirname,
465                files_duplicated[index_file].name_duplicates[index_duplicate] );
466      fd = open( filename, O_RDWR );
467      rtems_test_assert( fd >= 0 );
468
469      rc = close( fd );
470      rtems_test_assert( rc == 0 );
471    }
472
473    rc = remove( filename );
474    rtems_test_assert( rc == 0 );
475  }
476}
477
478/*
479 * Open and read existing valid directories
480 */
481static void test_handling_directories(
482  const char        *start_dir,
483  const char        *directory_names,
484  const unsigned int number_of_directories,
485  const char        *file_names,
486  const unsigned int number_of_files )
487{
488  unsigned int   index_directory;
489  unsigned int   index_file;
490  int            rc;
491  DIR           *dir_stream;
492  char           dirname[MAX_NAME_LENGTH * 2];
493  struct dirent *dp;
494
495
496  for ( index_directory = 0;
497        index_directory < number_of_directories;
498        ++index_directory ) {
499    snprintf(
500      dirname,
501      sizeof( dirname ) - 1,
502      "%s/%s",
503      start_dir,
504      directory_names + index_directory * MAX_NAME_LENGTH );
505
506    test_handling_files(
507      dirname,
508      file_names,
509      number_of_files );
510
511    dir_stream = opendir( dirname );
512    rtems_test_assert( dir_stream != NULL );
513
514    dp = readdir( dir_stream );
515    rtems_test_assert( dp != NULL );
516    rtems_test_assert( 0 == strcmp( ".", dp->d_name ) );
517
518    dp = readdir( dir_stream );
519    rtems_test_assert( dp != NULL );
520    rtems_test_assert( 0 == strcmp( "..", dp->d_name ) );
521
522    dp         = readdir( dir_stream );
523    rtems_test_assert( dp != NULL );
524    index_file = 0;
525
526    while ( dp != NULL ) {
527      rtems_test_assert( 0 == strcmp(
528                           file_names + index_file * MAX_NAME_LENGTH,
529                           dp->d_name ) );
530      ++index_file;
531      dp = readdir( dir_stream );
532    }
533
534    rtems_test_assert( number_of_files == index_file );
535
536    rc = closedir( dir_stream );
537    rtems_test_assert( rc == 0 );
538  }
539}
540
541/*
542 * Main test method
543 */
544static void test( void )
545{
546  int  rc;
547  char start_dir[MOUNT_DIR_SIZE + START_DIR_SIZE + 2];
548
549
550  rc = mkdir( MOUNT_DIR, S_IRWXU | S_IRWXG | S_IRWXO );
551  rtems_test_assert( rc == 0 );
552
553  init_ramdisk();
554
555  snprintf( start_dir, sizeof( start_dir ), "%s/%s", MOUNT_DIR, "strt" );
556
557  /*
558   * Tests with code page 850 compatible directory and file names
559   * and the code page 850 backwards compatible default mode mode of the
560   * FAT file system
561   */
562  mount_device_with_defaults( start_dir );
563
564  test_creating_duplicate_directories(
565    &start_dir[0],
566    &DIRECTORY_DUPLICATES[0],
567    NUMBER_OF_DIRECTORIES_DUPLICATED );
568
569  unmount_and_close_device();
570
571  mount_device_with_defaults( start_dir );
572
573  test_duplicated_files(
574    MOUNT_DIR,
575    FILES_DUPLICATES,
576    NUMBER_OF_FILES_DUPLICATED );
577
578  unmount_and_close_device();
579
580  mount_device_with_defaults( start_dir );
581
582  test_creating_invalid_directories();
583
584  test_creating_directories(
585    &start_dir[0],
586    &DIRECTORY_NAMES[0][0],
587    NUMBER_OF_DIRECTORIES );
588
589  test_handling_directories(
590    &start_dir[0],
591    &DIRECTORY_NAMES[0][0],
592    NUMBER_OF_DIRECTORIES,
593    &FILE_NAMES[0][0],
594    NUMBER_OF_FILES );
595
596  unmount_and_close_device();
597
598  del_ramdisk();
599}
600
601static void Init( rtems_task_argument arg )
602{
603  puts( "\n\n*** TEST fsdosfsname01 ***" );
604
605  test();
606
607  puts( "*** END OF TEST fsdosfsname01 ***" );
608
609  rtems_test_exit( 0 );
610}
611
612#define CONFIGURE_INIT_TASK_STACK_SIZE ( 1024 * 64 )
613#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
614#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
615#define CONFIGURE_MAXIMUM_DRIVERS 4
616#define CONFIGURE_MAXIMUM_SEMAPHORES RTEMS_DOSFS_SEMAPHORES_PER_INSTANCE
617
618#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
619
620#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
621
622#define CONFIGURE_FILESYSTEM_DOSFS
623
624/* 1 RAM disk device file + 1 mount_dir + stdin + stdout + stderr + 2 for open directories/files */
625#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS ( 5 + 2 )
626
627#define CONFIGURE_MAXIMUM_TASKS 1
628
629#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
630
631#define CONFIGURE_INIT
632
633#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.