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

4.104.115
Last change on this file since 5027104 was 59762963, checked in by Chris Johns <chrisj@…>, on 02/22/10 at 23:02:41

2010-02-23 Chris Johns <chrisj@…>

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