Add errno.h
[oweals/busybox.git] / df.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini df implementation for busybox
4  *
5  * Copyright (C) 1999,2000 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7  * based on original code by (I think) Bruce Perens <bruce@pixar.com>.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  */
24
25 #include "busybox.h"
26 #include <stdio.h>
27 #include <mntent.h>
28 #include <sys/vfs.h>
29
30 extern const char mtab_file[];  /* Defined in utility.c */
31 #ifdef BB_FEATURE_HUMAN_READABLE
32 unsigned long disp_hr = KILOBYTE; 
33 #endif
34
35 static int df(char *device, const char *mountPoint)
36 {
37         struct statfs s;
38         long blocks_used;
39         long blocks_percent_used;
40
41         if (statfs(mountPoint, &s) != 0) {
42                 perror_msg("%s", mountPoint);
43                 return FALSE;
44         }
45
46         if (s.f_blocks > 0) {
47                 blocks_used = s.f_blocks - s.f_bfree;
48                 if(0 == blocks_used)
49                         blocks_percent_used = 0;
50                 else
51                         blocks_percent_used = (long)
52                           (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
53                 if (strcmp(device, "/dev/root") == 0) {
54                         /* Adjusts device to be the real root device,
55                          * or leaves device alone if it can't find it */
56                         find_real_root_device_name( device);
57                 }
58 #ifdef BB_FEATURE_HUMAN_READABLE
59                 printf("%-20s %9s",
60                            device,
61                            format((s.f_blocks * s.f_bsize), disp_hr));
62                 printf(" %9s", format((s.f_blocks - s.f_bfree) * s.f_bsize, disp_hr));
63                 printf(" %9s %3ld%% %s\n",
64                            format(s.f_bavail * s.f_bsize, disp_hr),
65                            blocks_percent_used, mountPoint);
66 #else
67                 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
68                            device,
69                            (long) (s.f_blocks * (s.f_bsize / 1024.0)),
70                            (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
71                            (long) (s.f_bavail * (s.f_bsize / 1024.0)),
72                            blocks_percent_used, mountPoint);
73 #endif
74
75         }
76
77         return TRUE;
78 }
79
80 extern int df_main(int argc, char **argv)
81 {
82         int status = EXIT_SUCCESS;
83         int opt = 0;
84         int i = 0;
85
86         while ((opt = getopt(argc, argv, "?"
87 #ifdef BB_FEATURE_HUMAN_READABLE
88         "hm"
89 #endif
90         "k"
91 )) > 0)
92         {
93                 switch (opt) {
94 #ifdef BB_FEATURE_HUMAN_READABLE
95                         case 'h': disp_hr = 0;         break;
96                         case 'm': disp_hr = MEGABYTE;  break;
97                         case 'k': disp_hr = KILOBYTE;  break;
98 #else
99                         case 'k': break;
100 #endif
101                         case '?': goto print_df_usage; break;
102                 }
103         }
104
105         printf("%-20s %-14s %s %s %s %s\n", "Filesystem",
106 #ifdef BB_FEATURE_HUMAN_READABLE
107                    (KILOBYTE == disp_hr) ? "1k-blocks" : "     Size",
108 #else
109                    "1k-blocks",
110 #endif
111                "Used", "Available", "Use%", "Mounted on");
112
113
114         if(optind < argc) {
115                 struct mntent *mountEntry;
116                 for(i = optind; i < argc; i++)
117                 {
118                         if ((mountEntry = find_mount_point(argv[i], mtab_file)) == 0) {
119                                 error_msg("%s: can't find mount point.\n", argv[i]);
120                                 status = EXIT_FAILURE;
121                         } else if (!df(mountEntry->mnt_fsname, mountEntry->mnt_dir))
122                                 status = EXIT_FAILURE;
123                 }
124         } else {
125                 FILE *mountTable;
126                 struct mntent *mountEntry;
127
128                 mountTable = setmntent(mtab_file, "r");
129                 if (mountTable == 0) {
130                         perror_msg("%s", mtab_file);
131                         return EXIT_FAILURE;
132                 }
133
134                 while ((mountEntry = getmntent(mountTable))) {
135                         if (!df(mountEntry->mnt_fsname, mountEntry->mnt_dir))
136                                 status = EXIT_FAILURE;
137                 }
138                 endmntent(mountTable);
139         }
140
141         return status;
142
143 print_df_usage:
144     usage(df_usage);
145     return(FALSE);
146 }
147
148 /*
149 Local Variables:
150 c-file-style: "linux"
151 c-basic-offset: 4
152 tab-width: 4
153 End:
154 */