]> granicus.if.org Git - sysstat/blob - systest.c
Starting sysstat-12.5.4
[sysstat] / systest.c
1 /*
2  * sysstat test functions.
3  * (C) 2019-2021 by Sebastien GODARD (sysstat <at> orange.fr)
4  *
5  ***************************************************************************
6  * This program is free software; you can redistribute it and/or modify it *
7  * under the terms of the GNU General Public License as published  by  the *
8  * Free Software Foundation; either version 2 of the License, or (at  your *
9  * option) any later version.                                              *
10  *                                                                         *
11  * This program is distributed in the hope that it  will  be  useful,  but *
12  * WITHOUT ANY WARRANTY; without the implied warranty  of  MERCHANTABILITY *
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
14  * for more details.                                                       *
15  *                                                                         *
16  * You should have received a copy of the GNU General Public License along *
17  * with this program; if not, write to the Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA              *
19  ***************************************************************************
20  */
21
22 #ifdef TEST
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <dirent.h>
31 #include <pwd.h>
32 #include <sys/stat.h>
33 #include <sys/utsname.h>
34 #include <sys/statvfs.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37
38 #include "systest.h"
39
40 time_t __unix_time = 0;
41 int __env = 0;
42
43 extern long interval;
44 extern int sigint_caught;
45
46 /*
47  ***************************************************************************
48  * Test mode: Instead of reading system time, use time given on the command
49  * line.
50  *
51  * RETURNS:
52  * Number of seconds since the epoch, as given on the command line.
53  ***************************************************************************
54  */
55 time_t get_unix_time(time_t *t)
56 {
57         return __unix_time;
58 }
59
60 /*
61  ***************************************************************************
62  * Test mode: Get time of the day using __unix_time variable contents.
63  *
64  * OUT:
65  * @tv  Number of seconds since the Epoch.
66  ***************************************************************************
67  */
68 void get_day_time(struct timeval *tv)
69 {
70         __unix_time += interval;
71         tv->tv_sec = __unix_time;
72         tv->tv_usec = 0;
73 }
74
75 /*
76  ***************************************************************************
77  * Test mode: Send bogus information about current kernel.
78  *
79  * OUT:
80  * @h   Structure with kernel information.
81  ***************************************************************************
82  */
83 void get_uname(struct utsname *h)
84 {
85         strcpy(h->sysname, "Linux");
86         strcpy(h->nodename, "SYSSTAT.TEST");
87         strcpy(h->release, "1.2.3-TEST");
88         strcpy(h->machine, "x86_64");
89 }
90
91 /*
92  ***************************************************************************
93  * Test mode: Send bogus information about current filesystem.
94  *
95  * OUT:
96  * @buf Structure with filesystem information.
97  ***************************************************************************
98  */
99 int get_fs_stat(char *c, struct statvfs *buf)
100 {
101         static int p = 0;
102         /*
103          * f_bfree, f_blocks and f_bavail used to be unsigned long.
104          * So don't use values greater then UINT_MAX to make sure that values
105          * won't overflow on 32-bit systems.
106          */
107         unsigned long long bfree[4]  = {739427840, 286670336, 1696156672, 2616732672};
108         unsigned long long blocks[4] = {891291136, 502345216, 1829043712, 3502345216};
109         unsigned long long bavail[4] = {722675712, 241253120, 1106515456, 1871315456};
110         unsigned long long files[4]  = {6111232, 19202048, 1921360, 19202048};
111         unsigned long long ffree[4]  = {6008414, 19201593, 1621550, 19051710};
112
113         buf->f_bfree = bfree[p];
114         buf->f_blocks = blocks[p];
115         buf->f_bavail = bavail[p];
116         buf->f_frsize = 1;
117         buf->f_files = files[p];
118         buf->f_ffree = ffree[p];
119
120         p = (p + 1) & 0x3;
121
122         return 0;
123 }
124
125 /*
126  ***************************************************************************
127  * Test mode: Ignore environment variable value.
128  ***************************************************************************
129  */
130 char *get_env_value(const char *c)
131 {
132         if (!__env)
133                 return NULL;
134
135         fprintf(stderr, "Reading contents of %s\n", c);
136         return getenv(c);
137 }
138
139 /*
140  ***************************************************************************
141  * Test mode: Go to next time period.
142  ***************************************************************************
143  */
144 void next_time_step(void)
145 {
146         int root_nr = 1;
147         char rootf[64], testf[128];
148         char *resolved_name;
149
150         __unix_time += interval;
151
152         if ((resolved_name = realpath(ROOTDIR, NULL)) != NULL) {
153                 if (strlen(resolved_name) > 4) {
154                         root_nr = atoi(resolved_name + strlen(resolved_name) - 1);
155                 }
156                 free(resolved_name);
157         }
158         if ((unlink(ROOTDIR) < 0) && (errno != ENOENT)) {
159                 perror("unlink");
160                 exit(1);
161         }
162
163         snprintf(rootf, sizeof(rootf), "%s%d", ROOTFILE, ++root_nr);
164         rootf[sizeof(rootf) - 1] = '\0';
165         snprintf(testf, sizeof(testf), "%s/%s", TESTDIR, rootf);
166         testf[sizeof(testf) - 1] = '\0';
167
168         if (access(testf, F_OK) < 0) {
169                 if (errno == ENOENT) {
170                         /* No more kernel directories: Simulate a Ctrl/C */
171                         int_handler(0);
172                         return ;
173                 }
174         }
175
176         if (symlink(rootf, ROOTDIR) < 0) {
177                 perror("link");
178                 exit(1);
179         }
180 }
181
182 /*
183  ***************************************************************************
184  * If current file is considered as a virtual one ("virtualhd"), then set
185  * its device ID (major 253, minor 2, corresponding here to dm-2) in the
186  * stat structure normally filled by the stat() system call.
187  * Otherwise, open file and read its major and minor numbers.
188  *
189  * IN:
190  * @name        Pathname to file.
191  *
192  * OUT:
193  * @statbuf     Structure containing device ID.
194  *
195  * RETURNS:
196  * 0 if it actually was the virtual device, 1 otherwise, and -1 on failure.
197  ***************************************************************************
198  */
199 int virtual_stat(const char *name, struct stat *statbuf)
200 {
201         FILE *fp;
202         char line[128];
203         int major, minor;
204
205         if (!strcmp(name, VIRTUALHD)) {
206                 statbuf->st_rdev = (253 << MINORBITS) + 2;
207                 return 0;
208         }
209
210         statbuf->st_rdev = 0;
211
212         if ((fp = fopen(name, "r")) == NULL)
213                 return -1;
214
215         if (fgets(line, sizeof(line), fp) != NULL) {
216                 sscanf(line, "%d %d", &major, &minor);
217                 statbuf->st_rdev = (major << MINORBITS) + minor;
218         }
219
220         fclose(fp);
221
222         return 1;
223 }
224
225 /*
226  ***************************************************************************
227  * Open a "_list" file containing a list of files enumerated in a known
228  * order contained in current directory.
229  *
230  * IN:
231  * @name        Pathname to directory containing the "_list" file.
232  *
233  * RETURNS:
234  * A pointer on current "_list" file.
235  ***************************************************************************
236  */
237 DIR *open_list(const char *name)
238 {
239         FILE *fp;
240         char filename[1024];
241
242         snprintf(filename, sizeof(filename), "%s/%s", name, _LIST);
243         filename[sizeof(filename) - 1] = '\0';
244
245         if ((fp = fopen(filename, "r")) == NULL)
246                 return NULL;
247
248         return (DIR *) fp;
249 }
250
251 /*
252  ***************************************************************************
253  * Read next file name contained in a "_list" file.
254  *
255  * IN:
256  * @dir Pointer on current "_list" file.
257  *
258  * RETURNS:
259  * A structure containing the name of the next file to read.
260  ***************************************************************************
261  */
262 struct dirent *read_list(DIR *dir)
263 {
264         FILE *fp = (FILE *) dir;
265         static struct dirent drd;
266         char line[1024];
267
268
269         if ((fgets(line, sizeof(line), fp) != NULL) && (strlen(line) > 1) &&
270                 (strlen(line) < sizeof(drd.d_name))) {
271                 strcpy(drd.d_name, line);
272                 drd.d_name[strlen(line) - 1] = '\0';
273                 return &drd;
274         }
275
276         return NULL;
277 }
278
279 /*
280  ***************************************************************************
281  * Close a "_list" file.
282  *
283  * IN:
284  * @dir Pointer on "_list" file to close.
285  ***************************************************************************
286  */
287 void close_list(DIR *dir)
288 {
289         FILE *fp = (FILE *) dir;
290
291         fclose(fp);
292 }
293
294 /*
295  ***************************************************************************
296  * Replacement function for realpath() system call. Do nothing here.
297  *
298  * IN:
299  * @name        Pathname to process.
300  * @c           Unused here.
301  *
302  * RETURNS:
303  * Pathname (unchanged).
304  ***************************************************************************
305  */
306 char *get_realname(char *name, char *c)
307 {
308         char *resolved_name;
309
310         if ((resolved_name = (char *) malloc(1024)) == NULL) {
311                 perror("malloc");
312                 exit(4);
313         }
314         strncpy(resolved_name, name, 1024);
315         resolved_name[1023] = '\0';
316
317         return resolved_name;
318 }
319
320 /*
321  ***************************************************************************
322  * Replacement function for getpwuid() system call. Fill a dummy passwd
323  * structure containing the name of a user.
324  *
325  * IN:
326  * @uid         UID of the user
327  *
328  * RETURNS:
329  * Pointer on the passwd structure.
330  ***************************************************************************
331  */
332 struct passwd *get_usrname(uid_t uid)
333 {
334         static struct passwd pwd_ent;
335         static char pw_name[16];
336
337         pwd_ent.pw_name = pw_name;
338         if (!uid) {
339                 strcpy(pwd_ent.pw_name, "root");
340         }
341         else {
342                 strcpy(pwd_ent.pw_name, "testusr");
343         }
344
345         return &pwd_ent;
346 }
347
348 /*
349  ***************************************************************************
350  * Replacement function for fork() system call. Don't fork really but return
351  * a known PID number.
352  *
353  * RETURNS:
354  * Known PID number.
355  ***************************************************************************
356  */
357 pid_t get_known_pid(void)
358 {
359         return 8741;
360 }
361
362 #endif  /* TEST */
363