]> granicus.if.org Git - sysstat/blobdiff - systest.c
sadf: Display timezone for all output formats
[sysstat] / systest.c
index bfb44f1ea401b84b9de5902d22e0ba40d9feebe1..618c4a93715d3c4f0c9c714734b558d1b9ed609b 100644 (file)
--- a/systest.c
+++ b/systest.c
@@ -1,6 +1,6 @@
 /*
  * sysstat test functions.
- * (C) 2019 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 2019-2022 by Sebastien GODARD (sysstat <at> orange.fr)
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
+#include <dirent.h>
+#include <pwd.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <sys/statvfs.h>
+#include <sys/time.h>
+#include <sys/types.h>
 
 #include "systest.h"
 
 time_t __unix_time = 0;
+int __env = 0;
+
 extern long interval;
 extern int sigint_caught;
 
@@ -42,13 +48,28 @@ 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:
- * @t  Number of seconds since the epoch, as given on the command line.
+ * @tv Number of seconds since the Epoch.
  ***************************************************************************
  */
-void get_unix_time(time_t *t)
+void get_day_time(struct timeval *tv)
 {
-       *t = __unix_time;
+       __unix_time += interval;
+       tv->tv_sec = __unix_time;
+       tv->tv_usec = 0;
 }
 
 /*
@@ -78,11 +99,16 @@ void get_uname(struct utsname *h)
 int get_fs_stat(char *c, struct statvfs *buf)
 {
        static int p = 0;
-       unsigned long long bfree[4] = {89739427840, 293286670336, 11696156672, 292616732672};
-       unsigned long long blocks[4] = {97891291136, 309502345216, 30829043712, 309502345216};
-       unsigned long long bavail[4] = {84722675712, 277541253120, 10106515456, 276871315456};
-       unsigned long long files[4] = {6111232, 19202048, 1921360, 19202048};
-       unsigned long long ffree[4] = {6008414, 19201593, 1621550, 19051710};
+       /*
+        * 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];
@@ -91,7 +117,7 @@ int get_fs_stat(char *c, struct statvfs *buf)
        buf->f_files = files[p];
        buf->f_ffree = ffree[p];
 
-       p = (p + 1) & 0x11;
+       p = (p + 1) & 0x3;
 
        return 0;
 }
@@ -101,9 +127,13 @@ int get_fs_stat(char *c, struct statvfs *buf)
  * Test mode: Ignore environment variable value.
  ***************************************************************************
  */
-char *get_env_value(char *c)
+char *get_env_value(const char *c)
 {
-       return NULL;
+       if (!__env)
+               return NULL;
+
+       fprintf(stderr, "Reading contents of %s\n", c);
+       return getenv(c);
 }
 
 /*
@@ -113,26 +143,41 @@ char *get_env_value(char *c)
  */
 void next_time_step(void)
 {
-       static int root_nr = 1;
-       char rootf[64], testf[64];
+       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);
        }
 
-       sprintf(rootf, "%s%d", ROOTFILE, ++root_nr);
-       sprintf(testf, "%s/%s", TESTDIR, rootf);
+       /* 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 kernel directories: Simulate a Ctrl/C */
+               if (errno == ENOENT) {
+                       /* No more root directories: Simulate a Ctrl/C */
                        int_handler(0);
-                       return ;
+                       return;
                }
        }
 
+       /* Create "root" symlink pointing at the new root directory */
        if (symlink(rootf, ROOTDIR) < 0) {
                perror("link");
                exit(1);
@@ -144,6 +189,7 @@ void next_time_step(void)
  * 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.
@@ -152,18 +198,171 @@ void next_time_step(void)
  * @statbuf    Structure containing device ID.
  *
  * RETURNS:
- * 0 if it actually was the virtual device, 1 otherwise.
+ * 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 << 8) + 2;
+               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 */