1 | /** |
---|
2 | * df Shell Command Implmentation |
---|
3 | * |
---|
4 | * @brief Obtain MS-DOS filesystem information |
---|
5 | * @ingroup libfs_msdos MSDOS FileSystem |
---|
6 | */ |
---|
7 | |
---|
8 | /* |
---|
9 | * Copyright (c) 2013 Andrey Mozzhuhin |
---|
10 | * |
---|
11 | * The license and distribution terms for this file may be |
---|
12 | * found in the file LICENSE in this distribution or at |
---|
13 | * http://www.rtems.org/license/LICENSE. |
---|
14 | */ |
---|
15 | |
---|
16 | #ifdef HAVE_CONFIG_H |
---|
17 | #include "config.h" |
---|
18 | #endif |
---|
19 | |
---|
20 | #include <rtems/shell.h> |
---|
21 | |
---|
22 | #define __need_getopt_newlib |
---|
23 | #include <getopt.h> |
---|
24 | #include <string.h> |
---|
25 | |
---|
26 | static const char suffixes[] = |
---|
27 | { 'B', 'K', 'M', 'G', 'T' }; |
---|
28 | |
---|
29 | struct df_context |
---|
30 | { |
---|
31 | unsigned block_size; |
---|
32 | }; |
---|
33 | |
---|
34 | static unsigned rtems_shell_df_parse_size(const char *str) |
---|
35 | { |
---|
36 | unsigned result; |
---|
37 | char suffix; |
---|
38 | int i; |
---|
39 | |
---|
40 | if (sscanf(str, "%d%c", &result, &suffix) == 2) |
---|
41 | { |
---|
42 | for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) |
---|
43 | { |
---|
44 | if (suffix == suffixes[i]) |
---|
45 | break; |
---|
46 | result *= 1024; |
---|
47 | } |
---|
48 | } |
---|
49 | else if (sscanf(str, "%d", &result) != 1) |
---|
50 | { |
---|
51 | result = 0; |
---|
52 | } |
---|
53 | |
---|
54 | return result; |
---|
55 | } |
---|
56 | |
---|
57 | static char *rtems_shell_df_humanize_size(unsigned block_size, char *buf, |
---|
58 | size_t size) |
---|
59 | { |
---|
60 | int i = 0; |
---|
61 | |
---|
62 | while (block_size >= 1024 && i < sizeof(suffixes) / sizeof(suffixes[0]) - 1) |
---|
63 | { |
---|
64 | block_size /= 1024; |
---|
65 | i++; |
---|
66 | } |
---|
67 | |
---|
68 | snprintf(buf, size, "%d%c", block_size, suffixes[i]); |
---|
69 | return buf; |
---|
70 | } |
---|
71 | |
---|
72 | static bool rtems_shell_df_print_entry( |
---|
73 | const rtems_filesystem_mount_table_entry_t *mt_entry, void *arg) |
---|
74 | { |
---|
75 | struct df_context *context = arg; |
---|
76 | |
---|
77 | struct statvfs svfs; |
---|
78 | int code; |
---|
79 | char f_buf[16], u_buf[16], a_buf[16]; |
---|
80 | |
---|
81 | if ((code = statvfs(mt_entry->target, &svfs))) |
---|
82 | return false; |
---|
83 | |
---|
84 | if (context->block_size > 0) |
---|
85 | { |
---|
86 | printf("%-15s %10llu %9llu %11llu %9llu%% %14s\n", |
---|
87 | mt_entry->dev == NULL ? "none" : mt_entry->dev, |
---|
88 | (svfs.f_blocks * svfs.f_frsize + (context->block_size - 1)) / context->block_size, |
---|
89 | ((svfs.f_blocks - svfs.f_bfree) * svfs.f_frsize + (context->block_size - 1)) / context->block_size, |
---|
90 | (svfs.f_bfree * svfs.f_frsize + (context->block_size - 1)) / context->block_size, |
---|
91 | ((svfs.f_blocks - svfs.f_bfree) * 100 / svfs.f_blocks), |
---|
92 | mt_entry->target == NULL ? "none" : mt_entry->target); |
---|
93 | } |
---|
94 | else |
---|
95 | { |
---|
96 | rtems_shell_df_humanize_size(svfs.f_blocks * svfs.f_frsize, f_buf, |
---|
97 | sizeof(f_buf)); |
---|
98 | rtems_shell_df_humanize_size((svfs.f_blocks - svfs.f_bfree) * svfs.f_frsize, |
---|
99 | u_buf, sizeof(u_buf)); |
---|
100 | rtems_shell_df_humanize_size(svfs.f_bfree * svfs.f_frsize, a_buf, |
---|
101 | sizeof(a_buf)); |
---|
102 | printf("%-15s %10s %9s %11s %9llu%% %14s\n", |
---|
103 | mt_entry->dev == NULL ? "none" : mt_entry->dev, f_buf, u_buf, a_buf, |
---|
104 | (svfs.f_blocks - svfs.f_bfree) * 100 / svfs.f_blocks, |
---|
105 | mt_entry->target == NULL ? "none" : mt_entry->target); |
---|
106 | } |
---|
107 | |
---|
108 | return false; |
---|
109 | } |
---|
110 | |
---|
111 | static int rtems_shell_main_df(int argc, char **argv) |
---|
112 | { |
---|
113 | int c; |
---|
114 | struct getopt_data optdata; |
---|
115 | struct df_context context; |
---|
116 | char buf[32]; |
---|
117 | |
---|
118 | memset(&optdata, 0, sizeof(optdata)); |
---|
119 | context.block_size = 1024; |
---|
120 | |
---|
121 | while ((c = getopt_r(argc, (char**) argv, ":hB:", &optdata)) != -1) |
---|
122 | { |
---|
123 | switch (c) |
---|
124 | { |
---|
125 | case 'h': |
---|
126 | context.block_size = 0; |
---|
127 | break; |
---|
128 | case 'B': |
---|
129 | context.block_size = rtems_shell_df_parse_size(optdata.optarg); |
---|
130 | break; |
---|
131 | default: |
---|
132 | return -1; |
---|
133 | } |
---|
134 | } |
---|
135 | |
---|
136 | if (context.block_size == 0) |
---|
137 | printf( |
---|
138 | "Filesystem Size Used Available Use%% Mounted on\n"); |
---|
139 | else |
---|
140 | printf( |
---|
141 | "Filesystem %s-blocks Used Available Use%% Mounted on\n", |
---|
142 | rtems_shell_df_humanize_size(context.block_size, buf, sizeof(buf))); |
---|
143 | |
---|
144 | rtems_filesystem_mount_iterate(rtems_shell_df_print_entry, &context); |
---|
145 | |
---|
146 | return 0; |
---|
147 | } |
---|
148 | |
---|
149 | rtems_shell_cmd_t rtems_shell_DF_Command = |
---|
150 | { |
---|
151 | "df", /* name */ |
---|
152 | "[-hB]\n" |
---|
153 | " -h human-readable output\n" |
---|
154 | " -B scale sizes by SIZE before printing them\n", /* usage */ |
---|
155 | "files", /* topic */ |
---|
156 | rtems_shell_main_df, /* command */ |
---|
157 | NULL, /* alias */ |
---|
158 | NULL /* next */ |
---|
159 | }; |
---|