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

Last change on this file since d50ab079 was d50ab079, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 16, 2017 at 2:12:20 PM

dosfs: Fix file name search

Do not use our long file name entry count to optimize the file name
search. The Unicode comparison must be taken into account.

Update #2939.

  • Property mode set to 100644
File size: 34.4 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.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19
20#include "tmacros.h"
21
22#include <errno.h>
23#include <fcntl.h>
24#include <dirent.h>
25
26#include <bsp.h>
27#include <rtems/io.h>
28#include <rtems/libio.h>
29#include <rtems/dosfs.h>
30#include <rtems/ramdisk.h>
31#include <rtems/libcsupport.h>
32#include "image.h"
33#include "image_bin_le_singlebyte.h"
34#include "image_bin_le_multibyte.h"
35#include "files.h"
36
37#include <errno.h>
38
39const char rtems_test_name[] = "FSDOSFSNAME 1";
40
41#define PRINT_DISK_IMAGE 0
42
43#define MOUNT_DIR "/mnt"
44#define MOUNT_DIR_SIZE 4
45#define START_DIR_SIZE 4
46#define RAMDISK_PATH "/dev/rda"
47#define BLOCK_NUM 47
48#define BLOCK_SIZE 512
49
50#define NUMBER_OF_DIRECTORIES 8
51#define NUMBER_OF_FILES 13
52#define NUMBER_OF_DIRECTORIES_INVALID 25
53#define NUMBER_OF_DIRECTORIES_DUPLICATED 3
54#define NUMBER_OF_MULTIBYTE_NAMES_DUPLICATED 2
55#define NUMBER_OF_FILES_DUPLICATED 2
56#define NUMBER_OF_NAMES_MULTIBYTE 10
57#define MAX_NAME_LENGTH ( 255 + 1 )
58#define MAX_NAME_LENGTH_INVALID ( 255 + 2 )
59#define MAX_DUPLICATES_PER_NAME 3
60static const char UTF8_BOM[] = {0xEF, 0xBB, 0xBF};
61#define UTF8_BOM_SIZE 3 /* Size of the UTF-8 byte-order-mark */
62
63#define BLOCK_SIZE 512
64
65#define BLOCK_COUNT ( sizeof( image_bin ) / BLOCK_SIZE )
66
67static ramdisk                            disk_image = {
68  .block_size             = BLOCK_SIZE,
69  .block_num              = BLOCK_COUNT,
70  .area                   = &image_bin[0],
71  .initialized            = true,
72  .malloced               = false,
73  .trace                  = false,
74  .free_at_delete_request = false
75};
76
77static rtems_resource_snapshot            before_mount;
78
79static const msdos_format_request_param_t rqdata = {
80  .OEMName             = "RTEMS",
81  .VolLabel            = "RTEMSDisk",
82  .sectors_per_cluster = 2,
83  .fat_num             = 0,
84  .files_per_root_dir  = 0,
85  .media               = 0,
86  .quick_format        = true,
87  .skip_alignment      = 0,
88  .info_level          = 0
89};
90
91static const char                         DIRECTORY_NAMES[NUMBER_OF_DIRECTORIES]
92[MAX_NAME_LENGTH] = {
93  "a dir",
94  "Shortdir",
95  "shrtdir",
96  "shrt.dir",
97  "long_conventional_dir",
98  "long_conventional.dir",
99  "LongConventionalDir",
100  "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"
101};
102
103static const char DIRECTORY_NAMES_INVALID[
104  NUMBER_OF_DIRECTORIES_INVALID][MAX_NAME_LENGTH_INVALID] = {
105  "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",
106  ".",
107  "..",
108  "...",
109  " ",
110  "... ...",
111  " ... ",
112  "",
113  "*",
114  "/",
115  ":",
116  "<",
117  ">",
118  "?",
119  "\\",
120  "|",
121  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
122    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
123    20, 21, 22, 23, 24, 25, 26, 17, 28, 29, 30, 31},
124  {127},
125  "э*_тП ЎлОММПе ОЌя",
126  "э:_тП ЎлОММПе ОЌя",
127  "э<_тП ЎлОММПе ОЌя",
128  "э>_тП ЎлОММПе ОЌя",
129  "э?_тП ЎлОММПе ОЌя",
130  "э|_тП ЎлОММПе ОЌя"
131};
132
133static const char NAMES_MULTIBYTE[
134  NUMBER_OF_NAMES_MULTIBYTE][MAX_NAME_LENGTH] = {
135  "đây là một tên tập tin dài",
136  "Bu uzun bir dosya adı",
137  "هذا هو اسم ملف طويل",
138  "αυτό είΜαι έΜα Όεγάλο όΜοΌα αρχείου",
139  "этП ЎлОММПе ОЌя",
140  "гэта ЎПўгае іЌя",
141  "тПва е ЎългП ОЌе Ма файла",
142  "这是䞀䞪长文件名",
143  "shrtname",
144  "long_conventional_name"
145};
146
147static const char NAMES_MULTIBYTE_IN_CODEPAGE_FORMAT[
148  NUMBER_OF_NAMES_MULTIBYTE][MAX_NAME_LENGTH] = {
149  "_\2030005~1._t",
150  "bu0008~1.bir",
151  "__000b~1.__",
152  "__000f~1.__",
153  "__0012~1.___",
154  "__0015~1.___",
155  "__0018~1.___",
156  "__001a~1",
157  "shrtname",
158  "long_conventional_name"
159};
160
161static const char FILE_NAMES[NUMBER_OF_FILES][
162  MAX_NAME_LENGTH] = {
163  "a file",
164  "shrtfile",
165  "ShrtFle",
166  "The quick brown.fox",
167  "long_conventional_file",
168  "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",
169  "+",
170  ",",
171  "a.a",
172  ";",
173  "=",
174  "[",
175  "]"
176};
177
178typedef struct {
179  char name[MAX_NAME_LENGTH];
180  unsigned int number_of_duplicates;
181  char name_duplicates[MAX_DUPLICATES_PER_NAME][MAX_NAME_LENGTH];
182} name_duplicates;
183
184static const name_duplicates DIRECTORY_DUPLICATES[
185  NUMBER_OF_DIRECTORIES_DUPLICATED] = {
186  {
187    "shrtdir",
188    3,
189    {
190      "shrtdir",
191      "SHRTDIR",
192      "Shrtdir"
193    }
194  },
195  {
196    "Kurzdir",
197    3,
198    {
199      "kurzdir",
200      "KURZDIR",
201      "Kurzdir"
202    }
203  },
204  {
205    "long_conventional_dir",
206    3,
207    {
208      "long_conventional_dir",
209      "LONG_CONVENTIONAL_DIR",
210      "Long_conventional_dir"
211    }
212  }
213};
214
215static const name_duplicates MULTIBYTE_DUPLICATES[
216  NUMBER_OF_MULTIBYTE_NAMES_DUPLICATED] = {
217  {
218    /* The angstroem encoded differently. These encodings might become short entries */
219    {0xc3, 0x85}, /* '̊A' */
220    2,
221    {
222      {0xc3, 0x85}, /* '̊A' */
223      {0xe2, 0x84, 0xab} /* 'Å' */
224    }
225  },
226
227  /* Again the angstroem encoded differently,
228   * but this time with additional characters in order to enforce a long entry. */
229  {
230    {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', 0xc3,
231     0x85},
232    2,
233    {
234      {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', 0xc3,
235       0x85},
236      {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', 0xe2,
237       0x84, 0xab}
238    }
239  }
240};
241
242
243static const name_duplicates FILES_DUPLICATES[NUMBER_OF_FILES_DUPLICATED] = {
244  {
245    "shrtfile",
246    3,
247    {
248      "shrtfile",
249      "SHRTFILE",
250      "Shrtfile"
251    }
252  },
253  {
254    "long_conventional_file",
255    3,
256    {
257      "long_conventional_file",
258      "LONG_CONVENTIONAL_FILE",
259      "Long_conventional_file"
260    }
261  }
262};
263
264static int path_is_directory( const char *path )
265{
266  struct stat s_buf;
267
268
269  if ( stat( path, &s_buf ) )
270    return 0;
271
272  return S_ISDIR( s_buf.st_mode );
273}
274
275static void delete_folder_tree( const char *directory_name )
276{
277  DIR           *dp;
278  struct dirent *ep;
279  char           p_buf[1024] = {0};
280  int            rc          = 0;
281
282
283  dp = opendir( directory_name );
284  rtems_test_assert( dp != NULL );
285
286  while ( ( ep = readdir( dp ) ) != NULL && rc == 0 ) {
287    if ( 0 != strcmp( ".", ep->d_name )
288         && 0 != strcmp( "..", ep->d_name ) ) {
289      snprintf( p_buf, sizeof( p_buf ), "%s/%s", directory_name, ep->d_name );
290
291      if ( path_is_directory( p_buf ) ) {
292        delete_folder_tree( p_buf );
293        rc = rmdir( p_buf );
294        rtems_test_assert( rc == 0 );
295        rewinddir( dp );
296      } else {
297        rc = unlink( p_buf );
298        rtems_test_assert( rc == 0 );
299        rewinddir( dp );
300      }
301    }
302  }
303
304  rc = closedir( dp );
305  rtems_test_assert( rc == 0 );
306}
307
308static void mount_device( const char *start_dir,
309  const rtems_dosfs_mount_options    *mount_opts )
310{
311  int rc;
312
313  rc = mount(
314    RAMDISK_PATH,
315    MOUNT_DIR,
316    "dosfs",
317    RTEMS_FILESYSTEM_READ_WRITE,
318    mount_opts );
319  rtems_test_assert( rc == 0 );
320
321  rc = mkdir( start_dir, S_IRWXU | S_IRWXG | S_IRWXO );
322  rtems_test_assert( rc == 0 || ( rc == -1 && errno == EEXIST ) );
323}
324
325static void mount_device_with_defaults( const char *start_dir )
326{
327  int rc;
328
329
330  rc = msdos_format( RAMDISK_PATH, &rqdata );
331  rtems_test_assert( rc == 0 );
332
333  rtems_resource_snapshot_take( &before_mount );
334
335  mount_device( start_dir, NULL );
336}
337
338static void mount_device_with_iconv(
339  const char                *start_dir,
340  rtems_dosfs_mount_options *mount_opts
341)
342{
343  int                       rc;
344
345  rc = msdos_format( RAMDISK_PATH, &rqdata );
346  rtems_test_assert( rc == 0 );
347
348  rtems_resource_snapshot_take( &before_mount );
349
350  mount_opts->converter = rtems_dosfs_create_utf8_converter( "CP850" );
351  rtems_test_assert( mount_opts->converter != NULL );
352
353  mount_device( start_dir, mount_opts );
354}
355
356static void unmount_and_close_device( void )
357{
358  int                     rc;
359  rtems_resource_snapshot now;
360  bool                    are_resources_freed;
361
362
363  delete_folder_tree( MOUNT_DIR );
364
365  rc = unmount( MOUNT_DIR );
366  rtems_test_assert( rc == 0 );
367
368  are_resources_freed = rtems_resource_snapshot_check( &before_mount );
369
370  if ( !are_resources_freed )
371    rtems_resource_snapshot_take( &now );
372
373  rtems_test_assert( are_resources_freed );
374}
375
376/*
377 * Simply create a few directories. These tests should all succeed
378 */
379static void test_creating_directories(
380  const char        *start_dir,
381  const char        *directories,
382  const unsigned int number_of_directories )
383{
384  unsigned int   index;
385  int            rc;
386  char           dirname[MAX_NAME_LENGTH + strlen( start_dir ) + 1];
387  DIR           *dirp;
388  struct dirent *dp;
389
390
391  for ( index = 0; index < number_of_directories; ++index ) {
392    snprintf( dirname, sizeof( dirname ), "%s/%s", start_dir, directories
393              + ( index * MAX_NAME_LENGTH ) );
394    rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
395    rtems_test_assert( rc == 0 );
396  }
397
398  dirp = opendir( start_dir );
399  rtems_test_assert( NULL != dirp );
400
401  index = 0;
402  dp    = readdir( dirp );
403  rtems_test_assert( dp != NULL );
404  rtems_test_assert( 0 == strcmp( ".", dp->d_name ) );
405
406  dp = readdir( dirp );
407  rtems_test_assert( dp != NULL );
408  rtems_test_assert( 0 == strcmp( "..", dp->d_name ) );
409
410  dp = readdir( dirp );
411  rtems_test_assert( dp != NULL );
412
413  while ( dp != NULL ) {
414    rtems_test_assert( 0
415                       == strcmp( directories + ( index * MAX_NAME_LENGTH ),
416                                  dp->d_name ) );
417    ++index;
418    dp = readdir( dirp );
419  }
420
421  rtems_test_assert( number_of_directories == index );
422
423  rc = closedir( dirp );
424  rtems_test_assert( rc == 0 );
425}
426
427/*
428 * Try creating directories with invalid names.
429 */
430static void test_creating_invalid_directories( void )
431{
432  unsigned int index;
433  int          rc;
434  char         dirname[MAX_NAME_LENGTH_INVALID + MOUNT_DIR_SIZE + 1];
435
436
437  for ( index = 0; index < NUMBER_OF_DIRECTORIES_INVALID; ++index ) {
438    snprintf( dirname,
439              sizeof( dirname ),
440              "%s/%s",
441              MOUNT_DIR,
442              DIRECTORY_NAMES_INVALID[index] );
443    rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
444    rtems_test_assert( rc == -1 );
445  }
446}
447
448/*
449 * Try creating directories which do already exist
450 * (although names may have different capitalization/encoding)
451 */
452static void test_creating_duplicate_directories(
453  const char            *start_dir,
454  const name_duplicates *duplicates,
455  const unsigned int     number_of_duplicates )
456{
457  unsigned int index_dir;
458  unsigned int index_duplicate;
459  int          rc;
460  char         dirname[MAX_NAME_LENGTH + MOUNT_DIR_SIZE + START_DIR_SIZE + 2];
461
462
463  for ( index_dir = 0; index_dir < number_of_duplicates; ++index_dir ) {
464    snprintf( dirname, sizeof( dirname ), "%s/%s", start_dir,
465              duplicates[index_dir].name );
466    rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
467    rtems_test_assert( rc == 0 );
468
469    for ( index_duplicate = 0;
470          index_duplicate < duplicates[index_dir].number_of_duplicates;
471          ++index_duplicate ) {
472      snprintf( dirname, sizeof( dirname ), "%s/%s", start_dir,
473                duplicates[index_dir].name_duplicates[index_duplicate] );
474      errno = 0;
475      rc = mkdir( dirname, S_IRWXU | S_IRWXG | S_IRWXO );
476      rtems_test_assert( rc == -1 );
477      rtems_test_assert( errno == EEXIST );
478    }
479  }
480}
481
482/*
483 * Try creating and opening files with valid names
484 */
485static void test_handling_files(
486  const char        *dirname,
487  const char        *file_names,
488  const unsigned int number_of_files )
489{
490  unsigned int index;
491  int          rc;
492  char         filename[MAX_NAME_LENGTH * 2 + MOUNT_DIR_SIZE + START_DIR_SIZE
493                        + 4];
494  int          fd;
495
496
497  for ( index = 0; index < number_of_files; ++index ) {
498    snprintf(
499      filename,
500      sizeof( filename ) - 1,
501      "%s/%s",
502      dirname,
503      file_names + index * MAX_NAME_LENGTH );
504    fd = open( filename,
505               O_RDWR | O_CREAT,
506               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
507    rtems_test_assert( fd >= 0 );
508
509    rc = close( fd );
510    rtems_test_assert( rc == 0 );
511
512    /* See if the file still exists and can be found */
513    fd = open( filename, O_RDWR );
514    rtems_test_assert( fd >= 0 );
515
516    rc = close( fd );
517    rtems_test_assert( rc == 0 );
518  }
519}
520
521/*
522 * Try to find (and open) all of the file names from an
523 * array in a given directory
524 */
525static void test_finding_files(
526  const char        *dirname,
527  const char        *file_names,
528  const unsigned int number_of_files )
529{
530  int            rc;
531  DIR           *dir_stream;
532  struct dirent *dp;
533  int            fd;
534  unsigned int   index_file;
535  char           filename[MAX_NAME_LENGTH * 2 + MOUNT_DIR_SIZE
536                          + START_DIR_SIZE + 4];
537
538
539  dir_stream = opendir( dirname );
540  rtems_test_assert( dir_stream != NULL );
541
542  dp = readdir( dir_stream );
543  rtems_test_assert( dp != NULL );
544  rtems_test_assert( 0 == strcmp( ".", dp->d_name ) );
545
546  dp = readdir( dir_stream );
547  rtems_test_assert( dp != NULL );
548  rtems_test_assert( 0 == strcmp( "..", dp->d_name ) );
549
550  dp         = readdir( dir_stream );
551  rtems_test_assert( dp != NULL );
552  index_file = 0;
553
554  while ( dp != NULL ) {
555    rtems_test_assert( 0 == strcmp(
556                         file_names + index_file * MAX_NAME_LENGTH,
557                         dp->d_name ) );
558
559    snprintf(
560      filename,
561      sizeof( filename ) - 1,
562      "%s/%s",
563      dirname,
564      file_names + index_file * MAX_NAME_LENGTH );
565
566    /* See if the file still exists and can be found */
567    fd = open( filename, O_RDWR );
568    rtems_test_assert( fd >= 0 );
569
570    rc = close( fd );
571    rtems_test_assert( rc == 0 );
572
573    ++index_file;
574    dp = readdir( dir_stream );
575  }
576
577  rtems_test_assert( number_of_files == index_file );
578
579  rc = closedir( dir_stream );
580  rtems_test_assert( rc == 0 );
581}
582
583/*
584 * Try opening files which do already exist (with different capitalization in their names)
585 */
586static void test_duplicated_files( const char *dirname,
587  const name_duplicates                       *files_duplicated,
588  const unsigned int                           number_of_files_duplicated )
589{
590  unsigned int index_file;
591  unsigned int index_duplicate;
592  int          rc;
593  char         filename[MAX_NAME_LENGTH + strlen( dirname ) + 1];
594  int          fd;
595
596
597  for ( index_file = 0; index_file < number_of_files_duplicated;
598        ++index_file ) {
599    snprintf( filename,
600              sizeof( filename ) - 1,
601              "%s/%s",
602              dirname,
603              files_duplicated[index_file].name );
604    fd = open( filename,
605               O_RDWR | O_CREAT,
606               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
607    rtems_test_assert( fd >= 0 );
608
609    rc = close( fd );
610    rtems_test_assert( rc == 0 );
611
612    for ( index_duplicate = 0;
613          index_duplicate < files_duplicated[index_file].number_of_duplicates;
614          ++index_duplicate ) {
615      snprintf( filename,
616                sizeof( filename ) - 1,
617                "%s/%s",
618                dirname,
619                files_duplicated[index_file].name_duplicates[index_duplicate] );
620      fd = open( filename, O_RDWR );
621      rtems_test_assert( fd >= 0 );
622
623      rc = close( fd );
624      rtems_test_assert( rc == 0 );
625
626      errno = 0;
627      fd = open( filename, O_RDWR | O_CREAT | O_EXCL );
628      rtems_test_assert( fd == -1 );
629      rtems_test_assert( errno == EEXIST );
630    }
631
632    rc = remove( filename );
633    rtems_test_assert( rc == 0 );
634  }
635}
636
637/*
638 * Open and read existing valid directories
639 */
640static void test_handling_directories(
641  const char        *start_dir,
642  const char        *directory_names,
643  const unsigned int number_of_directories,
644  const char        *file_names,
645  const unsigned int number_of_files )
646{
647  unsigned int   index_directory;
648  unsigned int   index_file;
649  int            rc;
650  DIR           *dir_stream;
651  char           dirname[MAX_NAME_LENGTH * 2];
652  struct dirent *dp;
653
654
655  for ( index_directory = 0;
656        index_directory < number_of_directories;
657        ++index_directory ) {
658    snprintf(
659      dirname,
660      sizeof( dirname ) - 1,
661      "%s/%s",
662      start_dir,
663      directory_names + index_directory * MAX_NAME_LENGTH );
664
665    test_handling_files(
666      dirname,
667      file_names,
668      number_of_files );
669
670    dir_stream = opendir( dirname );
671    rtems_test_assert( dir_stream != NULL );
672
673    dp = readdir( dir_stream );
674    rtems_test_assert( dp != NULL );
675    rtems_test_assert( 0 == strcmp( ".", dp->d_name ) );
676
677    dp = readdir( dir_stream );
678    rtems_test_assert( dp != NULL );
679    rtems_test_assert( 0 == strcmp( "..", dp->d_name ) );
680
681    dp         = readdir( dir_stream );
682    rtems_test_assert( dp != NULL );
683    index_file = 0;
684
685    while ( dp != NULL ) {
686      rtems_test_assert( 0 == strcmp(
687                           file_names + index_file * MAX_NAME_LENGTH,
688                           dp->d_name ) );
689      ++index_file;
690      dp = readdir( dir_stream );
691    }
692
693    rtems_test_assert( number_of_files == index_file );
694
695    rc = closedir( dir_stream );
696    rtems_test_assert( rc == 0 );
697  }
698}
699
700/*
701 * Try to find all sub-directories from an array
702 * in a given start directory.
703 * In addition try to find and open files
704 * in these sub-directories.
705 */
706static void test_finding_directories(
707  const char        *start_dir,
708  const char        *directory_names,
709  const unsigned int number_of_directories,
710  const char        *file_names,
711  const unsigned int number_of_files )
712{
713  unsigned int   index_directory;
714  int            rc;
715  DIR           *dir_stream;
716  struct dirent *dp;
717  char           dirname[MAX_NAME_LENGTH * 2];
718
719
720  dir_stream = opendir( start_dir );
721  rtems_test_assert( dir_stream != NULL );
722
723  dp = readdir( dir_stream );
724  rtems_test_assert( dp != NULL );
725  rtems_test_assert( 0 == strcmp( ".", dp->d_name ) );
726
727  dp = readdir( dir_stream );
728  rtems_test_assert( dp != NULL );
729  rtems_test_assert( 0 == strcmp( "..", dp->d_name ) );
730
731  dp              = readdir( dir_stream );
732  rtems_test_assert( dp != NULL );
733  index_directory = 0;
734
735  while ( dp != NULL ) {
736    rtems_test_assert( 0 == strcmp(
737                         directory_names + index_directory * MAX_NAME_LENGTH,
738                         dp->d_name ) );
739
740    snprintf(
741      dirname,
742      sizeof( dirname ) - 1,
743      "%s/%s",
744      start_dir,
745      directory_names + index_directory * MAX_NAME_LENGTH );
746
747    test_finding_files(
748      dirname,
749      file_names,
750      number_of_files );
751
752    ++index_directory;
753    dp = readdir( dir_stream );
754  }
755
756  rtems_test_assert( number_of_directories == index_directory );
757
758  rc = closedir( dir_stream );
759  rtems_test_assert( rc == 0 );
760}
761
762#if (PRINT_DISK_IMAGE != 0)
763static void print_image(
764  const char* include_guard,
765  const char* image_name
766)
767{
768  #define                   BYTES_PER_ROW     8
769  int                       rc;
770  int                       fd;
771  ssize_t                   bytes_read;
772  uint8_t                   buf[BLOCK_SIZE];
773  unsigned int              index_block;
774  unsigned int              index_row;
775  unsigned int              index_column;
776  unsigned int              index_buf;
777#ifdef SHOW_LINE_NUMBERS
778  size_t                    index_row_start = 1;
779#endif /* SWOW_LINE_NUMBERS */
780  size_t                    bytes_written   = 0;
781  const size_t              DISK_SIZE       = BLOCK_SIZE * BLOCK_NUM;
782  const unsigned int        ROWS_PER_BLOCK  = BLOCK_SIZE / BYTES_PER_ROW;
783
784  printf ("/*\n"
785          " *  Declarations for C structure representing a disk image\n"
786          " *\n"
787          " *  WARNING: Automatically generated by init.c -- do not edit!\n"
788          " */\n"
789          "#ifndef %s\n"
790          "#define %s\n"
791          "\n"
792          "#include <sys/types.h>\n"
793          "\n"
794          "#ifdef __cplusplus\n"
795          "extern \"C\" {\n"
796          "#endif /* __cplusplus */\n"
797          "\n"
798          "static unsigned char %s[] = {\n",
799          include_guard,
800          include_guard,
801          image_name);
802  fd = open( RAMDISK_PATH, O_RDWR );
803  rtems_test_assert( fd >= 0 );
804
805  for ( index_block = 0; index_block < BLOCK_NUM; ++index_block )
806  {
807    bytes_read = read( fd, &buf[0], BLOCK_SIZE );
808    rtems_test_assert( bytes_read = BLOCK_SIZE );
809
810    index_buf = 0;
811
812    for ( index_row = 0; index_row < ROWS_PER_BLOCK; ++index_row )
813    {
814      printf( "  " );
815      for ( index_column = 0;
816            index_column < BYTES_PER_ROW;
817            ++index_column ) {
818        printf("0x%02x", buf[index_buf]);
819        ++bytes_written;
820        ++index_buf;
821        if ( bytes_written < DISK_SIZE ) {
822          printf (", ");
823        } else {
824          printf ("  ");
825        }
826      }
827#ifdef SHOW_LINE_NUMBERS
828      printf( "/* %6u - %6u */", index_row_start, bytes_written );
829      index_row_start = bytes_written + 1;
830#endif /* SWOW_LINE_NUMBERS */
831      printf( "\n" );
832    }
833  }
834
835  rc = close( fd );
836  rtems_test_assert( rc == 0 );
837
838  printf ("};\n"
839          "#ifdef __cplusplus\n"
840          "}\n"
841          "#endif /* __cplusplus */\n"
842          "\n"
843          "#endif /* %s */\n",
844          include_guard);
845}
846#else /* PRINT_DISK_IMAGE */
847static void print_image(
848  const char* include_guard,
849  const char* image_name
850)
851{
852  /* Nothing to be done */
853}
854#endif /* PRINT_DISK_IMAGE */
855
856
857static void compare_files(
858  const char *file0,
859  const char *file1
860)
861{
862  struct stat  stat_buf[2];
863  int          fd[2];
864  unsigned int index;
865  uint8_t      buf[2];
866  ssize_t      bytes_read;
867  int          rc;
868
869  rc = stat( file0 , &stat_buf[0] );
870  rtems_test_assert( rc == 0 );
871  rc = stat( file1 , &stat_buf[1] );
872  rtems_test_assert( rc == 0 );
873
874  rtems_test_assert( stat_buf[0].st_size == stat_buf[1].st_size );
875
876  fd[0] = open( file0, O_RDONLY );
877  rtems_test_assert( fd[0] > 0 );
878  fd[1] = open( file1, O_RDONLY );
879  rtems_test_assert( fd[1] > 0 );
880
881  for ( index = 0; index < stat_buf[0].st_size; ++index ) {
882    bytes_read = read( fd[0], &buf[0], 1 );
883    rtems_test_assert( bytes_read == 1 );
884    bytes_read = read( fd[1], &buf[1], 1 );
885    rtems_test_assert( bytes_read == 1 );
886    rtems_test_assert( buf[0] == buf[1] );
887  }
888  rc = close( fd[0] );
889  rtems_test_assert( rc == 0 );
890  rc = close( fd[1] );
891  rtems_test_assert( rc == 0 );
892}
893
894static void compare_directories(
895  const char *dir0,
896  const char *dir1)
897{
898  int                       rc;
899  DIR                      *dir_stream[2];
900  struct dirent            *dp;
901  struct stat               stat_buf[2];
902  char                     *path[2];
903  const unsigned int        PATH_LENGTH = 1024;
904
905  path[0] = calloc( PATH_LENGTH, sizeof(char) );
906  rtems_test_assert( path[0] != NULL );
907  path[1] = calloc( PATH_LENGTH, sizeof(char) );
908  rtems_test_assert( path[1] != NULL );
909
910  dir_stream[0] = opendir( dir0 );
911  rtems_test_assert( dir_stream[0] != NULL );
912
913  dir_stream[1] = opendir( dir1 );
914  rtems_test_assert( dir_stream[1] != NULL );
915
916  dp = readdir( dir_stream[0] );
917  rtems_test_assert( dp != NULL );
918
919  while ( dp != NULL ) {
920    rc = snprintf(path[0], PATH_LENGTH, "%s/%s", dir0, dp->d_name);
921    rtems_test_assert( rc < PATH_LENGTH );
922    rtems_test_assert( rc >= 0 );
923    rc = snprintf(path[1], PATH_LENGTH, "%s/%s", dir1, dp->d_name);
924    rtems_test_assert( rc < PATH_LENGTH );
925    rtems_test_assert( rc >= 0 );
926
927    rc = stat( path[0] , &stat_buf[0] );
928    rtems_test_assert( rc == 0 );
929
930    if (   ( strcmp( dp->d_name, "."  ) != 0)
931        && ( strcmp( dp->d_name, ".." ) != 0) ) {
932      if ( S_ISDIR( stat_buf[0].st_mode ) ) {
933        compare_directories( path[0], path[1] );
934      } else {
935        compare_files( path[0], path[1] );
936      }
937    }
938
939    dp = readdir( dir_stream[0] );
940
941  }
942  rc = closedir( dir_stream[0] );
943  rtems_test_assert( rc == 0 );
944
945  rc = closedir( dir_stream[1] );
946  rtems_test_assert( rc == 0 );
947
948  free (path[0]);
949  free (path[1]);
950}
951
952static void compare_image(
953  const char                      *mount_dir,
954  const char                      *dev,
955  const rtems_dosfs_mount_options *mount_opts )
956{
957  #define MOUNT_DIR2 "/mnt2"
958  int                       rc;
959
960  rc = mount_and_make_target_path(
961    dev,
962    MOUNT_DIR2,
963    RTEMS_FILESYSTEM_TYPE_DOSFS,
964    RTEMS_FILESYSTEM_READ_WRITE,
965    mount_opts );
966  rtems_test_assert( rc == 0 );
967
968  compare_directories(mount_dir, MOUNT_DIR2);
969
970  rc = unmount( MOUNT_DIR2 );
971  rtems_test_assert( rc == 0 );
972
973  rc = rmdir( MOUNT_DIR2 );
974  rtems_test_assert( rc == 0 );
975
976}
977/*
978 * Test the compatibility with a genuine MS Windows FAT file system.
979 */
980static void test_compatibility( void )
981{
982  int                       rc;
983  rtems_status_code         sc;
984  dev_t                     dev;
985  char                      diskpath[] = "/dev/ramdisk1";
986  rtems_dosfs_mount_options mount_opts;
987  rtems_device_major_number major;
988  FILE                     *fp;
989  int                       buffer;
990  unsigned int              index_file = 0;
991  unsigned int              index_char;
992  unsigned int              offset;
993  char                      content_buf[MAX_NAME_LENGTH + strlen( MOUNT_DIR )
994                                        + 1];
995  char                      file_path[MAX_NAME_LENGTH + strlen( MOUNT_DIR )
996                                      + 1];
997  DIR                      *dir_stream;
998  struct dirent            *dp;
999
1000
1001  mount_opts.converter = rtems_dosfs_create_utf8_converter( "CP850" );
1002  rtems_test_assert( mount_opts.converter != NULL );
1003
1004  sc = rtems_io_register_driver( 0, &ramdisk_ops, &major );
1005  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
1006
1007  dev = rtems_filesystem_make_dev_t( major, 1 );
1008
1009  sc  = rtems_disk_create_phys(
1010    dev,
1011    BLOCK_SIZE,
1012    BLOCK_COUNT,
1013    ramdisk_ioctl,
1014    &disk_image,
1015    diskpath );
1016  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
1017
1018  rc = mount_and_make_target_path(
1019    diskpath,
1020    MOUNT_DIR,
1021    RTEMS_FILESYSTEM_TYPE_DOSFS,
1022    RTEMS_FILESYSTEM_READ_WRITE,
1023    &mount_opts );
1024  rtems_test_assert( rc == 0 );
1025
1026  dir_stream = opendir( MOUNT_DIR );
1027  rtems_test_assert( dir_stream != NULL );
1028
1029  dp = readdir( dir_stream );
1030  rtems_test_assert( dp != NULL );
1031
1032  while ( dp != NULL ) {
1033    index_char = 0;
1034
1035    size_t len = strlen( filenames[index_file] );
1036
1037    if ( filenames[index_file][len - 1] == '.' )
1038      rtems_test_assert( ( len - 1 ) == dp->d_namlen );
1039    else
1040      rtems_test_assert( len == dp->d_namlen );
1041
1042    rtems_test_assert( 0
1043                       == memcmp( &filenames[index_file][0], &dp->d_name[0],
1044                                  dp->d_namlen ) );
1045
1046    snprintf( file_path, sizeof( file_path ), "%s/%s", MOUNT_DIR,
1047              filenames[index_file] );
1048    fp = fopen( file_path, "r" );
1049    rtems_test_assert( fp != NULL );
1050
1051    /* These files should contain their own file names. */
1052    while ( ( buffer = fgetc( fp ) ) != EOF ) {
1053      content_buf[index_char] = buffer;
1054      ++index_char;
1055    }
1056
1057    if ( 0 == strncmp( content_buf, UTF8_BOM, UTF8_BOM_SIZE ) )
1058      offset = UTF8_BOM_SIZE;
1059    else
1060      offset = 0;
1061
1062    rtems_test_assert( 0
1063                       == memcmp( filenames[index_file],
1064                                  &content_buf[offset],
1065                                  index_char - offset ) );
1066
1067    rc = fclose( fp );
1068    rtems_test_assert( rc == 0 );
1069
1070    ++index_file;
1071    dp = readdir( dir_stream );
1072  }
1073
1074  rtems_test_assert( index_file == FILES_FILENAMES_NUMBER_OF );
1075
1076  rc = closedir( dir_stream );
1077  rtems_test_assert( rc == 0 );
1078
1079  rc = unmount( MOUNT_DIR );
1080  rtems_test_assert( rc == 0 );
1081}
1082
1083static void test_end_of_string_matches( void )
1084{
1085  int rc;
1086
1087  rc = mkdir( MOUNT_DIR "/lib.beam", S_IRWXU | S_IRWXG | S_IRWXO );
1088  rtems_test_assert( rc == 0 );
1089
1090  errno = 0;
1091  rc = unlink( MOUNT_DIR "/proc_lib.beam" );
1092  rtems_test_assert( rc == -1 );
1093  rtems_test_assert( errno == ENOENT );
1094
1095  rc = unlink( MOUNT_DIR "/lib.beam" );
1096  rtems_test_assert( rc == 0 );
1097}
1098
1099static void test_full_8_3_name( void )
1100{
1101  int rc;
1102
1103  rc = mkdir( MOUNT_DIR "/txtvsbin.txt", S_IRWXU | S_IRWXG | S_IRWXO );
1104  rtems_test_assert( rc == 0 );
1105
1106  rc = unlink( MOUNT_DIR "/txtvsbin.txt" );
1107  rtems_test_assert( rc == 0 );
1108}
1109
1110static void test_special_cases( void )
1111{
1112  test_end_of_string_matches();
1113  test_full_8_3_name();
1114}
1115
1116/*
1117 * Main test method
1118 */
1119static void test( void )
1120{
1121  int  rc;
1122  char start_dir[MOUNT_DIR_SIZE + START_DIR_SIZE + 2];
1123  rtems_dosfs_mount_options mount_opts[2];
1124
1125  rc = mkdir( MOUNT_DIR, S_IRWXU | S_IRWXG | S_IRWXO );
1126  rtems_test_assert( rc == 0 );
1127
1128  snprintf( start_dir, sizeof( start_dir ), "%s/%s", MOUNT_DIR, "strt" );
1129
1130  /*
1131   * Tests with code page 850 compatible directory and file names
1132   * and the code page 850 backwards compatible default mode mode of the
1133   * FAT file system
1134   */
1135  mount_device_with_defaults( start_dir );
1136
1137  test_creating_duplicate_directories(
1138    &start_dir[0],
1139    &DIRECTORY_DUPLICATES[0],
1140    NUMBER_OF_DIRECTORIES_DUPLICATED );
1141
1142  unmount_and_close_device();
1143
1144  mount_device_with_defaults( start_dir );
1145
1146  test_duplicated_files(
1147    MOUNT_DIR,
1148    FILES_DUPLICATES,
1149    NUMBER_OF_FILES_DUPLICATED );
1150
1151  unmount_and_close_device();
1152
1153  mount_device_with_defaults( start_dir );
1154
1155  test_creating_invalid_directories();
1156
1157  test_creating_directories(
1158    &start_dir[0],
1159    &DIRECTORY_NAMES[0][0],
1160    NUMBER_OF_DIRECTORIES );
1161
1162  test_handling_directories(
1163    &start_dir[0],
1164    &DIRECTORY_NAMES[0][0],
1165    NUMBER_OF_DIRECTORIES,
1166    &FILE_NAMES[0][0],
1167    NUMBER_OF_FILES );
1168
1169  compare_image(
1170    MOUNT_DIR,
1171    "/dev/rdb",
1172    NULL);
1173
1174  test_special_cases();
1175
1176  rc = unmount( MOUNT_DIR );
1177  rtems_test_assert( rc == 0 );
1178
1179  /*
1180   * Again tests with code page 850 compatible directory and file names
1181   * but with multibyte string compatible conversion methods which use
1182   * iconv and utf8proc
1183   */
1184  mount_opts[0].converter = rtems_dosfs_create_utf8_converter( "CP850" );
1185  rtems_test_assert( mount_opts[0].converter != NULL );
1186
1187  rc                     = mount(
1188    RAMDISK_PATH,
1189    MOUNT_DIR,
1190    "dosfs",
1191    RTEMS_FILESYSTEM_READ_WRITE,
1192    &mount_opts );
1193  rtems_test_assert( rc == 0 );
1194
1195  test_finding_directories(
1196    &start_dir[0],
1197    &DIRECTORY_NAMES[0][0],
1198    NUMBER_OF_DIRECTORIES,
1199    &FILE_NAMES[0][0],
1200    NUMBER_OF_FILES );
1201  unmount_and_close_device();
1202
1203  mount_device_with_iconv( start_dir, &mount_opts[0] );
1204  test_creating_invalid_directories();
1205
1206  test_creating_duplicate_directories(
1207    &start_dir[0],
1208    &DIRECTORY_DUPLICATES[0],
1209    NUMBER_OF_DIRECTORIES_DUPLICATED );
1210
1211  unmount_and_close_device();
1212
1213  mount_device_with_iconv( start_dir, &mount_opts[0] );
1214
1215  test_duplicated_files(
1216    MOUNT_DIR,
1217    FILES_DUPLICATES,
1218    NUMBER_OF_FILES_DUPLICATED );
1219
1220  unmount_and_close_device();
1221
1222  mount_device_with_iconv( start_dir, &mount_opts[0] );
1223
1224  test_creating_directories(
1225    &start_dir[0],
1226    &DIRECTORY_NAMES[0][0],
1227    NUMBER_OF_DIRECTORIES );
1228
1229  test_handling_directories(
1230    &start_dir[0],
1231    &DIRECTORY_NAMES[0][0],
1232    NUMBER_OF_DIRECTORIES,
1233    &FILE_NAMES[0][0],
1234    NUMBER_OF_FILES );
1235
1236  mount_opts[1].converter = rtems_dosfs_create_utf8_converter( "CP850" );
1237  rtems_test_assert( mount_opts[1].converter != NULL );
1238
1239  compare_image(
1240    MOUNT_DIR,
1241    "/dev/rdb",
1242    &mount_opts[1]);
1243
1244  test_special_cases();
1245
1246  rc = unmount( MOUNT_DIR );
1247  rtems_test_assert( rc == 0 );
1248
1249  print_image(
1250      "IMAGE_BIN_LE_SINGLEBYTE_H_",
1251      "IMAGE_BIN_LE_SINGLEBYTE");
1252
1253  rc = mount(
1254    RAMDISK_PATH,
1255    MOUNT_DIR,
1256    "dosfs",
1257    RTEMS_FILESYSTEM_READ_WRITE,
1258    NULL );
1259  rtems_test_assert( rc == 0 );
1260
1261  unmount_and_close_device();
1262
1263
1264  /*
1265   * Tests with multibyte directory and file names and
1266   * with multibyte string compatible conversion methods which use
1267   * iconv and utf8proc
1268   */
1269  mount_device_with_iconv( start_dir, &mount_opts[0] );
1270
1271  test_creating_duplicate_directories(
1272    &start_dir[0],
1273    &MULTIBYTE_DUPLICATES[0],
1274    NUMBER_OF_MULTIBYTE_NAMES_DUPLICATED );
1275
1276  unmount_and_close_device();
1277
1278  mount_device_with_iconv( start_dir, &mount_opts[0] );
1279
1280  test_duplicated_files(
1281    MOUNT_DIR,
1282    &MULTIBYTE_DUPLICATES[0],
1283    NUMBER_OF_MULTIBYTE_NAMES_DUPLICATED );
1284
1285  unmount_and_close_device();
1286
1287  mount_device_with_iconv( start_dir, &mount_opts[0] );
1288
1289  test_creating_directories(
1290    &start_dir[0],
1291    &NAMES_MULTIBYTE[0][0],
1292    NUMBER_OF_NAMES_MULTIBYTE );
1293
1294  test_handling_directories(
1295    &start_dir[0],
1296    &NAMES_MULTIBYTE[0][0],
1297    NUMBER_OF_NAMES_MULTIBYTE,
1298    &NAMES_MULTIBYTE[0][0],
1299    NUMBER_OF_NAMES_MULTIBYTE );
1300
1301  mount_opts[1].converter = rtems_dosfs_create_utf8_converter( "CP850" );
1302  rtems_test_assert( mount_opts[1].converter != NULL );
1303
1304  compare_image(
1305    MOUNT_DIR,
1306    "/dev/rdc",
1307    &mount_opts[1]);
1308
1309  test_special_cases();
1310
1311  rc = unmount( MOUNT_DIR );
1312  rtems_test_assert( rc == 0 );
1313
1314  print_image(
1315    "IMAGE_BIN_LE_MULTIBYTE_H_",
1316    "IMAGE_BIN_LE_MULTIBYTE");
1317
1318  rc = mount(
1319    RAMDISK_PATH,
1320    MOUNT_DIR,
1321    "dosfs",
1322    RTEMS_FILESYSTEM_READ_WRITE,
1323    NULL );
1324  rtems_test_assert( rc == 0 );
1325
1326  test_finding_directories(
1327    &start_dir[0],
1328    &NAMES_MULTIBYTE_IN_CODEPAGE_FORMAT[0][0],
1329    NUMBER_OF_NAMES_MULTIBYTE,
1330    &NAMES_MULTIBYTE_IN_CODEPAGE_FORMAT[0][0],
1331    NUMBER_OF_NAMES_MULTIBYTE );
1332
1333  unmount_and_close_device();
1334
1335  test_compatibility();
1336}
1337
1338static void Init( rtems_task_argument arg )
1339{
1340  TEST_BEGIN();
1341
1342  test();
1343
1344  TEST_END();
1345  rtems_test_exit( 0 );
1346}
1347
1348rtems_ramdisk_config rtems_ramdisk_configuration [] = {
1349  { .block_size = BLOCK_SIZE, .block_num = BLOCK_NUM },
1350  { .block_size = BLOCK_SIZE, .block_num = BLOCK_NUM, .location = &IMAGE_BIN_LE_SINGLEBYTE[0] },
1351  { .block_size = BLOCK_SIZE, .block_num = BLOCK_NUM, .location = &IMAGE_BIN_LE_MULTIBYTE[0] }
1352};
1353
1354size_t rtems_ramdisk_configuration_size = RTEMS_ARRAY_SIZE(rtems_ramdisk_configuration);
1355
1356#define CONFIGURE_INIT_TASK_STACK_SIZE ( 1024 * 64 )
1357#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
1358#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
1359#define CONFIGURE_MAXIMUM_DRIVERS 4
1360#define CONFIGURE_MAXIMUM_SEMAPHORES (2 * RTEMS_DOSFS_SEMAPHORES_PER_INSTANCE)
1361#define CONFIGURE_APPLICATION_EXTRA_DRIVERS RAMDISK_DRIVER_TABLE_ENTRY
1362
1363#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
1364
1365#define CONFIGURE_FILESYSTEM_DOSFS
1366
1367/* 2 RAM disk device files + 2 mount_dir + stdin + stdout + stderr +
1368 * 2 for open directories/files  + 4 * 2 for recursive tree compares*/
1369#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS ( 7 + 2 + ( 4 * 2 ) )
1370
1371#define CONFIGURE_MAXIMUM_TASKS 1
1372
1373#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
1374
1375#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
1376
1377#define CONFIGURE_INIT
1378
1379#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.