/** * df Shell Command Implmentation * * @ingroup libfs_msdos MSDOS FileSystem * * @brief Obtain MS-DOS filesystem information */ /* * 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.org/license/LICENSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #define __need_getopt_newlib #include #include #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 %10" PRIu64 " %9" PRIu64 " %11" PRIu64 " %9" PRIu64 "%% %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 %9" PRIu64 "%% %14s\n", mt_entry->dev == NULL ? "none" : mt_entry->dev, f_buf, u_buf, a_buf, (uint64_t)(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 */ };