source: rtems/cpukit/libfs/src/rfs/rtems-rfs-shell.c @ f639680

4.115
Last change on this file since f639680 was f639680, checked in by Ralf Corsepius <ralf.corsepius@…>, on 06/16/10 at 14:31:48

2010-06-16 Ralf Corsépius <ralf.corsepius@…>

PR 1556/cpukit

  • libfs/src/rfs/rtems-rfs-shell.c: Remove rtems_rfs_shell_cmd_t.
  • Property mode set to 100644
File size: 18.4 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File Systems Shell Commands Support
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <string.h>
23
24#include <rtems/rfs/rtems-rfs-block.h>
25#include <rtems/rfs/rtems-rfs-buffer.h>
26#include <rtems/rfs/rtems-rfs-group.h>
27#include <rtems/rfs/rtems-rfs-inode.h>
28#include <rtems/rfs/rtems-rfs-dir.h>
29#include <rtems/rtems-rfs-format.h>
30
31#include <sys/statvfs.h>
32
33#if __rtems__
34#include "rtems-rfs-rtems.h"
35#endif
36
37/**
38 * The type of the shell handlers we have.
39 */
40typedef int (*rtems_rfs_shell_handler) (rtems_rfs_file_system* fs, int argc, char *argv[]);
41
42/**
43 * Table of handlers we parse to invoke the command.
44 */
45typedef struct
46{
47  const char*             name;
48  rtems_rfs_shell_handler handler;
49  const char*             help;
50} rtems_rfs_shell_cmd;
51
52/**
53 * Lock the file system.
54 */
55static void
56rtems_rfs_shell_lock_rfs (rtems_rfs_file_system* fs)
57{
58#if __rtems__
59  rtems_rfs_rtems_lock (fs);
60#endif 
61}
62
63/**
64 * Unlock the file system.
65 */
66static void
67rtems_rfs_shell_unlock_rfs (rtems_rfs_file_system* fs)
68{
69#if __rtems__
70  rtems_rfs_rtems_unlock (fs);
71#endif 
72}
73
74/**
75 * Get the file system data from the specific path. Checks to make sure the path is
76 * pointing to a valid RFS file system.
77 */
78static int
79rtems_rfs_get_fs (const char* path, rtems_rfs_file_system** fs)
80{
81  struct statvfs sb;
82  int            rc;
83
84  rc = statvfs (path, &sb);
85  if (rc < 0)
86  {
87    printf ("error: cannot statvfs path: %s: (%d) %s\n",
88            path, errno, strerror (errno));
89    return -1;
90  }
91
92  if (sb.f_fsid != RTEMS_RFS_SB_MAGIC)
93  {
94    printf ("error: path '%s' is not on an RFS file system\n", path);
95    return -1;
96  }
97
98#if __rtems__
99  /*
100   * Now find the path location on the file system. This will give the file
101   * system data.
102   */
103  {
104    rtems_filesystem_location_info_t pathloc;
105    rc = rtems_filesystem_evaluate_path (path, strlen (path), 0, &pathloc, true);
106    *fs = rtems_rfs_rtems_pathloc_dev (&pathloc);
107    rtems_filesystem_freenode (&pathloc);
108  }
109#endif
110 
111  return rc;
112}
113
114static int
115rtems_rfs_shell_data (rtems_rfs_file_system* fs, int argc, char *argv[])
116{
117  size_t blocks;
118  size_t inodes;
119  int    bpcent;
120  int    ipcent;
121
122  printf ("RFS Filesystem Data\n");
123  printf ("             flags: %08lx\n", fs->flags);
124#if 0
125  printf ("            device: %08lx\n", rtems_rfs_fs_device (fs));
126#endif
127  printf ("            blocks: %zu\n",  rtems_rfs_fs_blocks (fs));
128  printf ("        block size: %zu\n",  rtems_rfs_fs_block_size (fs));
129  printf ("              size: %llu\n", rtems_rfs_fs_size (fs));
130  printf ("  media block size: %lu\n",  rtems_rfs_fs_media_block_size (fs));
131  printf ("        media size: %llu\n", rtems_rfs_fs_media_size (fs));
132  printf ("            inodes: %lu\n",  rtems_rfs_fs_inodes (fs));
133  printf ("        bad blocks: %lu\n",  fs->bad_blocks);
134  printf ("  max. name length: %lu\n",  rtems_rfs_fs_max_name (fs));
135  printf ("            groups: %d\n",   fs->group_count);
136  printf ("      group blocks: %zd\n",  fs->group_blocks);
137  printf ("      group inodes: %zd\n",  fs->group_inodes);
138  printf ("  inodes per block: %zd\n",  fs->inodes_per_block);
139  printf ("  blocks per block: %zd\n",  fs->blocks_per_block);
140  printf ("     singly blocks: %zd\n",  fs->block_map_singly_blocks);
141  printf ("    doublly blocks: %zd\n",  fs->block_map_doubly_blocks);
142  printf (" max. held buffers: %ld\n",  fs->max_held_buffers);
143
144  rtems_rfs_shell_lock_rfs (fs);
145
146  rtems_rfs_group_usage (fs, &blocks, &inodes);
147 
148  rtems_rfs_shell_unlock_rfs (fs);
149
150  bpcent = (blocks * 1000) / rtems_rfs_fs_blocks (fs);
151  ipcent = (inodes * 1000) / rtems_rfs_fs_inodes (fs);
152 
153  printf ("       blocks used: %zd (%d.%d%%)\n",
154          blocks, bpcent / 10, bpcent % 10);
155  printf ("       inodes used: %zd (%d.%d%%)\n",
156          inodes, ipcent / 10, ipcent % 10);
157 
158  return 0;
159}
160
161static int
162rtems_rfs_shell_block (rtems_rfs_file_system* fs, int argc, char *argv[])
163{
164  rtems_rfs_buffer_handle buffer;
165  rtems_rfs_block_no      block;
166  uint8_t*                data;
167  bool                    state;
168  int                     b;
169  int                     rc;
170 
171  if (argc <= 1)
172  {
173    printf ("error: no block number provided\n");
174    return 1;
175  }
176
177  block = strtoul (argv[1], 0, 0);
178
179  rtems_rfs_shell_lock_rfs (fs);
180 
181  rc = rtems_rfs_group_bitmap_test (fs, false, block, &state);
182  if (rc > 0)
183  {
184    rtems_rfs_shell_unlock_rfs (fs);
185    printf ("error: testing block state: block=%lu: (%d) %s\n",
186            block, rc, strerror (rc));
187    return 1;
188  }
189
190  printf (" %5lu: block %s\n", block, state ? "allocated" : "free");
191   
192  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
193  if (rc > 0)
194  {
195    rtems_rfs_shell_unlock_rfs (fs);
196    printf ("error: opening buffer handle: block=%lu: (%d) %s\n",
197            block, rc, strerror (rc));
198    return 1;
199  }
200
201  rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
202  if (rc > 0)
203  {
204    rtems_rfs_buffer_handle_close (fs, &buffer);
205    rtems_rfs_shell_unlock_rfs (fs);
206    printf ("error: requesting buffer handle: block=%lu: (%d) %s\n",
207            block, rc, strerror (rc));
208    return 1;
209  }
210
211  for (b = 0, data = rtems_rfs_buffer_data (&buffer);
212       b < rtems_rfs_fs_block_size (fs);
213       b++, data++)
214  {
215    int mod = b % 16;
216    if (mod == 0)
217    {
218      if (b)
219        printf ("\n");
220      printf ("%04x ", b);
221    }
222    if (mod == 8)
223      printf (" ");
224    printf ("%02x ", *data);
225  }
226
227  printf ("\n");
228 
229  rc = rtems_rfs_buffer_handle_close (fs, &buffer);
230  if (rc > 0)
231  {
232    rtems_rfs_shell_unlock_rfs (fs);
233    printf ("error: closing buffer handle: block=%lu: (%d) %s\n",
234            block, rc, strerror (rc));
235    return 1;
236  }
237 
238  rtems_rfs_shell_unlock_rfs (fs);
239 
240  return 0;
241}
242
243static int
244rtems_rfs_shell_inode (rtems_rfs_file_system* fs, int argc, char *argv[])
245{
246  rtems_rfs_ino start;
247  rtems_rfs_ino end;
248  rtems_rfs_ino total;
249  rtems_rfs_ino ino;
250  bool          show_all;
251  bool          error_check_only;
252  bool          forced;
253  bool          have_start;
254  bool          have_end;
255  int           arg;
256  int           b;
257  int           rc;
258
259  total = fs->group_inodes * fs->group_count;
260  start = RTEMS_RFS_ROOT_INO;
261  end = total - 1;
262  show_all = false;
263  error_check_only = false;
264  forced = false;
265  have_start = have_end = false;
266
267  for (arg = 1; arg < argc; arg++)
268  {
269    if (argv[arg][0] == '-')
270    {
271      switch (argv[arg][1])
272      {
273        case 'a':
274          show_all = true;
275          break;
276        case 'e':
277          error_check_only = true;
278          break;
279        case 'f':
280          forced = true;
281          break;
282        default:
283          printf ("warning: option ignored: %s\n", argv[arg]);
284          break;
285      }
286    }
287    else
288    {
289      if (have_end && have_start)
290        printf ("warning: option ignored: %s\n", argv[arg]);
291      else if (!have_start)
292      {
293        start = end = strtoul (argv[arg], 0, 0);
294        have_start = true;
295      }
296      else
297      {
298        end = strtoul (argv[arg], 0, 0);
299        have_end = true;
300      }
301    }
302  }
303
304  if ((start < 0) || (end < 0) ||
305      (start >= total) || (end >= total))
306  {
307    printf ("error: inode out of range (0->%ld).\n", total - 1);
308    return 1;
309  }
310
311  rtems_rfs_shell_lock_rfs (fs);
312 
313  for (ino = start; ino <= end; ino++)
314  {
315    rtems_rfs_inode_handle inode;
316    bool                   allocated;
317
318    rc = rtems_rfs_group_bitmap_test (fs, true, ino, &allocated);
319    if (rc > 0)
320    {
321      rtems_rfs_shell_unlock_rfs (fs);
322      printf ("error: testing inode state: ino=%lu: (%d) %s\n",
323              ino, rc, strerror (rc));
324      return 1;
325    }
326
327    if (show_all || allocated)
328    {
329      uint16_t mode;
330      bool     error;
331
332      rc = rtems_rfs_inode_open (fs, ino, &inode, true);
333      if (rc > 0)
334      {
335        rtems_rfs_shell_unlock_rfs (fs);
336        printf ("error: opening inode handle: ino=%lu: (%d) %s\n",
337                ino, rc, strerror (rc));
338        return 1;
339      }
340
341      error = false;
342     
343      mode = rtems_rfs_inode_get_mode (&inode);
344
345      if (error_check_only)
346      {
347        if (!RTEMS_RFS_S_ISDIR (mode) &&
348            !RTEMS_RFS_S_ISCHR (mode) &&
349            !RTEMS_RFS_S_ISBLK (mode) &&
350            !RTEMS_RFS_S_ISREG (mode) &&
351            !RTEMS_RFS_S_ISLNK (mode))
352          error = true;
353        else
354        {
355#if NEED_TO_HANDLE_DIFFERENT_TYPES
356          int b;
357          for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
358          {
359            uint32_t block;
360            block = rtems_rfs_inode_get_block (&inode, b);
361            if ((block <= RTEMS_RFS_SUPERBLOCK_SIZE) ||
362                (block >= rtems_rfs_fs_blocks (fs)))
363              error = true;
364          }
365#endif
366        }
367      }
368
369      if (!error_check_only || error)
370      {
371        printf (" %5lu: pos=%06lu:%04zx %c ",
372                ino, rtems_rfs_buffer_bnum (&inode.buffer),
373                inode.offset * RTEMS_RFS_INODE_SIZE,
374                allocated ? 'A' : 'F');
375   
376        if (!allocated && !forced)
377          printf (" --\n");
378        else
379        {     
380          const char* type;
381          type = "UKN";
382          if (RTEMS_RFS_S_ISDIR (mode))
383            type = "DIR";
384          else if (RTEMS_RFS_S_ISCHR (mode))
385            type = "CHR";
386          else if (RTEMS_RFS_S_ISBLK (mode))
387            type = "BLK";
388          else if (RTEMS_RFS_S_ISREG (mode))
389            type = "REG";
390          else if (RTEMS_RFS_S_ISLNK (mode))
391            type = "LNK";
392          printf ("links=%03i mode=%04x (%s/%03o) bo=%04u bc=%04lu b=[",
393                  rtems_rfs_inode_get_links (&inode),
394                  mode, type, mode & ((1 << 10) - 1),
395                  rtems_rfs_inode_get_block_offset (&inode),
396                  rtems_rfs_inode_get_block_count (&inode));
397          for (b = 0; b < (RTEMS_RFS_INODE_BLOCKS - 1); b++)
398            printf ("%lu ", rtems_rfs_inode_get_block (&inode, b));
399          printf ("%lu]\n", rtems_rfs_inode_get_block (&inode, b));
400        }
401      }
402     
403      rc = rtems_rfs_inode_close (fs, &inode);
404      if (rc > 0)
405      {
406        rtems_rfs_shell_unlock_rfs (fs);
407        printf ("error: closing inode handle: ino=%lu: (%d) %s\n",
408                ino, rc, strerror (rc));
409        return 1;
410      }
411    }
412  }
413 
414  rtems_rfs_shell_unlock_rfs (fs);
415 
416  return 0;
417}
418
419static int
420rtems_rfs_shell_dir (rtems_rfs_file_system* fs, int argc, char *argv[])
421{
422  rtems_rfs_buffer_handle buffer;
423  rtems_rfs_block_no      block;
424  uint8_t*                data;
425  bool                    state;
426  int                     entry;
427  int                     b;
428  int                     rc;
429 
430  if (argc <= 1)
431  {
432    printf ("error: no block number provided\n");
433    return 1;
434  }
435
436  block = strtoul (argv[1], 0, 0);
437
438  rtems_rfs_shell_lock_rfs (fs);
439 
440  rc = rtems_rfs_group_bitmap_test (fs, false, block, &state);
441  if (rc > 0)
442  {
443    rtems_rfs_shell_unlock_rfs (fs);
444    printf ("error: testing block state: block=%lu: (%d) %s\n",
445            block, rc, strerror (rc));
446    return 1;
447  }
448
449  printf (" %5lu: block %s\n", block, state ? "allocated" : "free");
450
451  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
452  if (rc > 0)
453  {
454    rtems_rfs_shell_unlock_rfs (fs);
455    printf ("error: opening buffer handle: block=%lu: (%d) %s\n",
456            block, rc, strerror (rc));
457    return 1;
458  }
459
460  rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
461  if (rc > 0)
462  {
463    rtems_rfs_buffer_handle_close (fs, &buffer);
464    rtems_rfs_shell_unlock_rfs (fs);
465    printf ("error: requesting buffer handle: block=%lu: (%d) %s\n",
466            block, rc, strerror (rc));
467    return 1;
468  }
469
470  b = 0;
471  entry = 1;
472  data = rtems_rfs_buffer_data (&buffer);
473 
474  while (b < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE - 1))
475  {
476    rtems_rfs_ino eino;
477    int           elength;
478    int           length;
479    int           c;
480
481    eino    = rtems_rfs_dir_entry_ino (data);
482    elength = rtems_rfs_dir_entry_length (data);
483   
484    if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
485      break;
486
487    if ((elength < RTEMS_RFS_DIR_ENTRY_SIZE) ||
488        (elength >= rtems_rfs_fs_max_name (fs)))
489    {
490      printf (" %5d: entry length appears corrupt: %d\n", entry, elength);
491      break;
492    }
493   
494    if ((eino < RTEMS_RFS_ROOT_INO) || (eino >= rtems_rfs_fs_inodes (fs)))
495    {
496      printf (" %5d: entry ino appears corrupt: ino=%ld\n", entry, eino);
497      break;
498    }
499   
500    length = elength - RTEMS_RFS_DIR_ENTRY_SIZE;
501   
502    printf (" %5d: %04x inode=%-6lu hash=%08lx name[%03u]=",
503            entry, b,
504            rtems_rfs_dir_entry_ino (data),
505            rtems_rfs_dir_entry_hash (data),
506            length);
507
508    if (length > 50)
509      length = 50;
510   
511    for (c = 0; c < length; c++)
512      printf ("%c", data[RTEMS_RFS_DIR_ENTRY_SIZE + c]);
513    if (length < elength - RTEMS_RFS_DIR_ENTRY_SIZE)
514      printf ("...");
515    printf ("\n");
516
517    b += elength;
518    data += elength;
519    entry++;
520  }
521 
522  rc = rtems_rfs_buffer_handle_close (fs, &buffer);
523  if (rc > 0)
524  {
525    rtems_rfs_shell_unlock_rfs (fs);
526    printf ("error: closing buffer handle: block=%lu: (%d) %s\n",
527            block, rc, strerror (rc));
528    return 1;
529  }
530 
531  rtems_rfs_shell_unlock_rfs (fs);
532 
533  return 0;
534}
535
536static int
537rtems_rfs_shell_group (rtems_rfs_file_system* fs, int argc, char *argv[])
538{
539  int start;
540  int end;
541  int g;
542
543  start = 0;
544  end = fs->group_count - 1;
545
546  switch (argc)
547  {
548    case 1:
549      break;
550    case 2:
551      start = end = strtoul (argv[1], 0, 0);
552      break;
553    case 3:
554      start = strtoul (argv[1], 0, 0);
555      end = strtoul (argv[2], 0, 0);
556      break;
557    default:
558      printf ("error: too many arguments.\n");
559      return 1;
560  }
561
562  if ((start < 0) || (end < 0) ||
563      (start >= fs->group_count) || (end >= fs->group_count))
564  {
565    printf ("error: group out of range (0->%d).\n", fs->group_count);
566    return 1;
567  }
568 
569  rtems_rfs_shell_lock_rfs (fs);
570
571  for (g = start; g <= end; g++)
572  {
573    rtems_rfs_group* group = &fs->groups[g];
574    size_t           blocks;
575    size_t           inodes;
576    blocks = group->size - rtems_rfs_bitmap_map_free (&group->block_bitmap);
577    inodes = fs->group_inodes - rtems_rfs_bitmap_map_free (&group->inode_bitmap);
578    printf (" %4d: base=%-7lu size=%-6zu blocks=%-5zu (%3zu%%) inode=%-5zu (%3zu%%)\n",
579            g, group->base, group->size,
580            blocks, (blocks * 100)  / group->size,
581            inodes, (inodes * 100) / fs->group_inodes);
582  }
583 
584  rtems_rfs_shell_unlock_rfs (fs);
585 
586  return 0;
587}
588
589
590void
591rtems_rfs_shell_usage (const char* arg)
592{
593  printf ("%s: RFS debugger\n", arg);
594  printf ("  %s [-hl] <path> <command>\n", arg);
595  printf ("   where:\n");
596  printf ("     path:    Path to the mounted RFS file system\n");
597  printf ("     command: A debugger command. See -l for a list plus help.\n");
598  printf ("     -h:      This help\n");
599  printf ("     -l:      The debugger command list.\n");
600}
601
602int
603rtems_shell_debugrfs (int argc, char *argv[])
604{
605  const rtems_rfs_shell_cmd table[] =
606  {
607    { "block", rtems_rfs_shell_block,
608      "Display the contents of a block, block <bno>, block <bno>..<bno>" },
609    { "data", rtems_rfs_shell_data,
610      "Display file system data, data" },
611    { "dir", rtems_rfs_shell_dir,
612      "Display a block as a table for directory entrie, dir <bno>" },
613    { "group", rtems_rfs_shell_group,
614      "Display the group data of a file system, group, group <group>, group <start> <end>" },
615    { "inode", rtems_rfs_shell_inode,
616      "Display an inode, inode <ino>, inode> <ino>..<ino>" }
617  };
618
619  int arg;
620  int t;
621 
622  for (arg = 1; arg < argc; arg++)
623  {
624    if (argv[arg][0] != '-')
625      break;
626
627    switch (argv[arg][1])
628    {
629      case 'h':
630        rtems_rfs_shell_usage (argv[0]);
631        return 0;
632      case 'l':
633        printf ("%s: commands are:\n", argv[0]);
634        for (t = 0; t < (sizeof (table) / sizeof (const rtems_rfs_shell_cmd)); t++)
635          printf ("  %s\t\t%s\n", table[t].name, table[t].help);
636        return 0;
637      default:
638        printf ("error: unknown option: %s\n", argv[arg]);
639        return 1;
640    }
641  }
642
643  if ((argc - arg) < 2)
644    printf ("error: you need at least a path and command, try %s -h\n", argv[0]);
645  else
646  {
647    rtems_rfs_file_system* fs;
648    if (rtems_rfs_get_fs (argv[arg], &fs) == 0)
649    {
650      for (t = 0; t < (sizeof (table) / sizeof (const rtems_rfs_shell_cmd)); t++)
651        if (strcmp (argv[arg + 1], table[t].name) == 0)
652          return table[t].handler (fs, argc - 2, argv + 2);
653      printf ("error: command not found: %s\n", argv[arg + 1]);
654    }
655  }
656 
657  return 1;
658}
659
660int
661rtems_shell_rfs_format (int argc, char* argv[])
662{
663  rtems_rfs_format_config config;
664  const char*             driver = NULL;
665  int                     arg;
666
667  memset (&config, 0, sizeof (rtems_rfs_format_config));
668
669  for (arg = 1; arg < argc; arg++)
670  {
671    if (argv[arg][0] == '-')
672    {
673      switch (argv[arg][1])
674      {
675        case 'v':
676          config.verbose = true;
677          break;
678         
679        case 's':
680          arg++;
681          if (arg >= argc)
682          {
683            printf ("error: block size needs an argument\n");
684            return 1;
685          }
686          config.block_size = strtoul (argv[arg], 0, 0);
687          break;
688       
689        case 'b':
690          arg++;
691          if (arg >= argc)
692          {
693            printf ("error: group block count needs an argument\n");
694            return 1;
695          }
696          config.group_blocks = strtoul (argv[arg], 0, 0);
697          break;
698         
699        case 'i':
700          arg++;
701          if (arg >= argc)
702          {
703            printf ("error: group inode count needs an argument\n");
704            return 1;
705          }
706          config.group_inodes = strtoul (argv[arg], 0, 0);
707          break;
708
709        case 'I':
710          config.initialise_inodes = true;
711          break;
712         
713        case 'o':
714          arg++;
715          if (arg >= argc)
716          {
717            printf ("error: inode percentage overhead needs an argument\n");
718            return 1;
719          }
720          config.inode_overhead = strtoul (argv[arg], 0, 0);
721          break;
722         
723        default:
724          printf ("error: invalid option: %s\n", argv[arg]);
725          return 1;
726      }
727    }
728    else
729    {
730      if (!driver)
731        driver = argv[arg];
732      else
733      {
734        printf ("error: only one driver name allowed: %s\n", argv[arg]);
735        return 1;
736      }
737    }
738  }
739
740  if (rtems_rfs_format (driver, &config) < 0)
741  {
742    printf ("error: format of %s failed: %s\n",
743            driver, strerror (errno));
744    return 1;
745  }
746 
747  return 0;
748}
Note: See TracBrowser for help on using the repository browser.