From 726ac243f051f0daee6149db66ac21ba621fb454 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 15 Mar 2007 08:45:19 -0500 Subject: Add fs-tests from Adrian Hunter Signed-off-by: Adrian Hunter Signed-off-by: Josh Boyer --- tests/fs-tests/utils/Makefile | 19 +++ tests/fs-tests/utils/free_space.c | 56 +++++++ tests/fs-tests/utils/fstest_monitor.c | 281 ++++++++++++++++++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 tests/fs-tests/utils/Makefile create mode 100644 tests/fs-tests/utils/free_space.c create mode 100644 tests/fs-tests/utils/fstest_monitor.c (limited to 'tests/fs-tests/utils') diff --git a/tests/fs-tests/utils/Makefile b/tests/fs-tests/utils/Makefile new file mode 100644 index 0000000..9fb60b5 --- /dev/null +++ b/tests/fs-tests/utils/Makefile @@ -0,0 +1,19 @@ + +ifeq ($(origin CC),default) +CC = gcc +endif + +CFLAGS := $(CFLAGS) -Wall -g -O2 -I../lib + +LDFLAGS := $(LDFLAGS) + +TARGETS = fstest_monitor free_space + +all: $(TARGETS) + +clean: + rm -f *.o $(TARGETS) + +tests: all + ./fstest_monitor + ./free_space > /dev/null diff --git a/tests/fs-tests/utils/free_space.c b/tests/fs-tests/utils/free_space.c new file mode 100644 index 0000000..88036aa --- /dev/null +++ b/tests/fs-tests/utils/free_space.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + char *dir_name = "."; + uint64_t free_space; + struct statvfs fs_info; + + if (argc > 1) { + if (strncmp(argv[1], "--help", 6) == 0 || + strncmp(argv[1], "-h", 2) == 0) { + printf( "Usage is: " + "free_space [directory]\n" + "\n" + "Display the free space of the file system " + "of the directory given\n" + "or the current directory if no " + "directory is given.\nThe value output is " + "in bytes.\n" + ); + return 1; + } + dir_name = argv[1]; + } + if (statvfs(dir_name, &fs_info) == -1) + return 1; + + free_space = (uint64_t) fs_info.f_bavail * (uint64_t) fs_info.f_frsize; + + printf("%llu\n", (unsigned long long) free_space); + + return 0; +} diff --git a/tests/fs-tests/utils/fstest_monitor.c b/tests/fs-tests/utils/fstest_monitor.c new file mode 100644 index 0000000..298ee26 --- /dev/null +++ b/tests/fs-tests/utils/fstest_monitor.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct child_info { + struct child_info *next; + pid_t pid; + int terminated; + int killed; + int gone; +}; + +struct child_info *children = 0; + +void kill_children(void) +{ + struct child_info *child; + + child = children; + while (child) { + if (!child->gone) { + if (!child->terminated) { + child->terminated = 1; + kill(child->pid, SIGTERM); + } /*else if (!child->killed) { + child->killed = 1; + kill(child->pid, SIGKILL); + }*/ + } + child = child->next; + } +} + +void add_child(pid_t child_pid) +{ + struct child_info *child; + size_t sz; + + sz = sizeof(struct child_info); + child = (struct child_info *) malloc(sz); + memset(child, 0, sz); + child->pid = child_pid; + child->next = children; + children = child; +} + +void mark_child_gone(pid_t child_pid) +{ + struct child_info *child; + + child = children; + while (child) { + if (child->pid == child_pid) { + child->gone = 1; + break; + } + child = child->next; + } +} + +int have_children(void) +{ + struct child_info *child; + + child = children; + while (child) { + if (!child->gone) + return 1; + child = child->next; + } + return 0; +} + +int parse_command_line(char *cmdline, int *pargc, char ***pargv) +{ + char **tmp; + char *p, *v, *q; + size_t sz; + int argc = 0; + int state = 0; + char *argv[1024]; + + if (!cmdline) + return 1; + q = v = (char *) malloc(strlen(cmdline) + 1024); + if (!v) + return 1; + p = cmdline; + for (;;) { + char c = *p++; + if (!c) { + *v++ = 0; + break; + } + switch (state) { + case 0: /* Between args */ + if (isspace(c)) + break; + argv[argc++] = v; + if (c == '"') { + state = 2; + break; + } else if (c == '\'') { + state = 3; + break; + } + state = 1; + case 1: /* Not quoted */ + if (c == '\\') { + if (*p) + *v++ = *p; + } else if (isspace(c)) { + *v++ = 0; + state = 0; + } else + *v++ = c; + break; + case 2: /* Double quoted */ + if (c == '\\' && *p == '"') { + *v++ = '"'; + ++p; + } else if (c == '"') { + *v++ = 0; + state = 0; + } else + *v++ = c; + break; + case 3: /* Single quoted */ + if (c == '\'') { + *v++ = 0; + state = 0; + } else + *v++ = c; + break; + } + } + argv[argc] = 0; + sz = sizeof(char *) * (argc + 1); + tmp = (char **) malloc(sz); + if (!tmp) { + free(q); + return 1; + } + if (argc == 0) + free(q); + memcpy(tmp, argv, sz); + *pargc = argc; + *pargv = tmp; + return 0; +} + +void signal_handler(int signum) +{ + kill_children(); +} + +int result = 0; +int alarm_gone_off = 0; + +void alarm_handler(int signum) +{ + if (!result) + alarm_gone_off = 1; + kill_children(); +} + +int main(int argc, char *argv[], char **env) +{ + int p; + pid_t child_pid; + int status; + int duration = 0; + + p = 1; + if (argc > 1) { + if (strncmp(argv[p], "--help", 6) == 0 || + strncmp(argv[p], "-h", 2) == 0) { + printf( "Usage is: " + "fstest_monitor options programs...\n" + " Options are:\n" + " -h, --help " + "This help message\n" + " -d, --duration arg " + "Stop after arg seconds\n" + "\n" + "Run programs and wait for them." + " If duration is specified,\n" + "kill all programs" + " after that number of seconds have elapsed.\n" + "Example: " + "fstest_monitor \"/bin/ls -l\" /bin/date\n" + ); + return 1; + } + if (strncmp(argv[p], "--duration", 10) == 0 || + strncmp(argv[p], "-d", 2) == 0) { + char *s; + if (p+1 < argc && !isdigit(argv[p][strlen(argv[p])-1])) + ++p; + s = argv[p]; + while (*s && !isdigit(*s)) + ++s; + duration = atoi(s); + ++p; + } + } + + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + for (; p < argc; ++p) { + child_pid = fork(); + if (child_pid) { + /* Parent */ + if (child_pid == (pid_t) -1) { + kill_children(); + result = 1; + break; + } + add_child(child_pid); + } else { + /* Child */ + int cargc; + char **cargv; + + if (parse_command_line(argv[p], &cargc, &cargv)) + return 1; + execve(cargv[0], cargv, env); + return 1; + } + } + if (!result && duration > 0) { + signal(SIGALRM, alarm_handler); + alarm(duration); + } + while (have_children()) { + status = 0; + child_pid = wait(&status); + if (child_pid == (pid_t) -1) { + if (errno == EINTR) + continue; + kill_children(); + return 1; + } + mark_child_gone(child_pid); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + result = 1; + kill_children(); + } + } + + if (alarm_gone_off) + return 0; + + return result; +} -- cgit v1.2.3