bbda694567bbd18f41734b1827c8aa905703f81a
[oweals/busybox.git] / coreutils / df.c
1 #include "internal.h"
2 #include <stdio.h>
3 #include <mntent.h>
4 #include <sys/stat.h>
5 #include <sys/vfs.h>
6
7 const char      df_usage[] = "df [filesystem ...]\n"
8 "\n"
9 "\tPrint the filesystem space used and space available.\n";
10
11
12 static int
13 df(const char * device, const char * mountPoint)
14 {
15         struct statfs   s;
16         long            blocks_used;
17         long            blocks_percent_used;
18
19         if ( statfs(mountPoint, &s) != 0 ) {
20                 perror(mountPoint);
21                 return 1;
22         }
23         
24         if ( s.f_blocks > 0 ) {
25                 blocks_used = s.f_blocks - s.f_bfree;
26                 blocks_percent_used = (long)
27                  (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
28
29 /*
30                 printf(
31                  "%-20s %7ld %7ld  %7ld  %5ld%%   %s\n"
32                 ,device
33                 ,s.f_blocks
34                 ,s.f_blocks - s.f_bfree
35                 ,s.f_bavail
36                 ,blocks_percent_used
37                 ,mountPoint);
38 */
39
40                 printf(
41                        "%-20s %7.0f %7.0f  %7.0f  %5ld%%   %s\n"
42                        ,device
43                        ,s.f_blocks * (s.f_bsize / 1024.0)
44                        ,(s.f_blocks - s.f_bfree)  * (s.f_bsize / 1024.0)
45                        ,s.f_bavail * (s.f_bsize / 1024.0)
46                        ,blocks_percent_used
47                        ,mountPoint);
48
49         }
50
51         return 0;
52 }
53
54 extern int
55 df_main(int argc, char * * argv)
56 {
57         static const char header[] =
58          "Filesystem         1024-blocks  Used Available Capacity Mounted on\n";
59         printf(header);
60
61         if ( argc > 1 ) {
62                 struct mntent * mountEntry;
63                 int                             status;
64
65                 while ( argc > 1 ) {
66                         if ( (mountEntry = findMountPoint(argv[1], "/proc/mounts")) == 0 )
67                         {
68                                 fprintf(stderr, "%s: can't find mount point.\n" ,argv[1]);
69                                 return 1;
70                         }
71                         status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
72                         if ( status != 0 )
73                                 return status;
74                         argc--;
75                         argv++;
76                 }
77                 return 0;
78         }
79         else {
80                 FILE *          mountTable;
81                 struct mntent * mountEntry;
82
83                 if ( (mountTable = setmntent("/proc/mounts", "r")) == 0) {
84                         perror("/proc/mounts");
85                         return 1;
86                 }
87
88                 while ( (mountEntry = getmntent(mountTable)) != 0 ) {
89                         int status = df(
90                          mountEntry->mnt_fsname
91                         ,mountEntry->mnt_dir);
92                         if ( status != 0 )
93                                 return status;
94                 }
95                 endmntent(mountTable);
96         }
97         
98         return 0;
99 }
100
101
102
103
104 /*
105  * Given a block device, find the mount table entry if that block device
106  * is mounted.
107  *
108  * Given any other file (or directory), find the mount table entry for its
109  * filesystem.
110  */
111 extern struct mntent *
112 findMountPoint(const char * name, const char * table)
113 {
114         struct stat     s;
115         dev_t                   mountDevice;
116         FILE *                  mountTable;
117         struct mntent * mountEntry;
118
119         if ( stat(name, &s) != 0 )
120                 return 0;
121
122         if ( (s.st_mode & S_IFMT) == S_IFBLK )
123                 mountDevice = s.st_rdev;
124         else
125                 mountDevice = s.st_dev;
126
127         
128         if ( (mountTable = setmntent(table, "r")) == 0 )
129                 return 0;
130
131         while ( (mountEntry = getmntent(mountTable)) != 0 ) {
132                 if ( strcmp(name, mountEntry->mnt_dir) == 0
133                  || strcmp(name, mountEntry->mnt_fsname) == 0 ) /* String match. */
134                         break;
135                 if ( stat(mountEntry->mnt_fsname, &s) == 0
136                  && s.st_rdev == mountDevice )  /* Match the device. */
137                                 break;
138                 if ( stat(mountEntry->mnt_dir, &s) == 0
139                  && s.st_dev == mountDevice )   /* Match the directory's mount point. */
140                         break;
141         }
142         endmntent(mountTable);
143         return mountEntry;
144 }