From 7bb71c7e9dd7a95953a8507cb49f4949a01ae2e4 Mon Sep 17 00:00:00 2001 From: Andrei Mozzhuhin Date: Thu, 16 May 2013 11:24:09 +0200 Subject: shell: Add df command --- cpukit/libmisc/Makefile.am | 2 +- cpukit/libmisc/shell/main_df.c | 158 +++++++++++++++++++++++++++++++++++++ cpukit/libmisc/shell/shellconfig.h | 6 ++ doc/shell/file.t | 78 ++++++++++++++++++ 4 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 cpukit/libmisc/shell/main_df.c diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am index b0b219569a..5800a4763c 100644 --- a/cpukit/libmisc/Makefile.am +++ b/cpukit/libmisc/Makefile.am @@ -102,7 +102,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \ shell/hexdump-odsyntax.c shell/hexdump-parse.c shell/hexsyntax.c \ shell/main_time.c shell/main_mknod.c \ shell/main_setenv.c shell/main_getenv.c shell/main_unsetenv.c \ - shell/main_mkrfs.c shell/main_debugrfs.c \ + shell/main_mkrfs.c shell/main_debugrfs.c shell/main_df.c \ shell/main_lsof.c \ shell/main_blkstats.c \ shell/shell-wait-for-input.c diff --git a/cpukit/libmisc/shell/main_df.c b/cpukit/libmisc/shell/main_df.c new file mode 100644 index 0000000000..41183bd107 --- /dev/null +++ b/cpukit/libmisc/shell/main_df.c @@ -0,0 +1,158 @@ +/** + * df Shell Command Implmentation + * + * @brief Obtain MS-DOS filesystem information + * @ingroup libfs_msdos MSDOS FileSystem + */ + +/* + * Copyright (c) 2013 Andrey Mozzhuhin + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define __need_getopt_newlib +#include + +static const char suffixes[] = +{ 'B', 'K', 'M', 'G', 'T' }; + +struct df_context +{ + unsigned block_size; +}; + +static unsigned rtems_shell_df_parse_size(const char *str) +{ + unsigned result; + char suffix; + int i; + + if (sscanf(str, "%d%c", &result, &suffix) == 2) + { + for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) + { + if (suffix == suffixes[i]) + break; + result *= 1024; + } + } + else if (sscanf(str, "%d", &result) != 1) + { + result = 0; + } + + return result; +} + +static char *rtems_shell_df_humanize_size(unsigned block_size, char *buf, + size_t size) +{ + int i = 0; + + while (block_size >= 1024 && i < sizeof(suffixes) / sizeof(suffixes[0]) - 1) + { + block_size /= 1024; + i++; + } + + snprintf(buf, size, "%d%c", block_size, suffixes[i]); + return buf; +} + +static bool rtems_shell_df_print_entry( + const rtems_filesystem_mount_table_entry_t *mt_entry, void *arg) +{ + struct df_context *context = arg; + + struct statvfs svfs; + int code; + char f_buf[16], u_buf[16], a_buf[16]; + + if ((code = statvfs(mt_entry->target, &svfs))) + return false; + + if (context->block_size > 0) + { + printf("%-15s %10llu %9llu %11llu %9llu%% %14s\n", + mt_entry->dev == NULL ? "none" : mt_entry->dev, + (svfs.f_blocks * svfs.f_frsize + (context->block_size - 1)) / context->block_size, + ((svfs.f_blocks - svfs.f_bfree) * svfs.f_frsize + (context->block_size - 1)) / context->block_size, + (svfs.f_bfree * svfs.f_frsize + (context->block_size - 1)) / context->block_size, + ((svfs.f_blocks - svfs.f_bfree) * 100 / svfs.f_blocks), + mt_entry->target == NULL ? "none" : mt_entry->target); + } + else + { + rtems_shell_df_humanize_size(svfs.f_blocks * svfs.f_frsize, f_buf, + sizeof(f_buf)); + rtems_shell_df_humanize_size((svfs.f_blocks - svfs.f_bfree) * svfs.f_frsize, + u_buf, sizeof(u_buf)); + rtems_shell_df_humanize_size(svfs.f_bfree * svfs.f_frsize, a_buf, + sizeof(a_buf)); + printf("%-15s %10s %9s %11s %9llu%% %14s\n", + mt_entry->dev == NULL ? "none" : mt_entry->dev, f_buf, u_buf, a_buf, + (svfs.f_blocks - svfs.f_bfree) * 100 / svfs.f_blocks, + mt_entry->target == NULL ? "none" : mt_entry->target); + } + + return false; +} + +static int rtems_shell_main_df(int argc, char **argv) +{ + int c; + struct getopt_data optdata; + struct df_context context; + char buf[32]; + + memset(&optdata, 0, sizeof(optdata)); + context.block_size = 1024; + + while ((c = getopt_r(argc, (char**) argv, ":hB:", &optdata)) != -1) + { + switch (c) + { + case 'h': + context.block_size = 0; + break; + case 'B': + context.block_size = rtems_shell_df_parse_size(optdata.optarg); + break; + default: + return -1; + } + } + + if (context.block_size == 0) + printf( + "Filesystem Size Used Available Use%% Mounted on\n"); + else + printf( + "Filesystem %s-blocks Used Available Use%% Mounted on\n", + rtems_shell_df_humanize_size(context.block_size, buf, sizeof(buf))); + + rtems_filesystem_mount_iterate(rtems_shell_df_print_entry, &context); + + return 0; +} + +rtems_shell_cmd_t rtems_shell_DF_Command = +{ + "df", /* name */ + "[-hB]\n" + " -h human-readable output\n" + " -B scale sizes by SIZE before printing them\n", /* usage */ + "files", /* topic */ + rtems_shell_main_df, /* command */ + NULL, /* alias */ + NULL /* next */ +}; diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h index 9f451512a0..652d62bafd 100644 --- a/cpukit/libmisc/shell/shellconfig.h +++ b/cpukit/libmisc/shell/shellconfig.h @@ -70,6 +70,7 @@ extern rtems_shell_cmd_t rtems_shell_FDISK_Command; extern rtems_shell_cmd_t rtems_shell_DD_Command; extern rtems_shell_cmd_t rtems_shell_HEXDUMP_Command; extern rtems_shell_cmd_t rtems_shell_DEBUGRFS_Command; +extern rtems_shell_cmd_t rtems_shell_DF_Command; extern rtems_shell_cmd_t rtems_shell_RTC_Command; @@ -375,6 +376,11 @@ extern rtems_shell_alias_t *rtems_shell_Initial_aliases[]; defined(CONFIGURE_SHELL_COMMAND_DEBUGRFS) &rtems_shell_DEBUGRFS_Command, #endif + #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ + !defined(CONFIGURE_SHELL_NO_COMMAND_DF)) || \ + defined(CONFIGURE_SHELL_COMMAND_DF) + &rtems_shell_DF_Command, + #endif /* * RTEMS Related commands diff --git a/doc/shell/file.t b/doc/shell/file.t index c53a9cff3e..01a3b282b7 100644 --- a/doc/shell/file.t +++ b/doc/shell/file.t @@ -35,6 +35,7 @@ The RTEMS shell has the following file and directory commands: @item @code{dir} - alias for ls @item @code{mkrfs} - format RFS file system @item @code{cd} - alias for chdir +@item @code{df} - display file system disk space usage @end itemize @@ -2628,3 +2629,80 @@ following prototype: extern rtems_shell_cmd_t rtems_shell_CD_Command; @end example +@c +@c +@c +@page +@subsection df - display file system disk space usage + +@pgindex df + +@subheading SYNOPSYS: + +@example +df [-h] [-B block_size] +@end example + +@subheading DESCRIPTION: + +This command print disk space usage for mounted file systems. + +@subheading EXIT STATUS: + +This command returns 0 on success and non-zero if an error is encountered. + +@subheading NOTES: + +NONE + +@subheading EXAMPLES: + +The following is an example of how to use @code{df}: + +@example +SHLL [/] $ df -B 4K +Filesystem 4K-blocks Used Available Use% Mounted on +/dev/rda 124 1 124 0% /mnt/ramdisk +SHLL [/] $ df +Filesystem 1K-blocks Used Available Use% Mounted on +/dev/rda 495 1 494 0% /mnt/ramdisk +SHLL [/] $ df -h +Filesystem Size Used Available Use% Mounted on +/dev/rda 495K 1K 494K 0% /mnt/ramdisk +@end example + +@subheading CONFIGURATION: + +@findex CONFIGURE_SHELL_NO_COMMAND_DF +@findex CONFIGURE_SHELL_COMMAND_DF + +This command is included in the default shell command set. +When building a custom command set, define +@code{CONFIGURE_SHELL_COMMAND_DF} to have this +command included. + +This command can be excluded from the shell command set by +defining @code{CONFIGURE_SHELL_NO_COMMAND_DF} when all +shell commands have been configured. + +@subheading PROGRAMMING INFORMATION: + +@findex rtems_shell_rtems_main_df + +The @code{df} is implemented by a C language function +which has the following prototype: + +@example +int rtems_shell_main_df( + int argc, + char **argv +); +@end example + +The configuration structure for the @code{df} has the +following prototype: + +@example +extern rtems_shell_cmd_t rtems_shell_DF_Command; +@end example + -- cgit v1.2.3