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

4.115
Last change on this file since acf9a8d was acf9a8d, checked in by Sebastian Huber <sebastian.huber@…>, on 11/14/14 at 13:31:54

shell: Use crypt_r() in rtems_shell_login_check()

Use '*" to disable shell login instead of '!' according to the Linux man
page. Use getpwnam_r() instead of getpwnam(). Do not access the user
environment directly. Update the user environment only after a
successful login check.

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