1 /* Utility routines for Minix tests. 2 * This is designed to be #includ'ed near the top of test programs. It is 3 * self-contained except for max_error. 4 */ 5 6 #include <errno.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <unistd.h> 10 #include <stdarg.h> 11 #include <stdio.h> 12 #include <sys/statvfs.h> 13 #include <sys/syslimits.h> 14 15 #include "common.h" 16 17 int common_test_nr = -1, errct = 0, subtest; 18 int quietflag = 1, bigflag = 0; 19 20 /* provide a default max_error symbol as Max_error with a value 21 * of 5. The test program can override it wit its own max_error 22 * symbol if it wants that this code will then use instead. 23 */ 24 __weak_alias(max_error,Max_error); 25 int Max_error = 5; 26 extern int max_error; 27 28 void start(test_nr) 29 int test_nr; 30 { 31 char buf[64]; 32 int i; 33 34 /* if this variable is set, specify to tests we are running 35 * in 'overnight' mode 36 */ 37 bigflag = !!getenv(BIGVARNAME); 38 39 common_test_nr = test_nr; 40 printf("Test %2d ", test_nr); 41 fflush(stdout); /* since stdout is probably line buffered */ 42 sync(); 43 rm_rf_dir(test_nr); 44 sprintf(buf, "mkdir DIR_%02d", test_nr); 45 if (system(buf) != 0) { 46 e(666); 47 quit(); 48 } 49 sprintf(buf, "DIR_%02d", test_nr); 50 if (chdir(buf) != 0) { 51 e(6666); 52 quit(); 53 } 54 55 for (i = 3; i < OPEN_MAX; ++i) { 56 /* Close all files except stdin, stdout, and stderr */ 57 (void) close(i); 58 } 59 } 60 61 int does_fs_truncate(void) 62 { 63 struct statvfs stvfs; 64 int does_truncate = 0; 65 char cwd[PATH_MAX]; /* Storage for path to current working dir */ 66 67 if (realpath(".", cwd) == NULL) e(7777); /* Get current working dir */ 68 if (statvfs(cwd, &stvfs) != 0) e(7778); /* Get FS information */ 69 /* Depending on how an FS handles too long file names, we have to adjust our 70 * error checking. If an FS does not truncate file names, it should generate 71 * an ENAMETOOLONG error when we provide too long a file name. 72 */ 73 if (!(stvfs.f_flag & ST_NOTRUNC)) does_truncate = 1; 74 75 return(does_truncate); 76 } 77 78 int name_max(char *path) 79 { 80 struct statvfs stvfs; 81 82 if (statvfs(path, &stvfs) != 0) e(7779); 83 return(stvfs.f_namemax); 84 } 85 86 87 void rm_rf_dir(test_nr) 88 int test_nr; 89 { 90 char buf[128]; 91 92 sprintf(buf, "rm -rf DIR_%02d >/dev/null 2>&1", test_nr); 93 if (system(buf) != 0) printf("Warning: system(\"%s\") failed\n", buf); 94 } 95 96 void rm_rf_ppdir(test_nr) 97 int test_nr; 98 { 99 /* Attempt to remove everything in the test directory (== the current dir). */ 100 101 char buf[128]; 102 103 sprintf(buf, "chmod 777 ../DIR_%02d/* ../DIR_%02d/*/* >/dev/null 2>&1", 104 test_nr, test_nr); 105 (void) system(buf); 106 sprintf(buf, "rm -rf ../DIR_%02d >/dev/null 2>&1", test_nr); 107 if (system(buf) != 0) printf("Warning: system(\"%s\") failed\n", buf); 108 } 109 110 void e_f(char *file, int line, int n) 111 { 112 int err_number; 113 err_number = errno; /* Store before printf can clobber it */ 114 if (errct == 0) printf("\n"); /* finish header */ 115 printf("%s:%d: Subtest %d, error %d, errno %d: %s\n", 116 file, line, subtest, n, err_number, strerror(err_number)); 117 if (++errct > max_error) { 118 printf("Too many errors; test aborted\n"); 119 cleanup(); 120 exit(1); 121 } 122 errno = err_number; 123 } 124 125 void cleanup() 126 { 127 if (chdir("..") == 0 && common_test_nr != -1) rm_rf_dir(common_test_nr); 128 } 129 130 void fail_printf(const char *file, const char *func, int line, 131 const char *fmt, ...) { 132 va_list ap; 133 char buf[1024]; 134 size_t len; 135 136 len = snprintf(buf, sizeof(buf), "[%s:%s:%d] ", file, func, line); 137 138 va_start(ap, fmt); 139 len += vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); 140 va_end(ap); 141 142 snprintf(buf + len, sizeof(buf) - len, " errno=%d error=%s", 143 errno, strerror(errno)); 144 145 em(line, buf); 146 } 147 148 void quit() 149 { 150 cleanup(); 151 if (errct == 0) { 152 printf("ok\n"); 153 exit(0); 154 } else { 155 printf("%d errors\n", errct); 156 exit(1); 157 } 158 } 159 160 void 161 printprogress(char *msg, int i, int max) 162 { 163 int use_i = i + 1; 164 static time_t start_time, prev_time; 165 static int prev_i; 166 time_t now; 167 168 if(quietflag) return; 169 170 time(&now); 171 if(prev_i >= i) start_time = now; 172 173 if(now > start_time && prev_time < now) { 174 double i_per_sec = i / (now - start_time); 175 int remain_secs; 176 177 remain_secs = (int)((max-i) / i_per_sec); 178 179 fprintf(stderr, "%-35s %7d/%7d %3d%% ETA %3ds\r", msg, 180 use_i, (max), use_i*100/(max), remain_secs); 181 fflush(stderr); 182 } 183 184 if(use_i >= max) { 185 fprintf(stderr, "%-35s done \n", msg); 186 } 187 188 prev_i = i; 189 prev_time = now; 190 } 191 192 void getmem(uint32_t *total, uint32_t *free, uint32_t *cached) 193 { 194 uint32_t pagesize, largest; 195 FILE *f = fopen("/proc/meminfo", "r"); 196 if(!f) return; 197 if(fscanf(f, "%u %u %u %u %u", &pagesize, total, free, 198 &largest, cached) != 5) { 199 fprintf(stderr, "fscanf of meminfo failed\n"); 200 exit(1); 201 } 202 fclose(f); 203 } 204 205 static int get_setting(const char *name, int def) 206 { 207 const char *value; 208 209 value = getenv(name); 210 if (!value || !*value) return def; 211 if (strcmp(value, "yes") == 0) return 1; 212 if (strcmp(value, "no") == 0) return 0; 213 214 fprintf(stderr, "warning: invalid $%s value: %s\n", name, value); 215 return 0; 216 } 217 218 int get_setting_use_network(void) 219 { 220 /* set $USENETWORK to "yes" or "no" to indicate whether 221 * an internet connection is to be expected; defaults to "no" 222 */ 223 return get_setting("USENETWORK", 0); 224 } 225