1 /* Tests for statvfs(2) call family */
2 #include <sys/statvfs.h>
16 int do_getvfsstat(struct statvfs
*buf
, size_t bufsz
, int flags
, int count
);
17 void compare_statvfs(struct statvfs
*st1
, struct statvfs
*st2
);
22 char filename
[] = "statvfs_test_XXXXXX";
24 static void create_file(void)
28 ssize_t ntowrite
, nwritten
;
32 if ((fd
= mkstemp(filename
)) < 0) e(1);
36 while (ntowrite
> 0) {
37 if ((nwritten
= write(fd
, p
, ntowrite
)) < 0) e(2);
42 if (close(fd
) < 0) e(3);
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
;
62 if (statvfs(".", &stats
) < 0) e(1);
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
;
78 if (statvfs(".", &stats
) < 0) e(2);
79 if (unlink(filename
) < 0) e(3);
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
;
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
))) {
108 int do_getvfsstat(struct statvfs
*buf
, size_t bufsz
, int flags
, int count
)
112 if (getvfsstat(buf
, bufsz
, flags
) != count
) e(101);
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);
123 /* Expect one root file system. */
125 for (i
= 0; i
< count
; i
++) {
126 if (!strcmp(buf
[i
].f_mntonname
, "/")) {
136 void compare_statvfs(struct statvfs
*st1
, struct statvfs
*st2
)
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.
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);
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);
154 if (st1
->f_namemax
!= st2
->f_namemax
) e(207);
155 if (st1
->f_owner
!= st2
->f_owner
) e(208);
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);
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);
172 static struct statvfs buf
[FSMAX
];
173 struct statvfs rootbuf
;
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);
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);
188 /* We assume that nothing is being un/mounted right now. */
189 root
= do_getvfsstat(buf
, sizeof(buf
), ST_WAIT
, count
);
191 /* Compare cached and uncached copies. */
192 if (statvfs1("/", &rootbuf
, ST_NOWAIT
) != 0) e(13);
193 compare_statvfs(&buf
[root
], &rootbuf
);
195 /* Do the same again, but now the other way around. */
197 root
= do_getvfsstat(buf
, sizeof(buf
), ST_NOWAIT
, count
);
198 compare_statvfs(&buf
[root
], &rootbuf
);
201 int main(int argc
, char **argv
)
207 for(i
= 0; i
< TRIALS
; i
++) {