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