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

Last change on this file since d9c65429 was d9c65429, checked in by Sebastian Huber <sebastian.huber@…>, on Feb 13, 2017 at 2:13:02 PM

dosfs: Fix msdos_find_file_in_directory()

For a filename match the entry must match without anything remaining.

Close #2908.

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