2 * Copyright (C) 2010-2011 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <xvasprintf.h>
31 #include <libvirt/libvirt.h>
32 #include <libvirt/virterror.h>
43 static void write_csv_field (const char *field);
50 cols[0] = _("VirtualMachine");
51 cols[1] = _("Filesystem");
54 cols[2] = _("1K-blocks");
58 cols[4] = _("Available");
61 cols[2] = _("Inodes");
68 /* ignore cols[0] in this mode */
69 printf ("%-36s%10s %10s %10s %5s\n",
70 cols[1], cols[2], cols[3], cols[4], cols[5]);
75 for (i = 0; i < 6; ++i) {
78 write_csv_field (cols[i]);
84 static void canonical_device (char *dev, int offset);
87 print_stat (const char *name, const char *uuid_param,
88 const char *dev_param, int offset,
89 const struct guestfs_statvfs *stat)
91 /* First two columns are always 'name' and 'dev', followed by four
92 * other data columns. In text mode the 'name' and 'dev' are
93 * combined into a single 'name:dev' column. In CSV mode they are
94 * kept as two separate columns. In UUID mode the name might be
95 * replaced by 'uuid', if available.
97 #define MAX_LEN (LONGEST_HUMAN_READABLE > 128 ? LONGEST_HUMAN_READABLE : 128)
102 int hopts = human_round_to_nearest|human_autoscale|human_base_1024|human_SI;
105 /* Make the device canonical. */
106 len = strlen (dev_param) + 1;
108 strcpy (dev, dev_param);
110 canonical_device (dev, offset);
112 if (!inodes) { /* 1K blocks */
114 factor = stat->bsize / 1024;
116 v = stat->blocks * factor;
117 snprintf (buf[0], MAX_LEN, "%" PRIi64, v);
119 v = (stat->blocks - stat->bfree) * factor;
120 snprintf (buf[1], MAX_LEN, "%" PRIi64, v);
122 v = stat->bavail * factor;
123 snprintf (buf[2], MAX_LEN, "%" PRIi64, v);
127 human_readable ((uintmax_t) stat->blocks, buf[0],
128 hopts, stat->bsize, 1);
129 v = stat->blocks - stat->bfree;
131 human_readable ((uintmax_t) v, buf[1], hopts, stat->bsize, 1);
133 human_readable ((uintmax_t) stat->bavail, buf[2],
134 hopts, stat->bsize, 1);
137 if (stat->blocks != 0)
138 percent = 100. - 100. * stat->bfree / stat->blocks;
143 snprintf (buf[0], MAX_LEN, "%" PRIi64, stat->files);
145 snprintf (buf[1], MAX_LEN, "%" PRIi64, stat->files - stat->ffree);
147 snprintf (buf[2], MAX_LEN, "%" PRIi64, stat->ffree);
150 if (stat->files != 0)
151 percent = 100. - 100. * stat->ffree / stat->files;
157 /* Use 'ceil' on the percentage in order to emulate what df itself does. */
158 snprintf (buf[3], MAX_LEN, "%3.0f%%", ceil (percent));
160 snprintf (buf[3], MAX_LEN, "%.1f", (double) percent);
165 if (uuid && uuid_param)
169 len = strlen (name) + strlen (dev) + 1;
170 printf ("%s:%s", name, dev);
172 for (i = len; i < 36; ++i)
178 printf ("%10s %10s %10s %5s\n", cols[0], cols[1], cols[2], cols[3]);
181 write_csv_field (name);
183 write_csv_field (dev);
185 for (i = 0; i < 4; ++i) {
187 write_csv_field (cols[i]);
194 /* /dev/vda1 -> /dev/sda, adjusting the device offset. */
196 canonical_device (char *dev, int offset)
198 if (STRPREFIX (dev, "/dev/") &&
199 (dev[5] == 'h' || dev[5] == 'v') &&
201 c_isalpha (dev[7]) &&
202 (c_isdigit (dev[8]) || dev[8] == '\0')) {
208 /* Function to quote CSV fields on output without requiring an
212 write_csv_field (const char *field)
215 int needs_quoting = 0;
217 len = strlen (field);
219 for (i = 0; i < len; ++i) {
220 if (field[i] == ' ' || field[i] == '"' ||
221 field[i] == '\n' || field[i] == ',') {
227 if (!needs_quoting) {
228 printf ("%s", field);
232 /* Quoting for CSV fields. */
234 for (i = 0; i < len; ++i) {
235 if (field[i] == '"') {