1*433d6423SLionel Sambuc /* Tests for statvfs(2) call family */
2*433d6423SLionel Sambuc #include <sys/statvfs.h>
3*433d6423SLionel Sambuc #include <stdlib.h>
4*433d6423SLionel Sambuc #include <stdio.h>
5*433d6423SLionel Sambuc #include <assert.h>
6*433d6423SLionel Sambuc #include <fcntl.h>
7*433d6423SLionel Sambuc #include <err.h>
8*433d6423SLionel Sambuc #include <unistd.h>
9*433d6423SLionel Sambuc #define TRIALS 10
10*433d6423SLionel Sambuc #define SIZE 65536
11*433d6423SLionel Sambuc #define FSMAX 64
12*433d6423SLionel Sambuc
13*433d6423SLionel Sambuc int max_error = 3;
14*433d6423SLionel Sambuc #include "common.h"
15*433d6423SLionel Sambuc
16*433d6423SLionel Sambuc int do_getvfsstat(struct statvfs *buf, size_t bufsz, int flags, int count);
17*433d6423SLionel Sambuc void compare_statvfs(struct statvfs *st1, struct statvfs *st2);
18*433d6423SLionel Sambuc void test55a(void);
19*433d6423SLionel Sambuc void test55b(void);
20*433d6423SLionel Sambuc
21*433d6423SLionel Sambuc int subtest;
22*433d6423SLionel Sambuc char filename[] = "statvfs_test_XXXXXX";
23*433d6423SLionel Sambuc
create_file(void)24*433d6423SLionel Sambuc static void create_file(void)
25*433d6423SLionel Sambuc {
26*433d6423SLionel Sambuc char buf[SIZE]={0};
27*433d6423SLionel Sambuc char *p;
28*433d6423SLionel Sambuc ssize_t ntowrite, nwritten;
29*433d6423SLionel Sambuc int fd;
30*433d6423SLionel Sambuc
31*433d6423SLionel Sambuc subtest = 2;
32*433d6423SLionel Sambuc if ((fd = mkstemp(filename)) < 0) e(1);
33*433d6423SLionel Sambuc
34*433d6423SLionel Sambuc ntowrite = SIZE;
35*433d6423SLionel Sambuc p = &buf[0];
36*433d6423SLionel Sambuc while (ntowrite > 0) {
37*433d6423SLionel Sambuc if ((nwritten = write(fd, p, ntowrite)) < 0) e(2);
38*433d6423SLionel Sambuc p += nwritten;
39*433d6423SLionel Sambuc ntowrite -= nwritten;
40*433d6423SLionel Sambuc }
41*433d6423SLionel Sambuc
42*433d6423SLionel Sambuc if (close(fd) < 0) e(3);
43*433d6423SLionel Sambuc }
44*433d6423SLionel Sambuc
test55a(void)45*433d6423SLionel Sambuc void test55a(void)
46*433d6423SLionel Sambuc {
47*433d6423SLionel Sambuc struct statvfs stats;
48*433d6423SLionel Sambuc unsigned long f_bsize, f_bsize_new;
49*433d6423SLionel Sambuc unsigned long f_frsize, f_frsize_new;
50*433d6423SLionel Sambuc fsblkcnt_t f_blocks, f_blocks_new;
51*433d6423SLionel Sambuc fsblkcnt_t f_bfree, f_bfree_new;
52*433d6423SLionel Sambuc fsblkcnt_t f_bavail, f_bavail_new;
53*433d6423SLionel Sambuc fsfilcnt_t f_files, f_files_new;
54*433d6423SLionel Sambuc fsfilcnt_t f_ffree, f_ffree_new;
55*433d6423SLionel Sambuc fsfilcnt_t f_favail, f_favail_new;
56*433d6423SLionel Sambuc unsigned long f_fsid, f_fsid_new;
57*433d6423SLionel Sambuc unsigned long f_flag, f_flag_new;
58*433d6423SLionel Sambuc unsigned long f_namemax, f_namemax_new;
59*433d6423SLionel Sambuc
60*433d6423SLionel Sambuc subtest = 1;
61*433d6423SLionel Sambuc
62*433d6423SLionel Sambuc if (statvfs(".", &stats) < 0) e(1);
63*433d6423SLionel Sambuc
64*433d6423SLionel Sambuc f_bsize = stats.f_bsize ;
65*433d6423SLionel Sambuc f_frsize = stats.f_frsize ;
66*433d6423SLionel Sambuc f_blocks = stats.f_blocks ;
67*433d6423SLionel Sambuc f_bfree = stats.f_bfree ;
68*433d6423SLionel Sambuc f_bavail = stats.f_bavail ;
69*433d6423SLionel Sambuc f_files = stats.f_files ;
70*433d6423SLionel Sambuc f_ffree = stats.f_ffree ;
71*433d6423SLionel Sambuc f_favail = stats.f_favail ;
72*433d6423SLionel Sambuc f_fsid = stats.f_fsid ;
73*433d6423SLionel Sambuc f_flag = stats.f_flag ;
74*433d6423SLionel Sambuc f_namemax = stats.f_namemax;
75*433d6423SLionel Sambuc
76*433d6423SLionel Sambuc create_file();
77*433d6423SLionel Sambuc
78*433d6423SLionel Sambuc if (statvfs(".", &stats) < 0) e(2);
79*433d6423SLionel Sambuc if (unlink(filename) < 0) e(3);
80*433d6423SLionel Sambuc
81*433d6423SLionel Sambuc f_bsize_new = stats.f_bsize ;
82*433d6423SLionel Sambuc f_frsize_new = stats.f_frsize ;
83*433d6423SLionel Sambuc f_blocks_new = stats.f_blocks ;
84*433d6423SLionel Sambuc f_bfree_new = stats.f_bfree ;
85*433d6423SLionel Sambuc f_bavail_new = stats.f_bavail ;
86*433d6423SLionel Sambuc f_files_new = stats.f_files ;
87*433d6423SLionel Sambuc f_ffree_new = stats.f_ffree ;
88*433d6423SLionel Sambuc f_favail_new = stats.f_favail ;
89*433d6423SLionel Sambuc f_fsid_new = stats.f_fsid ;
90*433d6423SLionel Sambuc f_flag_new = stats.f_flag ;
91*433d6423SLionel Sambuc f_namemax_new = stats.f_namemax;
92*433d6423SLionel Sambuc
93*433d6423SLionel Sambuc if (!((f_bsize == f_bsize_new) &&
94*433d6423SLionel Sambuc (f_frsize == f_frsize_new) &&
95*433d6423SLionel Sambuc (f_blocks == f_blocks_new) &&
96*433d6423SLionel Sambuc (f_bfree > f_bfree_new) &&
97*433d6423SLionel Sambuc (f_bavail > f_bavail_new) &&
98*433d6423SLionel Sambuc (f_files == f_files_new) &&
99*433d6423SLionel Sambuc (f_ffree == f_ffree_new + 1) &&
100*433d6423SLionel Sambuc (f_favail == f_favail_new + 1) &&
101*433d6423SLionel Sambuc (f_fsid == f_fsid_new) &&
102*433d6423SLionel Sambuc (f_flag == f_flag_new) &&
103*433d6423SLionel Sambuc (f_namemax == f_namemax_new))) {
104*433d6423SLionel Sambuc e(4);
105*433d6423SLionel Sambuc }
106*433d6423SLionel Sambuc }
107*433d6423SLionel Sambuc
do_getvfsstat(struct statvfs * buf,size_t bufsz,int flags,int count)108*433d6423SLionel Sambuc int do_getvfsstat(struct statvfs *buf, size_t bufsz, int flags, int count)
109*433d6423SLionel Sambuc {
110*433d6423SLionel Sambuc int i, j;
111*433d6423SLionel Sambuc
112*433d6423SLionel Sambuc if (getvfsstat(buf, bufsz, flags) != count) e(101);
113*433d6423SLionel Sambuc
114*433d6423SLionel Sambuc /* All file system identifiers should be unique. */
115*433d6423SLionel Sambuc for (i = 0; i < count - 1; i++) {
116*433d6423SLionel Sambuc for (j = i + 1; j < count; j++) {
117*433d6423SLionel Sambuc if (buf[i].f_fsid == buf[j].f_fsid) e(102);
118*433d6423SLionel Sambuc if (!memcmp(&buf[i].f_fsidx, &buf[j].f_fsidx,
119*433d6423SLionel Sambuc sizeof(buf[j].f_fsidx))) e(103);
120*433d6423SLionel Sambuc }
121*433d6423SLionel Sambuc }
122*433d6423SLionel Sambuc
123*433d6423SLionel Sambuc /* Expect one root file system. */
124*433d6423SLionel Sambuc j = -1;
125*433d6423SLionel Sambuc for (i = 0; i < count; i++) {
126*433d6423SLionel Sambuc if (!strcmp(buf[i].f_mntonname, "/")) {
127*433d6423SLionel Sambuc if (j != -1) e(104);
128*433d6423SLionel Sambuc j = i;
129*433d6423SLionel Sambuc }
130*433d6423SLionel Sambuc }
131*433d6423SLionel Sambuc if (j == -1) e(105);
132*433d6423SLionel Sambuc
133*433d6423SLionel Sambuc return j;
134*433d6423SLionel Sambuc }
135*433d6423SLionel Sambuc
compare_statvfs(struct statvfs * st1,struct statvfs * st2)136*433d6423SLionel Sambuc void compare_statvfs(struct statvfs *st1, struct statvfs *st2)
137*433d6423SLionel Sambuc {
138*433d6423SLionel Sambuc int i;
139*433d6423SLionel Sambuc
140*433d6423SLionel Sambuc /* The structures should basically be identical, but a background
141*433d6423SLionel Sambuc * process calling statvfs for some reason might screw things up.
142*433d6423SLionel Sambuc * Thus, we only compare fields that we know should be identical.
143*433d6423SLionel Sambuc * For the strings, we use memcmp rather than strcmp to ensure that
144*433d6423SLionel Sambuc * no garbage is left in the fields.
145*433d6423SLionel Sambuc */
146*433d6423SLionel Sambuc if (st1->f_flag != st2->f_flag) e(201);
147*433d6423SLionel Sambuc if (st1->f_bsize != st2->f_bsize) e(202);
148*433d6423SLionel Sambuc if (st1->f_frsize != st2->f_frsize) e(203);
149*433d6423SLionel Sambuc if (st1->f_iosize != st2->f_iosize) e(204);
150*433d6423SLionel Sambuc
151*433d6423SLionel Sambuc if (st1->f_fsid != st2->f_fsid) e(205);
152*433d6423SLionel Sambuc if (memcmp(&st1->f_fsidx, &st2->f_fsidx, sizeof(st1->f_fsidx))) e(206);
153*433d6423SLionel Sambuc
154*433d6423SLionel Sambuc if (st1->f_namemax != st2->f_namemax) e(207);
155*433d6423SLionel Sambuc if (st1->f_owner != st2->f_owner) e(208);
156*433d6423SLionel Sambuc
157*433d6423SLionel Sambuc for (i = 0; i < sizeof(st1->f_spare) / sizeof(st1->f_spare[0]); i++) {
158*433d6423SLionel Sambuc if (st1->f_spare[i] != 0) e(209);
159*433d6423SLionel Sambuc if (st2->f_spare[i] != 0) e(210);
160*433d6423SLionel Sambuc }
161*433d6423SLionel Sambuc
162*433d6423SLionel Sambuc if (memcmp(st1->f_fstypename, st2->f_fstypename,
163*433d6423SLionel Sambuc sizeof(st1->f_fstypename))) e(211);
164*433d6423SLionel Sambuc if (memcmp(st1->f_mntonname, st2->f_mntonname,
165*433d6423SLionel Sambuc sizeof(st1->f_mntonname))) e(212);
166*433d6423SLionel Sambuc if (memcmp(st1->f_mntfromname, st2->f_mntfromname,
167*433d6423SLionel Sambuc sizeof(st1->f_mntfromname))) e(213);
168*433d6423SLionel Sambuc }
169*433d6423SLionel Sambuc
test55b(void)170*433d6423SLionel Sambuc void test55b(void)
171*433d6423SLionel Sambuc {
172*433d6423SLionel Sambuc static struct statvfs buf[FSMAX];
173*433d6423SLionel Sambuc struct statvfs rootbuf;
174*433d6423SLionel Sambuc int count, root;
175*433d6423SLionel Sambuc
176*433d6423SLionel Sambuc subtest = 2;
177*433d6423SLionel Sambuc
178*433d6423SLionel Sambuc count = getvfsstat(NULL, 0, ST_WAIT);
179*433d6423SLionel Sambuc if (count < 2) e(1); /* we have at least the root FS and ProcFS */
180*433d6423SLionel Sambuc if (count > FSMAX) e(2);
181*433d6423SLionel Sambuc
182*433d6423SLionel Sambuc if (getvfsstat(buf, 0, ST_WAIT) != 0) e(3);
183*433d6423SLionel Sambuc if (getvfsstat(buf, sizeof(buf[0]) - 1, ST_WAIT) != 0) e(4);
184*433d6423SLionel Sambuc if (getvfsstat(buf, sizeof(buf[0]), ST_WAIT) != 1) e(5);
185*433d6423SLionel Sambuc if (getvfsstat(buf, sizeof(buf[0]) + 1, ST_WAIT) != 1) e(6);
186*433d6423SLionel Sambuc if (getvfsstat(buf, sizeof(buf[0]) * 2, ST_WAIT) != 2) e(7);
187*433d6423SLionel Sambuc
188*433d6423SLionel Sambuc /* We assume that nothing is being un/mounted right now. */
189*433d6423SLionel Sambuc root = do_getvfsstat(buf, sizeof(buf), ST_WAIT, count);
190*433d6423SLionel Sambuc
191*433d6423SLionel Sambuc /* Compare cached and uncached copies. */
192*433d6423SLionel Sambuc if (statvfs1("/", &rootbuf, ST_NOWAIT) != 0) e(13);
193*433d6423SLionel Sambuc compare_statvfs(&buf[root], &rootbuf);
194*433d6423SLionel Sambuc
195*433d6423SLionel Sambuc /* Do the same again, but now the other way around. */
196*433d6423SLionel Sambuc rootbuf = buf[root];
197*433d6423SLionel Sambuc root = do_getvfsstat(buf, sizeof(buf), ST_NOWAIT, count);
198*433d6423SLionel Sambuc compare_statvfs(&buf[root], &rootbuf);
199*433d6423SLionel Sambuc }
200*433d6423SLionel Sambuc
main(int argc,char ** argv)201*433d6423SLionel Sambuc int main(int argc, char **argv)
202*433d6423SLionel Sambuc {
203*433d6423SLionel Sambuc int i;
204*433d6423SLionel Sambuc
205*433d6423SLionel Sambuc start(55);
206*433d6423SLionel Sambuc
207*433d6423SLionel Sambuc for(i = 0; i < TRIALS; i++) {
208*433d6423SLionel Sambuc test55a();
209*433d6423SLionel Sambuc test55b();
210*433d6423SLionel Sambuc }
211*433d6423SLionel Sambuc
212*433d6423SLionel Sambuc quit();
213*433d6423SLionel Sambuc return(-1);
214*433d6423SLionel Sambuc }
215