Fixed up copyright notices and such
[platform/upstream/busybox.git] / df.c
1 /*
2  * Mini df implementation for busybox
3  *
4  * Copyright (C) 1999 by Lineo, inc.
5  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
6  * based on original code by (I think) Bruce Perens <bruce@pixar.com>.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23
24 #include "internal.h"
25 #include <stdio.h>
26 #include <mntent.h>
27 #include <sys/stat.h>
28 #include <sys/vfs.h>
29 #include <fstab.h>
30
31 static const char df_usage[] = "df [filesystem ...]\n"
32     "\n" "\tPrint the filesystem space used and space available.\n";
33
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(mountPoint);
43         return 1;
44     }
45
46     if (s.f_blocks > 0) {
47         blocks_used = s.f_blocks - s.f_bfree;
48         blocks_percent_used = (long)
49             (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
50         if (strcmp(device, "/dev/root") == 0)
51             device = (getfsfile("/"))->fs_spec;
52
53         printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
54                device,
55                (long) (s.f_blocks * (s.f_bsize / 1024.0)),
56                (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
57                (long) (s.f_bavail * (s.f_bsize / 1024.0)),
58                blocks_percent_used, mountPoint);
59
60     }
61
62     return 0;
63 }
64
65 /*
66  * Given a block device, find the mount table entry if that block device
67  * is mounted.
68  *
69  * Given any other file (or directory), find the mount table entry for its
70  * filesystem.
71  */
72 extern struct mntent *findMountPoint(const char *name, const char *table)
73 {
74     struct stat s;
75     dev_t mountDevice;
76     FILE *mountTable;
77     struct mntent *mountEntry;
78
79     if (stat(name, &s) != 0)
80         return 0;
81
82     if ((s.st_mode & S_IFMT) == S_IFBLK)
83         mountDevice = s.st_rdev;
84     else
85         mountDevice = s.st_dev;
86
87
88     if ((mountTable = setmntent(table, "r")) == 0)
89         return 0;
90
91     while ((mountEntry = getmntent(mountTable)) != 0) {
92         if (strcmp(name, mountEntry->mnt_dir) == 0
93             || strcmp(name, mountEntry->mnt_fsname) == 0)       /* String match. */
94             break;
95         if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice)  /* Match the device. */
96             break;
97         if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice)      /* Match the directory's mount point. */
98             break;
99     }
100     endmntent(mountTable);
101     return mountEntry;
102 }
103
104
105
106 extern int df_main(int argc, char **argv)
107 {
108     printf("%-20s %-14s %s %s %s %s\n", "Filesystem",
109            "1k-blocks", "Used", "Available", "Use%", "Mounted on");
110
111     if (argc > 1) {
112         struct mntent *mountEntry;
113         int status;
114
115         while (argc > 1) {
116             if ((mountEntry = findMountPoint(argv[1], "/proc/mounts")) ==
117                 0) {
118                 fprintf(stderr, "%s: can't find mount point.\n", argv[1]);
119                 return 1;
120             }
121             status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
122             if (status != 0)
123                 return status;
124             argc--;
125             argv++;
126         }
127         return 0;
128     } else {
129         FILE *mountTable;
130         struct mntent *mountEntry;
131
132         mountTable = setmntent("/proc/mounts", "r");
133         if (mountTable == 0) {
134             perror("/proc/mounts");
135             exit(FALSE);
136         }
137
138         while ((mountEntry = getmntent(mountTable))) {
139             int status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
140             if (status)
141                 return status;
142         }
143         endmntent(mountTable);
144     }
145
146     return 0;
147 }