/* * sysstat test functions. * (C) 2019-2022 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation; either version 2 of the License, or (at your * * option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * * for more details. * * * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA * *************************************************************************** */ #ifdef TEST #include #include #include #include #include #include #include #include #include #include #include #include #include #include "systest.h" time_t __unix_time = 0; int __env = 0; extern long interval; extern int sigint_caught; /* *************************************************************************** * Test mode: Instead of reading system time, use time given on the command * line. * * RETURNS: * Number of seconds since the epoch, as given on the command line. *************************************************************************** */ time_t get_unix_time(time_t *t) { return __unix_time; } /* *************************************************************************** * Test mode: Get time of the day using __unix_time variable contents. * * OUT: * @tv Number of seconds since the Epoch. *************************************************************************** */ void get_day_time(struct timeval *tv) { __unix_time += interval; tv->tv_sec = __unix_time; tv->tv_usec = 0; } /* *************************************************************************** * Test mode: Send bogus information about current kernel. * * OUT: * @h Structure with kernel information. *************************************************************************** */ void get_uname(struct utsname *h) { strcpy(h->sysname, "Linux"); strcpy(h->nodename, "SYSSTAT.TEST"); strcpy(h->release, "1.2.3-TEST"); strcpy(h->machine, "x86_64"); } /* *************************************************************************** * Test mode: Send bogus information about current filesystem. * * OUT: * @buf Structure with filesystem information. *************************************************************************** */ int get_fs_stat(char *c, struct statvfs *buf) { static int p = 0; /* * f_bfree, f_blocks and f_bavail used to be unsigned long. * So don't use values greater then UINT_MAX to make sure that values * won't overflow on 32-bit systems. */ unsigned long long bfree[4] = {739427840, 286670336, 1696156672, 2616732672}; unsigned long long blocks[4] = {891291136, 502345216, 1829043712, 3502345216}; unsigned long long bavail[4] = {722675712, 241253120, 1106515456, 1871315456}; unsigned long long files[4] = {6111232, 19202048, 1921360, 19202048}; unsigned long long ffree[4] = {6008414, 19201593, 1621550, 19051710}; buf->f_bfree = bfree[p]; buf->f_blocks = blocks[p]; buf->f_bavail = bavail[p]; buf->f_frsize = 1; buf->f_files = files[p]; buf->f_ffree = ffree[p]; p = (p + 1) & 0x3; return 0; } /* *************************************************************************** * Test mode: Ignore environment variable value. *************************************************************************** */ char *get_env_value(const char *c) { if (!__env) return NULL; fprintf(stderr, "Reading contents of %s\n", c); return getenv(c); } /* *************************************************************************** * Test mode: Go to next time period. *************************************************************************** */ void next_time_step(void) { int root_nr = 1; char rootf[64], testf[128]; char *resolved_name; __unix_time += interval; /* Get root directory name (root1, root2, etc.) at which the "root" symlink points */ if ((resolved_name = realpath(ROOTDIR, NULL)) != NULL) { if (strlen(resolved_name) > 4) { /* Set root_nr to the root directory number (1, 2, etc.) */ root_nr = atoi(resolved_name + strlen(resolved_name) - 1); } free(resolved_name); } if ((unlink(ROOTDIR) < 0) && (errno != ENOENT)) { perror("unlink"); exit(1); } /* Set next root directory name (root2, root3, etc.). Directories like root1b are unreachable */ snprintf(rootf, sizeof(rootf), "%s%d", ROOTFILE, ++root_nr); rootf[sizeof(rootf) - 1] = '\0'; snprintf(testf, sizeof(testf), "%s/%s", TESTDIR, rootf); testf[sizeof(testf) - 1] = '\0'; /* Make sure that new root directory exists */ if (access(testf, F_OK) < 0) { if (errno == ENOENT) { /* No more root directories: Simulate a Ctrl/C */ int_handler(0); return; } } /* Create "root" symlink pointing at the new root directory */ if (symlink(rootf, ROOTDIR) < 0) { perror("link"); exit(1); } } /* *************************************************************************** * If current file is considered as a virtual one ("virtualhd"), then set * its device ID (major 253, minor 2, corresponding here to dm-2) in the * stat structure normally filled by the stat() system call. * Otherwise, open file and read its major and minor numbers. * * IN: * @name Pathname to file. * * OUT: * @statbuf Structure containing device ID. * * RETURNS: * 0 if it actually was the virtual device, 1 otherwise, and -1 on failure. *************************************************************************** */ int virtual_stat(const char *name, struct stat *statbuf) { FILE *fp; char line[128]; int major, minor; if (!strcmp(name, VIRTUALHD)) { statbuf->st_rdev = (253 << MINORBITS) + 2; return 0; } statbuf->st_rdev = 0; if ((fp = fopen(name, "r")) == NULL) return -1; if (fgets(line, sizeof(line), fp) != NULL) { sscanf(line, "%d %d", &major, &minor); statbuf->st_rdev = (major << MINORBITS) + minor; } fclose(fp); return 1; } /* *************************************************************************** * Open a "_list" file containing a list of files enumerated in a known * order contained in current directory. * * IN: * @name Pathname to directory containing the "_list" file. * * RETURNS: * A pointer on current "_list" file. *************************************************************************** */ DIR *open_list(const char *name) { FILE *fp; char filename[1024]; snprintf(filename, sizeof(filename), "%s/%s", name, _LIST); filename[sizeof(filename) - 1] = '\0'; if ((fp = fopen(filename, "r")) == NULL) return NULL; return (DIR *) fp; } /* *************************************************************************** * Read next file name contained in a "_list" file. * * IN: * @dir Pointer on current "_list" file. * * RETURNS: * A structure containing the name of the next file to read. *************************************************************************** */ struct dirent *read_list(DIR *dir) { FILE *fp = (FILE *) dir; static struct dirent drd; char line[1024]; if ((fgets(line, sizeof(line), fp) != NULL) && (strlen(line) > 1) && (strlen(line) < sizeof(drd.d_name))) { strcpy(drd.d_name, line); drd.d_name[strlen(line) - 1] = '\0'; return &drd; } return NULL; } /* *************************************************************************** * Close a "_list" file. * * IN: * @dir Pointer on "_list" file to close. *************************************************************************** */ void close_list(DIR *dir) { FILE *fp = (FILE *) dir; fclose(fp); } /* *************************************************************************** * Replacement function for realpath() system call. Do nothing here. * * IN: * @name Pathname to process. * @c Unused here. * * RETURNS: * Pathname (unchanged). *************************************************************************** */ char *get_realname(char *name, char *c) { char *resolved_name; if ((resolved_name = (char *) malloc(1024)) == NULL) { perror("malloc"); exit(4); } strncpy(resolved_name, name, 1024); resolved_name[1023] = '\0'; return resolved_name; } /* *************************************************************************** * Replacement function for getpwuid() system call. Fill a dummy passwd * structure containing the name of a user. * * IN: * @uid UID of the user * * RETURNS: * Pointer on the passwd structure. *************************************************************************** */ struct passwd *get_usrname(uid_t uid) { static struct passwd pwd_ent; static char pw_name[16]; pwd_ent.pw_name = pw_name; if (!uid) { strcpy(pwd_ent.pw_name, "root"); } else { strcpy(pwd_ent.pw_name, "testusr"); } return &pwd_ent; } /* *************************************************************************** * Replacement function for fork() system call. Don't fork really but return * a known PID number. * * RETURNS: * Known PID number. *************************************************************************** */ pid_t get_known_pid(void) { return 8741; } #endif /* TEST */