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