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

4.115
Last change on this file since eb8c45d was eb8c45d, checked in by Joel Sherrill <joel.sherrill@…>, on 06/24/10 at 13:28:39

2010-06-24 Joel Sherrill <joel.sherrilL@…>

PR 1587/filesystem
Coverity Id 35

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