source: rtems/testsuites/samples/fileio/init.c

Last change on this file was e71f0909, checked in by Joel Sherrill <joel@…>, on 04/07/22 at 16:13:34

testsuites/samples: Change license to BSD-2

Updates #3053.

  • Property mode set to 100644
File size: 29.1 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/*
4 *  COPYRIGHT (c) 1989-2012.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#define CONFIGURE_INIT
34#include "system.h"
35#include <sys/param.h>
36#include <crypt.h>
37#include <stdio.h>
38#include <string.h>
39#include <unistd.h>
40#include <stdlib.h>
41#include <errno.h>
42#include <rtems.h>
43#include <fcntl.h>
44#include <inttypes.h>
45#include <rtems/error.h>
46#include <rtems/dosfs.h>
47#include <ctype.h>
48#include <rtems/bdpart.h>
49#include <rtems/libcsupport.h>
50#include <rtems/fsmount.h>
51#include <rtems/ramdisk.h>
52#include <rtems/nvdisk.h>
53#include <rtems/nvdisk-sram.h>
54#include <rtems/shell.h>
55
56const char rtems_test_name[] = "FILE I/O";
57
58#if FILEIO_BUILD
59
60/**
61 * Let the IO system allocation the next available major number.
62 */
63#define RTEMS_DRIVER_AUTO_MAJOR (0)
64
65/**
66 * The NV Device descriptor. For this test it is just DRAM.
67 */
68rtems_nvdisk_device_desc rtems_nv_heap_device_descriptor[] =
69{
70  {
71    flags:  0,
72    base:   0,
73    size:   (size_t) 1024 * 1024,
74    nv_ops: &rtems_nvdisk_sram_handlers
75  }
76};
77
78/**
79 * The NV Disk configuration.
80 */
81const rtems_nvdisk_config rtems_nvdisk_configuration[] =
82{
83  {
84    block_size:         512,
85    device_count:       1,
86    devices:            &rtems_nv_heap_device_descriptor[0],
87    flags:              0,
88    info_level:         0
89  }
90};
91
92/**
93 * The number of NV Disk configurations.
94 */
95uint32_t rtems_nvdisk_configuration_size = 1;
96
97/*
98 * Table of FAT file systems that will be mounted
99 * with the "fsmount" function.
100 * See cpukit/libmisc/fsmount for definition of fields
101 */
102fstab_t fs_table[] = {
103  {
104    "/dev/hda1","/mnt/hda1", "dosfs",
105    RTEMS_FILESYSTEM_READ_WRITE,
106    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
107    0
108  },
109  {
110    "/dev/hda2","/mnt/hda2", "dosfs",
111    RTEMS_FILESYSTEM_READ_WRITE,
112    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
113    0
114  },
115  {
116    "/dev/hda3","/mnt/hda3", "dosfs",
117    RTEMS_FILESYSTEM_READ_WRITE,
118    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
119    0
120  },
121  {
122    "/dev/hda4","/mnt/hda4", "dosfs",
123    RTEMS_FILESYSTEM_READ_WRITE,
124    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
125    0
126  },
127  {
128    "/dev/hdc1","/mnt/hdc1", "dosfs",
129    RTEMS_FILESYSTEM_READ_WRITE,
130    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
131    0
132  },
133  {
134    "/dev/hdc2","/mnt/hdc2", "dosfs",
135    RTEMS_FILESYSTEM_READ_WRITE,
136    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
137    0
138  },
139  {
140    "/dev/hdc3","/mnt/hdc3", "dosfs",
141    RTEMS_FILESYSTEM_READ_WRITE,
142    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
143    0
144  },
145  {
146    "/dev/hdc4","/mnt/hdc4", "dosfs",
147    RTEMS_FILESYSTEM_READ_WRITE,
148    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
149    0
150  }
151};
152
153#define USE_SHELL
154
155#ifdef USE_SHELL
156
157static int
158shell_nvdisk_trace (int argc, char* argv[])
159{
160  const char* driver;
161  int         level;
162
163  if (argc != 3)
164  {
165    printf ("error: invalid number of options\n");
166    return 1;
167  }
168
169  driver = argv[1];
170  level  = strtoul (argv[2], 0, 0);
171 
172  int fd = open (driver, O_WRONLY, 0);
173  if (fd < 0)
174  {
175    printf ("error: driver open failed: %s\n", strerror (errno));
176    return 1;
177  }
178 
179  if (ioctl (fd, RTEMS_NVDISK_IOCTL_INFO_LEVEL, level) < 0)
180  {
181    printf ("error: driver set level failed: %s\n", strerror (errno));
182    return 1;
183  }
184 
185  close (fd);
186 
187  return 0;
188}
189
190static int
191shell_nvdisk_erase (int argc, char* argv[])
192{
193  const char* driver = NULL;
194  int         arg;
195  int         fd;
196 
197  for (arg = 1; arg < argc; arg++)
198  {
199    if (argv[arg][0] == '-')
200    {
201      printf ("error: invalid option: %s\n", argv[arg]);
202      return 1;
203    }
204    else
205    {
206      if (!driver)
207        driver = argv[arg];
208      else
209      {
210        printf ("error: only one driver name allowed: %s\n", argv[arg]);
211        return 1;
212      }
213    }
214  }
215 
216  printf ("erase nv disk: %s\n", driver);
217 
218  fd = open (driver, O_WRONLY, 0);
219  if (fd < 0)
220  {
221    printf ("error: nvdisk driver open failed: %s\n", strerror (errno));
222    return 1;
223  }
224 
225  if (ioctl (fd, RTEMS_NVDISK_IOCTL_ERASE_DISK) < 0)
226  {
227    printf ("error: nvdisk driver erase failed: %s\n", strerror (errno));
228    return 1;
229  }
230 
231  close (fd);
232 
233  printf ("nvdisk erased successful\n");
234
235  return 0;
236}
237
238static int
239shell_bdbuf_trace (int argc, char* argv[])
240{
241#if RTEMS_BDBUF_TRACE
242  extern bool rtems_bdbuf_tracer;
243  rtems_bdbuf_tracer = !rtems_bdbuf_tracer;
244  printf ("bdbuf trace: %d\n", rtems_bdbuf_tracer);
245#else
246  printf ("bdbuf trace disabled. Rebuild with enabled.\n");
247#endif
248  return 0;
249}
250
251static int
252disk_test_set_block_size (rtems_disk_device *dd, size_t size)
253{
254  return dd->ioctl (dd, RTEMS_BLKIO_SETBLKSIZE, &size);
255}
256
257static int
258disk_test_write_blocks (const char *name, int start, int count, size_t size)
259{
260  int                 block;
261  uint32_t*           ip;
262  uint32_t            value = 0;
263  int                 i;
264  rtems_bdbuf_buffer* bd;
265  rtems_status_code   sc;
266  int                 rv = 0;
267  rtems_disk_device*  dd;
268  int                 fd;
269
270  fd = open(name, O_RDWR);
271  if (fd < 0) {
272    printf ("error: cannot open disk\n");
273    rv = 1;
274  }
275
276  if (rv == 0 && rtems_disk_fd_get_disk_device(fd, &dd) != 0)
277  {
278    printf ("error: cannot obtain disk\n");
279    rv = 1;
280  }
281
282  if (fd >= 0 && close (fd) != 0)
283  {
284    printf ("error: close disk failed\n");
285    rv = 1;
286  }
287
288  if (rv == 0 && disk_test_set_block_size (dd, size) < 0)
289  {
290    printf ("error: set block size failed: %s\n", strerror (errno));
291    rv = 1;
292  }
293
294  for (block = start; rv == 0 && block < (start + count); block++)
295  {
296    sc = rtems_bdbuf_read (dd, block, &bd);
297    if (sc == RTEMS_SUCCESSFUL)
298    {
299      ip = (uint32_t*) bd->buffer;
300      for (i = 0; i < (size / sizeof (uint32_t)); i++, ip++, value++)
301        *ip = (size << 16) | value;
302
303      sc = rtems_bdbuf_release_modified (bd);
304      if (sc != RTEMS_SUCCESSFUL)
305      {
306        printf ("error: release block %d bd failed: %s\n",
307                block, rtems_status_text (sc));
308        rv = 1;
309      }
310    }
311    else
312    {
313      printf ("error: get block %d bd failed: %s\n",
314              block, rtems_status_text (sc));
315      rv = 1;
316    }
317  }
318
319  return rv;
320}
321
322static int
323disk_test_block_sizes (int argc, char *argv[])
324{
325  char* name;
326  int   start;
327  int   count;
328  int   size;
329
330  if (argc != (4 + 1))
331  {
332    printf ("error: need to supply a device path, start, block and size\n");
333    return 1;
334  }
335
336  name = argv[1];
337
338  start = strtoul (argv[2], 0, 0);
339  count = strtoul (argv[3], 0, 0);
340  size  = strtoul (argv[4], 0, 0);
341
342  return disk_test_write_blocks (name, start, count, size);
343}
344
345static uint32_t
346parse_size_arg (const char* arg)
347{
348  uint32_t size;
349  uint32_t scalar = 1;
350
351  size = strtoul (arg, 0, 0);
352  switch (arg[strlen (arg) - 1])
353  {
354    case 'b':
355      scalar = 1;
356      break;
357    case 'M':
358      scalar = 1024000;
359      break;
360    case 'm':
361      scalar = 1000000;
362      break;
363    case 'K':
364      scalar = 1024;
365      break;
366    case 'k':
367      scalar = 1000;
368      break;
369    default:
370      printf ("error: invalid scalar (b,M/m/K/k): %c\n", arg[strlen (arg) - 1]);
371      return 0;
372  }
373  return size * scalar;
374}
375
376static int
377create_ramdisk (int argc, char *argv[])
378{
379  rtems_status_code         sc;
380  int                       arg;
381  uint32_t                  size = 524288;
382  uint32_t                  block_size = 512;
383  uint32_t                  block_count;
384
385  for (arg = 0; arg < argc; ++arg)
386  {
387    if (argv[arg][0] == '-')
388    {
389      switch (argv[arg][1])
390      {
391        case 's':
392          ++arg;
393          if (arg == argc)
394          {
395            printf ("error: -s needs a size\n");
396            return 1;
397          }
398          size = parse_size_arg (argv[arg]);
399          if (size == 0)
400            return 1;
401          break;
402        case 'b':
403          ++arg;
404          if (arg == argc)
405          {
406            printf ("error: -b needs a size\n");
407            return 1;
408          }
409          block_size = parse_size_arg (argv[arg]);
410          if (size == 0)
411            return 1;
412          break;
413        default:
414          printf ("error: invalid option: %s\n", argv[arg]);
415          return 1;
416      }
417    }
418  }
419
420  block_count = size / block_size;
421
422  /*
423   * Register the RAM Disk driver.
424   */
425  printf ("Register RAM Disk Driver [blocks=%" PRIu32 \
426          " block-size=%" PRIu32 "]:",
427          block_count,
428          block_size);
429
430  sc = ramdisk_register(block_size, block_count, false, "/dev/rda");
431  if (sc != RTEMS_SUCCESSFUL)
432  {
433    printf ("error: ramdisk driver not initialised: %s\n",
434            rtems_status_text (sc));
435    return 1;
436  }
437
438  printf ("successful\n");
439
440  return 0;
441}
442
443static int
444create_nvdisk (int argc, char *argv[])
445{
446  rtems_status_code         sc;
447  int                       arg;
448  uint32_t                  size = 0;
449#if ADD_WHEN_NVDISK_HAS_CHANGED
450  uint32_t                  block_size = 0;
451#endif
452 
453  for (arg = 0; arg < argc; ++arg)
454  {
455    if (argv[arg][0] == '-')
456    {
457      switch (argv[arg][1])
458      {
459        case 's':
460          ++arg;
461          if (arg == argc)
462          {
463            printf ("error: -s needs a size\n");
464            return 1;
465          }
466          size = parse_size_arg (argv[arg]);
467          if (size == 0)
468            return 1;
469          break;
470#if ADD_WHEN_NVDISK_HAS_CHANGED
471        case 'b':
472          ++arg;
473          if (arg == argc)
474          {
475            printf ("error: -b needs a size\n");
476            return 1;
477          }
478          block_size = parse_size_arg (argv[arg]);
479          if (size == 0)
480            return 1;
481          break;
482#endif
483        default:
484          printf ("error: invalid option: %s\n", argv[arg]);
485          return 1;
486      }
487    }
488  }
489
490#if ADD_WHEN_NVDISK_HAS_CHANGED
491  if (block_size)
492    rtems_nvdisk_configuration[0].block_size = block_size;
493#endif
494  if (size)
495    rtems_nv_heap_device_descriptor[0].size = size;
496   
497  /*
498   * For our test we do not have any static RAM or EEPROM devices so
499   * we allocate the memory from the heap.
500   */
501  rtems_nv_heap_device_descriptor[0].base =
502    malloc (rtems_nv_heap_device_descriptor[0].size);
503
504  if (!rtems_nv_heap_device_descriptor[0].base)
505  {
506    printf ("error: no memory for NV disk\n");
507    return 1;
508  }
509 
510  /*
511   * Register the RAM Disk driver.
512   */
513  printf ("Register NV Disk Driver [size=%" PRIu32 \
514          " block-size=%" PRIu32"]:",
515          rtems_nv_heap_device_descriptor[0].size,
516          rtems_nvdisk_configuration[0].block_size);
517
518  sc = rtems_nvdisk_initialize (0, 0, NULL);
519  if (sc != RTEMS_SUCCESSFUL)
520  {
521    printf ("error: nvdisk driver not initialised: %s\n",
522            rtems_status_text (sc));
523    return 1;
524  }
525 
526  printf ("successful\n");
527
528  return 0;
529}
530
531static void writeFile(
532  const char *name,
533  mode_t      mode,
534  const char *contents
535)
536{
537  int sc;
538  sc = setuid(0);
539  if ( sc ) {
540    printf( "setuid failed: %s: %s\n", name, strerror(errno) );
541  }
542
543  rtems_shell_write_file( name, contents );
544
545  sc = chmod ( name, mode );
546  if ( sc ) {
547    printf( "chmod %s: %s\n", name, strerror(errno) );
548  }
549}
550
551#define writeScript( _name, _contents ) \
552        writeFile( _name, 0777, _contents )
553
554static void fileio_start_shell(void)
555{
556  int sc;
557
558  sc = mkdir("/scripts", 0777);
559  if ( sc ) {
560    printf( "mkdir /scripts: %s:\n", strerror(errno) );
561  }
562
563  sc = mkdir("/etc", 0777);
564  if ( sc ) {
565    printf( "mkdir /etc: %s:\n", strerror(errno) );
566  }
567
568  sc = mkdir("/chroot", 0777);
569  if ( sc ) {
570    printf( "mkdir /chroot: %s:\n", strerror(errno) );
571  }
572
573  printf(
574    "Creating /etc/passwd and group with four useable accounts:\n"
575    "  root/pwd\n"
576    "  test/pwd\n"
577    "  rtems/NO PASSWORD\n"
578    "  chroot/NO PASSWORD\n"
579    "Only the root user has access to all available commands.\n"
580  );
581
582  writeFile(
583    "/etc/passwd",
584    0644,
585    "root:$6$$FuPOhnllx6lhW2qqlnmWvZQLJ8Thr/09I7ESTdb9VbnTOn5.65"
586      "/Vh2Mqa6FoKXwT0nHS/O7F0KfrDc6Svb/sH.:0:0:root::/:/bin/sh\n"
587    "rtems::1:1:RTEMS Application::/:/bin/sh\n"
588    "test:$1$$oPu1Xt2Pw0ngIc7LyDHqu1:2:2:test account::/:/bin/sh\n"
589    "tty:*:3:3:tty owner::/:/bin/false\n"
590    "chroot::4:2:chroot account::/chroot:/bin/sh\n"
591  );
592  writeFile(
593    "/etc/group",
594    0644,
595    "root:x:0:root\n"
596    "rtems:x:1:rtems\n"
597    "test:x:2:test\n"
598    "tty:x:3:tty\n"
599  );
600
601  writeScript(
602    "/scripts/js",
603    "#! joel\n"
604    "\n"
605    "date\n"
606    "echo Script successfully ran\n"
607    "date\n"
608    "stackuse\n"
609  );
610
611  writeScript(
612    "/scripts/j1",
613    "#! joel -s 20480 -t JESS\n"
614    "stackuse\n"
615  );
616
617  rtems_shell_write_file(
618    "/scripts/j2",
619    "echo j2 TEST FILE\n"
620    "echo j2   SHOULD BE non-executable AND\n"
621    "echo j2   DOES NOT have the magic first line\n"
622  );
623
624  rtems_shell_add_cmd ("mkrd", "files",
625                       "Create a RAM disk driver", create_ramdisk);
626  rtems_shell_add_cmd ("mknvd", "files",
627                       "Create a NV disk driver", create_nvdisk);
628  rtems_shell_add_cmd ("nverase", "misc",
629                       "nverase driver", shell_nvdisk_erase);
630  rtems_shell_add_cmd ("nvtrace", "misc",
631                       "nvtrace driver level", shell_nvdisk_trace);
632  rtems_shell_add_cmd ("bdbuftrace", "files",
633                       "bdbuf trace toggle", shell_bdbuf_trace);
634  rtems_shell_add_cmd ("td", "files",
635                       "Test disk", disk_test_block_sizes);
636#if RTEMS_RFS_TRACE
637  rtems_shell_add_cmd ("rfs", "files",
638                       "RFS trace",
639                       rtems_rfs_trace_shell_command);
640#endif
641#if RTEMS_RFS_RTEMS_TRACE
642  rtems_shell_add_cmd ("rrfs", "files",
643                       "RTEMS RFS trace",
644                       rtems_rfs_rtems_trace_shell_command);
645#endif
646
647  printf(" =========================\n");
648  printf(" starting shell\n");
649  printf(" =========================\n");
650  rtems_shell_init(
651    "SHLL",                          /* task_name */
652    RTEMS_MINIMUM_STACK_SIZE * 5,    /* task_stacksize */
653    100,                             /* task_priority */
654    "/dev/foobar",                   /* devname */
655    /* device is currently ignored by the shell if it is not a pty */
656    false,                           /* forever */
657    true,                            /* wait */
658    rtems_shell_login_check          /* login */
659  );
660}
661#endif /* USE_SHELL */
662
663static void fileio_print_free_heap(void)
664{
665  printf("--- unused dynamic memory: %lu bytes ---\n",
666         (unsigned long) malloc_free_space());
667}
668
669
670static void fileio_part_table_initialize(void)
671{
672  char devname[64];
673  rtems_status_code rc;
674
675  printf(" =========================\n");
676  printf(" Initialize partition table\n");
677  printf(" =========================\n");
678  fileio_print_free_heap();
679  printf(" Enter device to initialize ==>");
680  fflush(stdout);
681  fgets(devname,sizeof(devname)-1,stdin);
682  while (devname[strlen(devname)-1] == '\n') {
683    devname[strlen(devname)-1] = '\0';
684  }
685  /*
686   * call function
687   */
688  rc = rtems_bdpart_register_from_disk(devname);
689  printf("result = %d\n",rc);
690  fileio_print_free_heap();
691}
692
693static void fileio_fsmount(void)
694{
695  rtems_status_code rc;
696
697  printf(" =========================\n");
698  printf(" Process fsmount table\n");
699  printf(" =========================\n");
700  fileio_print_free_heap();
701  /*
702   * call function
703   */
704  rc = rtems_fsmount( fs_table,
705                      sizeof(fs_table)/sizeof(fs_table[0]),
706                      NULL);
707  printf("result = %d\n",rc);
708  fileio_print_free_heap();
709}
710
711static void fileio_list_file(void)
712{
713  char fname[1024];
714  char *buf_ptr = NULL;
715  ssize_t   flen = 0;
716  int fd = -1;
717  ssize_t n;
718  size_t buf_size = 100;
719
720  rtems_interval start_tick,curr_tick,ticks_per_sec;
721
722  printf(" =========================\n");
723  printf(" LIST FILE ...            \n");
724  printf(" =========================\n");
725  fileio_print_free_heap();
726  printf(" Enter filename to list ==>");
727  fflush(stdout);
728  fgets(fname,sizeof(fname)-1,stdin);
729  while (fname[strlen(fname)-1] == '\n') {
730    fname[strlen(fname)-1] = '\0';
731  }
732  /*
733   * allocate buffer of given size
734   */
735  if (buf_size > 0) {
736    buf_ptr = malloc(buf_size);
737  }
738
739  if (buf_ptr != NULL) {
740    printf("\n Trying to open file \"%s\" for read\n",fname);
741    fd = open(fname,O_RDONLY);
742    if (fd < 0) {
743      printf("*** file failed to open, errno = %d(%s)\n",errno,strerror(errno));
744    }
745  }
746
747  if (fd >= 0) {
748    start_tick = rtems_clock_get_ticks_since_boot();
749    do {
750      n = read(fd,buf_ptr,buf_size);
751      if (n > 0) {
752        write(1,buf_ptr,(size_t) n);
753        flen += n;
754      }
755    } while (n > 0);
756
757    curr_tick = rtems_clock_get_ticks_since_boot();
758
759    printf("\n ******** End of file reached, flen = %zd\n",flen);
760    close(fd);
761
762    ticks_per_sec = rtems_clock_get_ticks_per_second();
763    printf("time elapsed for read:  %g seconds\n",
764           ((double)curr_tick-start_tick)/ticks_per_sec);
765  }
766  /*
767   * free buffer
768   */
769  if (buf_ptr != NULL) {
770    free(buf_ptr);
771  }
772  fileio_print_free_heap();
773}
774
775/*
776 * convert a size string (like 34K or 12M) to actual byte count
777 */
778static bool fileio_str2size(const char *str,uint32_t   *res_ptr)
779{
780  bool failed = false;
781  unsigned long size;
782  unsigned char suffix = ' ';
783
784  if (1 > sscanf(str,"%lu%c",&size,&suffix)) {
785    failed = true;
786  }
787  else if (toupper((int)suffix) == 'K') {
788    size *= 1024;
789  }
790  else if (toupper((int)suffix) == 'M') {
791    size *= 1024UL*1024UL;
792  }
793  else if (isalpha((int)suffix)) {
794    failed = true;
795  }
796
797  if (!failed) {
798    *res_ptr = size;
799  }
800  return failed;
801}
802
803static void fileio_write_file(void)
804{
805  char fname[1024];
806  char tmp_str[32];
807  uint32_t   file_size = 0;
808  uint32_t   buf_size  = 0;
809  size_t curr_pos,bytes_to_copy;
810  int fd = -1;
811  ssize_t n;
812  rtems_interval start_tick,curr_tick,ticks_per_sec;
813  char *bufptr = NULL;
814  bool failed = false;
815  static const char write_test_string[] =
816    "The quick brown fox jumps over the lazy dog\n";
817  static const char write_block_string[] =
818    "\n----- end of write buffer ------\n";
819
820  printf(" =========================\n");
821  printf(" WRITE FILE ...           \n");
822  printf(" =========================\n");
823  fileio_print_free_heap();
824  /*
825   * get number of ticks per second
826   */
827  ticks_per_sec = rtems_clock_get_ticks_per_second();
828
829  /*
830   * get path to file to write
831   */
832  if (!failed) {
833    printf("Enter path/filename ==>");
834    fflush(stdout);
835    fgets(fname,sizeof(fname)-1,stdin);
836    while (fname[strlen(fname)-1] == '\n') {
837      fname[strlen(fname)-1] = '\0';
838    }
839    if (0 == strlen(fname)) {
840      printf("*** no filename entered, aborted\n");
841      failed = true;
842    }
843  }
844  /*
845   * get total file size to write
846   */
847  if (!failed) {
848    printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
849           "Enter filesize to write ==>");
850    fflush(stdout);
851    fgets(tmp_str,sizeof(tmp_str)-1,stdin);
852    failed = fileio_str2size(tmp_str,&file_size);
853    if (failed) {
854      printf("*** illegal file size, aborted\n");
855    }
856  }
857  /*
858   * get block size to write
859   */
860  if (!failed) {
861    printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
862           "Enter block size to use for write calls ==>");
863    fflush(stdout);
864    fgets(tmp_str,sizeof(tmp_str)-1,stdin);
865    failed = fileio_str2size(tmp_str,&buf_size);
866    if (failed) {
867      printf("*** illegal block size, aborted\n");
868    }
869  }
870
871  /*
872   * allocate buffer
873   */
874  if (!failed) {
875    printf("... allocating %lu bytes of buffer for write data\n",
876           (unsigned long)buf_size);
877    bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
878    if (bufptr == NULL) {
879      printf("*** malloc failed, aborted\n");
880      failed = true;
881    }
882  }
883  /*
884   * fill buffer with test pattern
885   */
886  if (!failed) {
887    printf("... filling buffer with write data\n");
888    curr_pos = 0;
889    /*
890     * fill buffer with test string
891     */
892    while (curr_pos < buf_size) {
893      bytes_to_copy = MIN(buf_size-curr_pos,
894                          sizeof(write_test_string)-1);
895      memcpy(bufptr+curr_pos,write_test_string,bytes_to_copy);
896      curr_pos += bytes_to_copy;
897    }
898    /*
899     * put "end" mark at end of buffer
900     */
901    bytes_to_copy = sizeof(write_block_string)-1;
902    if (buf_size >= bytes_to_copy) {
903      memcpy(bufptr+buf_size-bytes_to_copy,
904             write_block_string,
905             bytes_to_copy);
906    }
907  }
908  /*
909   * create file
910   */
911  if (!failed) {
912    printf("... creating file \"%s\"\n",fname);
913    fd = open(fname,O_WRONLY | O_CREAT | O_TRUNC,S_IREAD|S_IWRITE);
914    if (fd < 0) {
915      printf("*** file create failed, errno = %d(%s)\n",errno,strerror(errno));
916      failed = true;
917    }
918  }
919  /*
920   * write file
921   */
922  if (!failed) {
923    printf("... writing to file\n");
924    start_tick = rtems_clock_get_ticks_since_boot();
925    curr_pos = 0;
926    do {
927      bytes_to_copy = buf_size;
928      do {
929        n = write(fd,
930          bufptr + (buf_size-bytes_to_copy),
931                  MIN(bytes_to_copy,file_size-curr_pos));
932        if (n > 0) {
933          bytes_to_copy -= (size_t) n;
934          curr_pos      += (size_t) n;
935        }
936      } while ((bytes_to_copy > 0)  && (n > 0));
937    } while ((file_size > curr_pos) && (n > 0));
938    curr_tick = rtems_clock_get_ticks_since_boot();
939    if (n < 0) {
940      failed = true;
941      printf("*** file write failed, "
942             "%lu bytes written, "
943             "errno = %d(%s)\n",
944             (unsigned long)curr_pos,errno,strerror(errno));
945    }
946    else {
947      printf("time elapsed for write:  %g seconds\n",
948             ((double)curr_tick-start_tick)/ticks_per_sec);
949      printf("write data rate: %g KBytes/second\n",
950             (((double)file_size) / 1024.0 /
951              (((double)curr_tick-start_tick)/ticks_per_sec)));
952    }
953  }
954  if (fd >= 0) {
955    printf("... closing file\n");
956    close(fd);
957  }
958  if (bufptr != NULL) {
959    printf("... deallocating buffer\n");
960    free(bufptr);
961    bufptr = NULL;
962  }
963  printf("\n ******** End of file write\n");
964  fileio_print_free_heap();
965}
966
967static void fileio_read_file(void)
968{
969  char fname[1024];
970  char tmp_str[32];
971  uint32_t   buf_size  = 0;
972  size_t curr_pos;
973  int fd = -1;
974  ssize_t n;
975  rtems_interval start_tick,curr_tick,ticks_per_sec;
976  char *bufptr = NULL;
977  bool failed = false;
978
979  printf(" =========================\n");
980  printf(" READ FILE ...            \n");
981  printf(" =========================\n");
982  fileio_print_free_heap();
983  /*
984   * get number of ticks per second
985   */
986  ticks_per_sec = rtems_clock_get_ticks_per_second();
987
988  /*
989   * get path to file to read
990   */
991  if (!failed) {
992    printf("Enter path/filename ==>");
993    fflush(stdout);
994    fgets(fname,sizeof(fname)-1,stdin);
995    while (fname[strlen(fname)-1] == '\n') {
996      fname[strlen(fname)-1] = '\0';
997    }
998    if (0 == strlen(fname)) {
999      printf("*** no filename entered, aborted\n");
1000      failed = true;
1001    }
1002  }
1003  /*
1004   * get block size to read
1005   */
1006  if (!failed) {
1007    printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
1008           "Enter block size to use for read calls ==>");
1009    fflush(stdout);
1010    fgets(tmp_str,sizeof(tmp_str)-1,stdin);
1011    failed = fileio_str2size(tmp_str,&buf_size);
1012    if (failed) {
1013      printf("*** illegal block size, aborted\n");
1014    }
1015  }
1016
1017  /*
1018   * allocate buffer
1019   */
1020  if (!failed) {
1021    printf("... allocating %lu bytes of buffer for write data\n",
1022           (unsigned long)buf_size);
1023    bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
1024    if (bufptr == NULL) {
1025      printf("*** malloc failed, aborted\n");
1026      failed = true;
1027    }
1028  }
1029  /*
1030   * open file
1031   */
1032  if (!failed) {
1033    printf("... opening file \"%s\"\n",fname);
1034    fd = open(fname,O_RDONLY);
1035    if (fd < 0) {
1036      printf("*** failed to open file, errno = %d(%s)\n",errno,strerror(errno));
1037      failed = true;
1038    }
1039  }
1040  /*
1041   * read file
1042   */
1043  if (!failed) {
1044    printf("... reading from file\n");
1045    start_tick = rtems_clock_get_ticks_since_boot();
1046    curr_pos = 0;
1047    do {
1048      n = read(fd,
1049               bufptr,
1050               buf_size);
1051      if (n > 0) {
1052        curr_pos      += (size_t) n;
1053      }
1054    } while (n > 0);
1055    curr_tick = rtems_clock_get_ticks_since_boot();
1056    if (n < 0) {
1057      failed = true;
1058      printf("*** file read failed, "
1059             "%lu bytes read, "
1060             "errno = %d(%s)\n",
1061             (unsigned long)curr_pos,errno,strerror(errno));
1062    }
1063    else {
1064      printf("%lu bytes read\n",
1065             (unsigned long)curr_pos);
1066      printf("time elapsed for read:  %g seconds\n",
1067             ((double)curr_tick-start_tick)/ticks_per_sec);
1068      printf("read data rate: %g KBytes/second\n",
1069             (((double)curr_pos) / 1024.0 /
1070              (((double)curr_tick-start_tick)/ticks_per_sec)));
1071    }
1072  }
1073  if (fd >= 0) {
1074    printf("... closing file\n");
1075    close(fd);
1076  }
1077  if (bufptr != NULL) {
1078    printf("... deallocating buffer\n");
1079    free(bufptr);
1080    bufptr = NULL;
1081  }
1082  printf("\n ******** End of file read\n");
1083  fileio_print_free_heap();
1084
1085}
1086
1087static void fileio_menu (void)
1088{
1089  char inbuf[10];
1090
1091  /*
1092   * Wait for characters from console terminal
1093   */
1094  for (;;) {
1095    printf(" =========================\n");
1096    printf(" RTEMS FILE I/O Test Menu \n");
1097    printf(" =========================\n");
1098    printf("   p -> part_table_initialize\n");
1099    printf("   f -> mount all disks in fs_table\n");
1100    printf("   l -> list  file\n");
1101    printf("   r -> read  file\n");
1102    printf("   w -> write file\n");
1103#ifdef USE_SHELL
1104    printf("   s -> start shell\n");
1105#endif
1106    printf("   Enter your selection ==>");
1107    fflush(stdout);
1108
1109    inbuf[0] = '\0';
1110    fgets(inbuf,sizeof(inbuf),stdin);
1111    switch (inbuf[0]) {
1112    case 'l':
1113      fileio_list_file ();
1114      break;
1115    case 'r':
1116      fileio_read_file ();
1117      break;
1118    case 'w':
1119      fileio_write_file ();
1120      break;
1121    case 'p':
1122      fileio_part_table_initialize ();
1123      break;
1124    case 'f':
1125      fileio_fsmount ();
1126      break;
1127#ifdef USE_SHELL
1128    case 's':
1129      fileio_start_shell ();
1130      break;
1131#endif
1132    default:
1133      printf("Selection `%c` not implemented\n",inbuf[0]);
1134      break;
1135    }
1136
1137  }
1138  exit (0);
1139}
1140
1141/*
1142 * RTEMS File Menu Task
1143 */
1144static rtems_task
1145fileio_task (rtems_task_argument ignored)
1146{
1147  fileio_menu();
1148}
1149
1150static void
1151notification (int fd, int seconds_remaining, void *arg)
1152{
1153  printf(
1154    "Press any key to start file I/O sample (%is remaining)\n",
1155    seconds_remaining
1156  );
1157}
1158
1159/*
1160 * RTEMS Startup Task
1161 */
1162rtems_task
1163Init (rtems_task_argument ignored)
1164{
1165  rtems_name Task_name;
1166  rtems_id   Task_id;
1167  rtems_status_code status;
1168
1169  TEST_BEGIN();
1170
1171  crypt_add_format(&crypt_md5_format);
1172  crypt_add_format(&crypt_sha512_format);
1173
1174  status = rtems_shell_wait_for_input(
1175    STDIN_FILENO,
1176    20,
1177    notification,
1178    NULL
1179  );
1180  if (status == RTEMS_SUCCESSFUL) {
1181    Task_name = rtems_build_name('F','M','N','U');
1182
1183    status = rtems_task_create(
1184      Task_name, 1, RTEMS_MINIMUM_STACK_SIZE * 2,
1185      RTEMS_DEFAULT_MODES ,
1186      RTEMS_FLOATING_POINT | RTEMS_DEFAULT_ATTRIBUTES, &Task_id
1187    );
1188    directive_failed( status, "create" );
1189
1190    status = rtems_task_start( Task_id, fileio_task, 1 );
1191    directive_failed( status, "start" );
1192
1193    rtems_task_exit();
1194  } else {
1195    TEST_END();
1196
1197    rtems_test_exit( 0 );
1198  }
1199}
1200
1201#if defined(USE_SHELL)
1202/*
1203 *  RTEMS Shell Configuration -- Add a command and an alias for it
1204 */
1205
1206static int main_usercmd(int argc, char **argv)
1207{
1208  int i;
1209  printf( "UserCommand: argc=%d\n", argc );
1210  for (i=0 ; i<argc ; i++ )
1211    printf( "argv[%d]= %s\n", i, argv[i] );
1212  return 0;
1213}
1214
1215static rtems_shell_cmd_t Shell_USERCMD_Command = {
1216  "usercmd",                                       /* name */
1217  "usercmd n1 [n2 [n3...]]     # echo arguments",  /* usage */
1218  "user",                                          /* topic */
1219  main_usercmd,                                    /* command */
1220  NULL,                                            /* alias */
1221  NULL                                             /* next */
1222};
1223
1224static rtems_shell_alias_t Shell_USERECHO_Alias = {
1225  "usercmd",                 /* command */
1226  "userecho"                 /* alias */
1227};
1228
1229
1230#define CONFIGURE_SHELL_USER_COMMANDS &Shell_USERCMD_Command
1231#define CONFIGURE_SHELL_USER_ALIASES &Shell_USERECHO_Alias
1232#define CONFIGURE_SHELL_COMMANDS_INIT
1233#define CONFIGURE_SHELL_COMMANDS_ALL
1234#define CONFIGURE_SHELL_MOUNT_MSDOS
1235#define CONFIGURE_SHELL_MOUNT_RFS
1236#define CONFIGURE_SHELL_DEBUGRFS
1237
1238#include <rtems/shellconfig.h>
1239#endif
1240
1241#else
1242/*
1243 * RTEMS Startup Task
1244 */
1245rtems_task
1246Init (rtems_task_argument ignored)
1247{
1248  puts( "\n\n*** FILE I/O SAMPLE AND TEST ***" );
1249  puts( "\n\n*** NOT ENOUGH MEMORY TO BUILD AND RUN ***" );
1250}
1251#endif
Note: See TracBrowser for help on using the repository browser.