Merge remote-tracking branch 'origin/vendor/BINUTILS227'
[dragonfly.git] / sbin / hammer / cmd_info.c
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Antonio Huete <tuxillo@quantumachine.net>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35
36 #include <libutil.h>
37 #include <libhammer.h>
38
39 #include "hammer.h"
40
41 void show_info(char *path);
42 static double percent(int64_t value, int64_t total);
43
44 void
45 hammer_cmd_info(char **av, int ac)
46 {
47         struct statfs *stfsbuf;
48         int mntsize, i, first = 1;
49         char *fstype, *path;
50
51         tzset();
52
53         if (ac > 0) {
54                 while (ac) {
55                         show_info(*av);
56                         --ac;
57                         ++av;
58                         if (ac)
59                                 printf("\n");
60                 }
61         } else {
62                 mntsize = getmntinfo(&stfsbuf, MNT_NOWAIT);
63                 if (mntsize > 0) {
64                         for (i = 0; i < mntsize; i++) {
65                                 fstype = stfsbuf[i].f_fstypename;
66                                 path = stfsbuf[i].f_mntonname;
67                                 if ((strcmp(fstype, "hammer")) == 0) {
68                                         if (first)
69                                                 first = 0;
70                                         else
71                                                 printf("\n");
72                                         show_info(path);
73                                 }
74                         }
75                         if (first)
76                                 printf("No mounted HAMMER filesystems found\n");
77                 } else {
78                         printf("No mounted filesystems found\n");
79                 }
80         }
81 }
82
83 void
84 show_info(char *path)
85 {
86         libhammer_fsinfo_t fip;
87         libhammer_pfsinfo_t pi, pi_first;
88         struct hammer_ioc_volume_list ioc;
89         int64_t     usedbigblocks;
90         int64_t     usedbytes, rsvbytes;
91         int64_t     totalbytes, freebytes;
92         char        *fsid;
93         char        buf[6];
94         char        rootvol[MAXPATHLEN];
95         int i;
96
97         fsid = NULL;
98         usedbigblocks = 0;
99
100         usedbytes = totalbytes = rsvbytes = freebytes = 0;
101
102         fip = libhammer_get_fsinfo(path);
103         if (fip == NULL) {
104                 perror("libhammer_get_fsinfo");
105                 exit(EXIT_FAILURE);
106         }
107
108         /* Find out the UUID strings */
109         uuid_to_string(&fip->vol_fsid, &fsid, NULL);
110
111         /* Get the volume paths */
112         if (hammer_fs_to_vol(path, &ioc) == -1) {
113                 fprintf(stderr, "Failed to get volume paths\n");
114                 exit(1);
115         }
116
117         /* Get the root volume path */
118         if (hammer_fs_to_rootvol(path, rootvol, sizeof(rootvol)) == -1) {
119                 fprintf(stderr, "Failed to get root volume path\n");
120                 exit(1);
121         }
122
123         /* Volume information */
124         printf("Volume identification\n");
125         printf("\tLabel               %s\n", fip->vol_name);
126         printf("\tNo. Volumes         %d\n", fip->nvolumes);
127         printf("\tHAMMER Volumes      ");
128         for (i = 0; i < ioc.nvols; i++) {
129                 printf("%s", ioc.vols[i].device_name);
130                 if (i != ioc.nvols - 1)
131                         printf(":");
132         }
133         printf("\n");
134         printf("\tRoot Volume         %s\n", rootvol);
135         printf("\tFSID                %s\n", fsid);
136         printf("\tHAMMER Version      %d\n", fip->version);
137
138         /* Big-blocks information */
139         usedbigblocks = fip->bigblocks - fip->freebigblocks;
140
141         printf("Big-block information\n");
142         printf("\tTotal      %10jd\n", (intmax_t)fip->bigblocks);
143         printf("\tUsed       %10jd (%.2lf%%)\n"
144                "\tReserved   %10jd (%.2lf%%)\n"
145                "\tFree       %10jd (%.2lf%%)\n",
146                 (intmax_t)usedbigblocks,
147                 percent(usedbigblocks, fip->bigblocks),
148                 (intmax_t)fip->rsvbigblocks,
149                 percent(fip->rsvbigblocks, fip->bigblocks),
150                 (intmax_t)(fip->freebigblocks - fip->rsvbigblocks),
151                 percent(fip->freebigblocks - fip->rsvbigblocks, fip->bigblocks));
152         printf("Space information\n");
153
154         /* Space information */
155         totalbytes = (fip->bigblocks << HAMMER_BIGBLOCK_BITS);
156         usedbytes = (usedbigblocks << HAMMER_BIGBLOCK_BITS);
157         rsvbytes = (fip->rsvbigblocks << HAMMER_BIGBLOCK_BITS);
158         freebytes = ((fip->freebigblocks - fip->rsvbigblocks)
159             << HAMMER_BIGBLOCK_BITS);
160
161         printf("\tNo. Inodes %10jd\n", (intmax_t)fip->inodes);
162         humanize_number(buf, sizeof(buf)  - (totalbytes < 0 ? 0 : 1),
163             totalbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
164         printf("\tTotal size     %6s (%jd bytes)\n",
165             buf, (intmax_t)totalbytes);
166
167         humanize_number(buf, sizeof(buf)  - (usedbytes < 0 ? 0 : 1),
168             usedbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
169         printf("\tUsed           %6s (%.2lf%%)\n", buf,
170             percent(usedbytes, totalbytes));
171
172         humanize_number(buf, sizeof(buf)  - (rsvbytes < 0 ? 0 : 1),
173             rsvbytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
174         printf("\tReserved       %6s (%.2lf%%)\n", buf,
175             percent(rsvbytes, totalbytes));
176
177         humanize_number(buf, sizeof(buf)  - (freebytes < 0 ? 0 : 1),
178             freebytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE | HN_B);
179         printf("\tFree           %6s (%.2lf%%)\n", buf,
180             percent(freebytes, totalbytes));
181
182         /* Pseudo-filesystem information */
183         printf("PFS information\n");
184         printf("\tPFS ID  Mode    Snaps\n");
185
186         /* Iterate all the PFSs found */
187         pi_first = libhammer_get_first_pfs(fip);
188         for (pi = pi_first; pi != NULL; pi = libhammer_get_next_pfs(pi)) {
189                 printf("\t%6d  %-6s",
190                     pi->pfs_id, (pi->ismaster ? "MASTER" : "SLAVE"));
191
192                 snprintf(buf, 6, "%d", pi->snapcount);
193                 printf(" %6s\n", (pi->head.error && pi->snapcount == 0) ? "-" : buf);
194         }
195
196         free(fsid);
197
198         libhammer_free_fsinfo(fip);
199
200 }
201
202 static double
203 percent(int64_t value, int64_t total)
204 {
205         /* Avoid divide-by-zero */
206         if (total == 0)
207                 return 100.0;
208
209         return ((value * 100.0) / (double)total);
210 }