blob: 7d808a4df7d2e7f95e6071e6c4cae35748d216fc [file] [log] [blame]
/******************************************************************************/
/* */
/* Copyright (c) International Business Machines Corp., 2001 */
/* */
/* 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/******************************************************************************/
/******************************************************************************/
/* */
/* History: Oct - 10 - 2001 Created - Manoj Iyer, IBM Austin TX. */
/* email:manjo@austin.ibm.com */
/* - create a directory tree that is */
/* unique to each process. The base directory */
/* looks like hostname.<pid of the process> */
/* the subdirectories will be <pid>.0 <pid.1> etc*/
/* eg: */
/* hostname.1234 */
/* |_ 1234.0 */
/* |_ 1234.1 */
/* |_1234.2 */
/* |.... */
/* hostname - hostname of the machine */
/* 1234 - pid of the current process. */
/* Each of these directories are populated with */
/* N number of ".c" files and a makefile that can*/
/* compile the ".c" files and also initiate */
/* compile of ".c" files in the subdirectories */
/* under it. */
/* */
/* Oct - 11 - 2001 Modified */
/* - fixed a bug in the makefiles, the last make-*/
/* file was expecting subdirectories. Added */
/* code to generate a different makefile for */
/* the last subdirectory. */
/* - Added logic to first compile all the c files*/
/* and upon completion remove them. */
/* - Added multithreading, arguments handling. */
/* By default the program will generate 8 */
/* threads, each creating by default 100 deep */
/* directory tree each containing default 100 */
/* ".c" files and one makefile. */
/* - Added usage message. */
/* */
/* Oct - 12 - 2001 Modified */
/* - Added logic to print missing arguments to */
/* options. */
/* */
/* Oct - 15 - 2001 Modified */
/* - Added logic to remove the files, makefiles */
/* and subdirectories that were created. */
/* - Added logic to print debug messages. */
/* */
/* Oct - 16 - 2001 Modified */
/* - Added sync() calls to commit changes. */
/* - Fixed bug. pthread_join() returns 0 when */
/* pthread_join fails, if the thread function */
/* fails pthread_join() will put the exit value*/
/* of the thread function in the thread_return */
/* output argument. */
/* - Debugging function crte_mk_rm fails to */
/* create fies, problem appears only in multi- */
/* threaded case. */
/* */
/* Oct - 17 - 2001 Checked in */
/* - GPL statement was added and the initial ver */
/* - checked into CVS. */
/* - note: this version works only if it is run */
/* single threaded, when its run multithreaded */
/* random thread will fail on open() sys call */
/* problem currently under investigation. */
/* */
/* Oct - 20 - 2001 Modified */
/* - fixed a whole bunch of problems. */
/* - created function init_compile. Apparently */
/* this code works!!. */
/* - removed system() system call that was doing */
/* make and make clean. init_compile() replaces*/
/* this piece of code. */
/* - on supplying the full pathname to unlink() */
/* solved most of the problems with rm_file_mk */
/* function. */
/* - reset the default vaulues for MAXT = 8 */
/* MAXD = 100 and MAXF = 100. */
/* ie. maximum number of threads = 8 */
/* directory depth (num of sub dirs) = 100 */
/* numeber of .c fils in each sub dir = 100*/
/* - finally program is now in working state. */
/* */
/* Nov - 01 - 2001 Modified. */
/* - fixed usage message default MAXT is 8 not 1 */
/* - fixed make to compile the files silently */
/* */
/* Nov - 19 - 2001 Modified. */
/* - changed th_status in function main() from */
/* dynamic variable to static array. */
/* */
/* File: make_tree.c */
/* */
/* Description: This program is designed stress the NFS implimentation. */
/* Many bugs were uncovered in the AIX operating system */
/* implimentation of NFS when AIX kernel was built over NFS. */
/* Source directory on a remote machine (one server many clients)*/
/* NFS-mounted on to a directory on a local machine from which */
/* the kernel build was initiated. Apparently many defects/bugs */
/* were uncovered when multiple users tried to build the kernel */
/* by NFS mounting the kernel source from a remote machine and */
/* tried to build the kernel on a local machine. AIX build envi- */
/* ronment is set up to create the object files and executable */
/* on the local machine. */
/* This testcase will try to recreate such a senario. */
/* Spawn N number of threads. Each thread does the following. */
/* * Create a directory tree. */
/* * Populate it with ".c" files and makefiles. */
/* * initate a build. Executable will print hello world when exed*/
/* * clean up all the executables that were created. */
/* * recurssively remove each subdir and its contents. */
/* The test is aimed at stressing the NFS client and server. */
/* hostname.1234 */
/* | */
/* | - 1234.0.0.c */
/* | - 1234.0.1.c */
/* | - .......... */
/* | - makefile */
/* | */
/* |_ 1234.0 */
/* | */
/* | - 1234.1.0.c */
/* | - 1234.1.1.c */
/* | - .......... */
/* | - makefile */
/* | */
/* |_ 1234.1 */
/* | */
/* | - 1234.2.0.c */
/* | - 1234.2.1.c */
/* | - .......... */
/* | - makefile */
/* | */
/* |_1234.2 */
/* |.... */
/* */
/* Setup: - on the server side: */
/* * create a directory /nfs_test */
/* * make an entry in /etc/exports file like this... */
/* "/nfs_test *(rw,no_root_squash)" */
/* * run command "exportfs -a" */
/* - on client side: */
/* * create a directory say for eg: /nfs_cli */
/* * mount -t nfs servername:/nfs_test /nfs_cli */
/* * set up the tescase in /nfs_cli directory */
/* - I reccomend that you have atleast 8 client machines running */
/* this test, linux has 8 NFSD's running by default, you might*/
/* have to increase it as per your requirement. */
/* */
/* Note: - assumed that NFS services are installed and configured */
/* - you have atleast 2 machines to act as client and server */
/* (you can have muiltiple client machines and one server) */
/* - large amount of disk space, this depends on the number of */
/* of clients you will have, if you have only one client, I */
/* reccomend that the server have atleast 4 Giga bytes of */
/* disk space (paranoid!). */
/* */
/******************************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mount.h>
#include <linux/limits.h>
#include <errno.h>
#include <linux/unistd.h>
#define gettid() syscall(__NR_gettid)
#ifdef DEBUG
#define dprt(fmt, args...) printf(fmt, ## args)
#else
#define dprt(fmt, args...)
#endif
#define MAKE_EXE 1 /* initate a make */
#define MAKE_CLEAN 0 /* initate a make clean */
#define PTHREAD_EXIT(val) do {\
exit_val = val; \
dprt("pid[%d]: exiting with %d\n", gettid(),exit_val); \
pthread_exit((void *)exit_val); \
} while (0)
#define OPT_MISSING(prog, opt) do{\
fprintf(stderr, "%s: option -%c ", prog, opt); \
fprintf(stderr, "requires an argument\n"); \
usage(prog); \
} while (0)
#define MAXD 100 /* default number of directories to create. */
#define MAXF 100 /* default number of files to create. */
#define MAXT 8 /* default number of threads to create. */
/******************************************************************************/
/* */
/* Function: usage */
/* */
/* Description: Print the usage message. */
/* */
/* Return: exits with -1 */
/* */
/******************************************************************************/
static void
usage(char *progname) /* name of this program */{
fprintf(stderr,
"Usage: %s -d NUMDIR -f NUMFILES -h -t NUMTHRD\n"
"\t -d Number of subdirectories to generate: Default: 100\n"
"\t -f Number of c files in each subdirectory: Default: 100\n"
"\t -h Help!\n"
"\t -t Number of threads to generate: Default: 8\n",
progname);
exit(-1);
}
/******************************************************************************/
/* */
/* Function: init_compile */
/* */
/* Description: This function compiles the .c files and removes the exeutables*/
/* This function does the same function as the system() system */
/* call, the code is available in the system() man page. When */
/* called with the parameter MAKE_EXE it will initiate make in */
/* the first directory created, the makefile is designed to build*/
/* recursively all the files in the subdirectories below. */
/* When called with the MAKE_CLEAN parameter it will remove the */
/* executables that were created design is similar to the case */
/* were it initiates a make. */
/* */
/* Return: exits with 1 on error, 0 on success */
/* */
/******************************************************************************/
static int
init_compile( int what_todo, /* do a compile or clean */
char *base_dir, /* base directory of the test */
char *hname) /* hostname of the machine */
{
int status; /* return status of execve process */
pid_t pid; /* pid of the process that does compile */
char *dirname; /* location where compile is initated */
char *command; /* make or make clean command. */
if ((dirname = malloc(sizeof(char) * 2048)) == NULL) /* just paranoid */
{
perror("init_compile(): dirname malloc()");
return 1;
}
if ((command = malloc(sizeof(char) * 1024)) == NULL) /* just paranoid */
{
perror("init_compile(): dirname malloc()");
return 1;
}
what_todo ? sprintf(command, "make -s") : sprintf(command, "make -s clean");
sprintf(dirname, "%s/%s.%ld", base_dir, hname, gettid());
if (chdir(dirname) == -1)
{
dprt("pid[%d]: init_compile(): dir name = %s\n", gettid(), dirname);
perror("init_compile() chdir()");
free(dirname);
return 1;
}
dprt("pid[%d]: init_compile(): command = %s\n", gettid(), command);
if ((pid = fork()) == -1)
{
perror("init_compile(): fork()");
return 1;
}
if (!pid)
{
char *argv[4];
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = command;
argv[3] = 0;
if (execv("/bin/sh", argv) == -1)
{
perror("init_compile(): execv()");
return 1;
}
}
do
{
if (waitpid(pid, &status, 0) == -1)
{
if (errno != EINTR)
{
fprintf(stderr, "init_compile(): waitpid() failed\n");
return 1;
}
}
else
{
if (chdir(base_dir) == -1)
{
dprt("pid[%d]: init_compile(): dir = %s\n", gettid(), dirname);
perror("init_compile(): chdir()");
return 1;
}
dprt("pid[%d]: init_compile(): status = %d\n", status);
dprt("we are here %d\n", __LINE__);
return status;
}
} while (1);
}
/******************************************************************************/
/* */
/* Function: rm_file_dir */
/* */
/* Description: This function removes the .c files makefiles and directories. */
/* First removes the files in the files in the last directory */
/* first then removes the last directory, then cycles through */
/* each subdirectory and does the same. */
/* */
/* Return: exits with 1 on error, 0 on success */
/* */
/******************************************************************************/
static int
rm_file_dir( int numsdir, /* how many subdirs to remove */
int numfiles, /* number of files to remove per dir */
char *hname, /* hostname of the client machine */
char *base_dir) /* directory where the test is located*/
{
int filecnt; /* index to the num of files to remove*/
int dircnt; /* index into directory tree */
int sindex = numsdir; /* num subdirectory tree to remove */
char *dirname; /* name of the directory to chdir() */
char *tmpdirname; /* temp name for directory, for swap */
char *filename; /* name of the cfile to remove */
char *subdir; /* name of the sub dir to remove */
if ((dirname = malloc(sizeof(char) * 2048)) == NULL) /* just paranoid */
{
perror("crte_mk_rm(): dirname malloc()");
return 1;
}
if ((tmpdirname = malloc(sizeof(char) * 2048)) == NULL) /* just paranoid */
{
perror("crte_mk_rm(): tmpdirname malloc()");
return 1;
}
if ((filename = malloc(sizeof(char) * 2048)) == NULL) /* just paranoid */
{
perror("crte_mk_rm(): filename malloc()");
return 1;
}
if ((subdir = malloc(sizeof(char) * 2048)) == NULL) /* just paranoid */
{
perror("crte_mk_rm(): subdir malloc()");
return 1;
}
dprt("pid[%d]: base directory: %s\n", gettid(), base_dir);
while (sindex)
{
/* get the name of the last directory created. */
for (dircnt = 0; dircnt < sindex; dircnt++)
{
if (dircnt == 0)
sprintf(dirname, "%s/%s.%ld", base_dir, hname, gettid());
else
{
sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(), dircnt);
sprintf(dirname, "%s", tmpdirname);
}
sync();
}
dprt("pid[%d]: cd'ing to last created dir: %s\n", gettid(), dirname);
sindex--;
/* remove all the ".c" files and makefile in this directory */
for (filecnt = 0; filecnt < numfiles; filecnt++)
{
sprintf(filename, "%s/%ld.%d.%d.c", dirname, gettid(), dircnt - 1,
filecnt);
dprt("pid[%d]: removing file: %s\n", gettid(), filename);
if (unlink(filename))
{
dprt("pid[%d]: failed removing file: %s\n", gettid(), filename);
perror("rm_file_dir(): unlink()");
free(tmpdirname);
free(dirname);
free(filename);
free(subdir);
return 1;
}
sync();
}
sprintf(filename, "%s/%s", dirname, "makefile");
dprt("pid[%d]: removing %s\n", gettid(), filename);
if (unlink(filename))
{
perror("rm_file_dir() cound not remove makefile unlink()");
free(tmpdirname);
free(dirname);
free(filename);
free(subdir);
return 1;
}
sync();
/* the last directory does not have any more sub directories */
/* nothing to remove. */
dprt("pid[%d]: in directory count(dircnt): %d\n", gettid(), dircnt);
dprt("pid[%d]: last directory(numsdir): %d\n", gettid(), numsdir);
if (dircnt < numsdir)
{
/* remove the sub directory */
sprintf(subdir, "%s/%ld.%d", dirname, gettid(), dircnt);
dprt("pid[%d]: removing subdirectory: %s\n", gettid(), subdir);
if (rmdir(subdir) == -1)
{
perror("rm_file_dir() rmdir()");
free(tmpdirname);
free(dirname);
free(filename);
free(subdir);
return 1;
}
sync();
}
}
free(tmpdirname);
free(dirname);
free(filename);
free(subdir);
return 0;
}
/******************************************************************************/
/* */
/* Function: crte_mk_rm */
/* */
/* Description: This function gets executed by each thread that is created. */
/* crte_mk_rm() created the directory tree, polpulates it with */
/* ".c" files and a makefile that will compile the ".c" files and*/
/* initiate the makefile in the subdirectory under it. Once the */
/* c source files are compiled it will remove them. */
/* */
/* Input: The argument pointer contains the following. */
/* arg[0] - number of directories to create, depth of the tree. */
/* arg[1] - number of ".c" files to create in each dir branch. */
/* */
/* Return: -1 on failure */
/* 0 on success */
/* */
/******************************************************************************/
static void *
crte_mk_rm(void *args)
{
int dircnt; /* index to the number of subdirectories */
int fd; /* file discriptor of the files genetated */
int filecnt; /* index to the number of ".c" files created */
int numchar[2]; /* number of characters written to buffer */
char *dirname; /* name of the directory/idirectory tree */
char *tmpdirname; /* name of a temporary directory, for swaping */
char *cfilename; /* name of the ".c" file created */
char *mkfilename; /* name of the makefile - which is "makefile" */
char *hostname; /* hostname of the client machine */
char *prog_buf; /* buffer containing contents of the ".c" file*/
char *make_buf; /* buffer the contents of the makefile */
char *pwd; /* contains the current working directory */
long *locargptr = /* local pointer to arguments */
(long *)args;
volatile int exit_val = 0; /* exit value of the pthreads */
if ((dirname = malloc(sizeof(char) * 2048)) == NULL) /* just paranoid */
{
perror("crte_mk_rm(): dirname malloc()");
PTHREAD_EXIT(-1);
}
if ((tmpdirname = malloc(sizeof(char) * 2048)) == NULL)
{
perror("crte_mk_rm(): tmpdirname malloc()");
PTHREAD_EXIT(-1);
}
if ((cfilename = malloc(sizeof(char) * 2048)) == NULL)
{
perror("crte_mk_rm(): cfilename malloc()");
PTHREAD_EXIT(-1);
}
if ((mkfilename = malloc(sizeof(char) * 2048)) == NULL)
{
perror("crte_mk_rm(): mkfilename malloc()");
PTHREAD_EXIT(-1);
}
if ((prog_buf = malloc(sizeof(char) * 4096)) == NULL)
{
perror("crte_mk_rm(): prog_buf malloc()");
PTHREAD_EXIT(-1);
}
if ((pwd = malloc(PATH_MAX)) == NULL)
{
perror("crte_mk_rm(): pwd malloc()");
PTHREAD_EXIT(-1);
}
if ((hostname = malloc(sizeof(char) * 1024)) == NULL)
{
perror("crte_mk_rm(): hostname malloc()");
PTHREAD_EXIT(-1);
}
if (gethostname(hostname, 255) == -1)
{
perror("crte_mk_rm(): gethostname()");
PTHREAD_EXIT(-1);
}
if (!getcwd(pwd, PATH_MAX))
{
perror("crte_mk_rm(): getcwd()");
PTHREAD_EXIT(-1);
}
numchar[0] = sprintf(prog_buf,
"main()\n{\n\t printf(\"hello world\");\n}\n");
for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++)
{
/* First create the base directory, then create the subdirectories */
if (dircnt == 0)
sprintf(dirname, "%s.%ld", hostname, gettid());
else
{
sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(), dircnt);
sprintf(dirname, "%s", tmpdirname);
}
sync();
dprt("pid[%d] creating directory: %s\n", gettid(), dirname);
if (mkdir(dirname, 0777) == -1)
{
perror("crte_mk_rm(): mkdir()");
PTHREAD_EXIT(-1);
}
}
sync();
usleep(10);
for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++)
{
if (dircnt == 0)
sprintf(dirname, "%s/%s.%ld", pwd, hostname, gettid());
else
{
sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(), dircnt);
sprintf(dirname, "%s", tmpdirname);
}
sync();
if ((make_buf = malloc(sizeof(char) * 4096)) == NULL)
{
perror("crte_mk_rm(): make_buf malloc()");
PTHREAD_EXIT(-1);
}
sprintf(mkfilename, "%s/makefile", dirname);
{
/* HACK! I could not write "%.c" to the makefile */
/* there is probably a correct way to do it */
char *dotc = malloc(10);
dotc = ".c";
sync();
usleep(10);
if (dircnt == (locargptr[0] - 1))
{
numchar[1] = sprintf(make_buf,
"CFLAGS := -O -w -g\n"
"SUBDIRS = %ld.%d\n"
"SRCS=$(wildcard *.c)\n"
"TARGETS=$(patsubst %%%s,\%%,$(SRCS))\n"
"all:\t $(TARGETS)\n"
"clean:\n"
"\trm -f $(TARGETS)\n",
gettid(), dircnt + 1, dotc);
}
else
{
numchar[1] = sprintf(make_buf,
"CFLAGS := -O -w -g\n"
"SUBDIRS = %ld.%d\n"
"SRCS=$(wildcard *.c)\n"
"TARGETS=$(patsubst %%%s,\%%,$(SRCS))\n\n\n"
"all:\t $(TARGETS)\n"
"\t@for i in $(SUBDIRS); do $(MAKE) -C $$i ; done\n\n"
"clean:\n"
"\trm -f $(TARGETS)\n"
"\t@for i in $(SUBDIRS); do $(MAKE) -C $$i clean ; done\n",
gettid(), dircnt + 1, dotc);
}
}
sync();
usleep(10);
dprt("pid[%d]: creating in dir: %s\n", gettid(), mkfilename);
/* create the makefile, complies .c files and initiates make in */
/* subdirectories. */
if ((fd = open(mkfilename, O_CREAT|O_RDWR,
S_IRWXU|S_IRWXG|S_IRWXO)) == -1)
{
dprt(" pid[%d]: failed to create makefile\n", gettid());
dprt("pid[%d]: failed in directory %s\n", gettid(), dirname);
perror("crte_mk_rm() failed creating makefile: open()");
PTHREAD_EXIT(-1);
}
else
{
sync();
if (write(fd, make_buf, numchar[1]) == -1)
{
perror("crte_mk_rm(): write()");
PTHREAD_EXIT(-1);
}
free(make_buf);
if (close(fd) == -1)
{
perror("crte_mk_rm(): close()");
PTHREAD_EXIT(-1);
}
}
}
for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++)
{
if (dircnt == 0)
sprintf(dirname, "%s/%s.%ld", pwd, hostname, gettid());
else
{
sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(), dircnt);
sprintf(dirname, "%s", tmpdirname);
}
sync();
/* In each directory create N ".c" files and a makefile. */
for (filecnt = 0; filecnt < (int)locargptr[1]; filecnt++)
{
sprintf(cfilename, "%s/%ld.%d.%d.c", dirname, gettid(),
dircnt, filecnt);
dprt("pid[%d]: creating file: %s\n", gettid(), cfilename);
if ((fd = open(cfilename, O_CREAT|O_RDWR,
S_IRWXU|S_IRWXG|S_IRWXO)) == -1)
{
fprintf(stderr, "open() failed to create file %s\n", cfilename);
perror("crte_mk_rm(): failed creating .c files: open()");
PTHREAD_EXIT(-1);
}
else
{
sync();
/* write the code, this program prints hello world */
if (write(fd, prog_buf, numchar[0]) == -1)
{
perror("crte_mk_rm(): write()");
PTHREAD_EXIT(-1);
}
fsync(fd);
if (close(fd) == -1)
{
perror("crte_mk_rm(): close()");
PTHREAD_EXIT(-1);
}
}
}
}
if (init_compile(MAKE_EXE, pwd, hostname) == 1)
{
fprintf(stderr, "init_compile() make failed\n");
PTHREAD_EXIT(-1);
}
else
{
if (init_compile(MAKE_CLEAN, pwd, hostname) == 1)
{
fprintf(stderr, "init_compile() make clean failed\n");
PTHREAD_EXIT(-1);
}
}
sync();
/* remove all the files makefiles and subdirecotries */
if (rm_file_dir((int)locargptr[0], (int)locargptr[1], hostname, pwd))
{
fprintf(stderr, "crte_mk_rm(): rm_file_dir() failed\n");
PTHREAD_EXIT(-1);
}
/* if it made it this far exit with success */
PTHREAD_EXIT(0);
}
/******************************************************************************/
/* */
/* Function: main */
/* */
/* Description: This is the entry point to the program. This function will */
/* parse the input arguments and set the values accordingly. If */
/* no arguments (or desired) are provided default values are used*/
/* refer the usage function for the arguments that this program */
/* takes. It also creates the threads which do most of the dirty */
/* work. If the threads exits with a value '0' the program exits */
/* with success '0' else it exits with failure '-1'. */
/* */
/* Return: -1 on failure */
/* 0 on success */
/* */
/******************************************************************************/
int
main(int argc, /* number of input parameters */
char **argv) /* pointer to the command line arguments. */
{
int c; /* command line options */
int num_thrd = MAXT;/* number of threads to create */
int num_dirs = MAXD;/* number of subdirectories to create */
int num_files = MAXF;/* number of files in each subdirectory */
int thrd_ndx; /* index into the array of thread ids */
int th_status[1]; /* exit status of LWP's */
pthread_t thrdid[30]; /* maxinum of 30 threads allowed */
long chld_args[3]; /* arguments to the thread function */
extern int optopt; /* options to the program */
while ((c = getopt(argc, argv, "d:f:ht:")) != -1)
{
switch(c)
{
case 'd': /* specify how deep the tree needs to grow */
if ((num_dirs = atoi(optarg)) == 0)
OPT_MISSING(argv[0], optopt);
else
if (num_dirs < 0)
{
fprintf(stdout,
"WARNING: bad argument. Using default\n");
num_dirs = MAXD;
}
break;
case 'f': /* how many ".c" files in each directory. */
if ((num_files = atoi(optarg)) == 0)
OPT_MISSING(argv[0], optopt);
else
if (num_files < 0)
{
fprintf(stdout,
"WARNING: bad argument. Using default\n");
num_files = MAXF;
}
break;
case 'h':
usage(argv[0]);
break;
case 't':
if ((num_thrd = atoi(optarg)) == 0)
OPT_MISSING(argv[0], optopt);
else
if (num_thrd < 0)
{
fprintf(stdout,
"WARNING: bad argument. Using default\n");
num_thrd = MAXT;
}
break;
default :
usage(argv[0]);
break;
}
}
chld_args[0] = num_dirs;
chld_args[1] = num_files;
for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++)
{
if (pthread_create(&thrdid[thrd_ndx], NULL, crte_mk_rm, chld_args))
{
perror("crte_mk_rm(): pthread_create()");
exit(-1);
}
}
sync();
for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++)
{
if (pthread_join(thrdid[thrd_ndx], (void **)&th_status) != 0)
{
perror("crte_mk_rm(): pthread_join()");
exit(-1);
}
else
{
dprt("WE ARE HERE %d\n", __LINE__);
if (*th_status == -1)
{
fprintf(stderr,
"thread [%ld] - process exited with errors\n",
thrdid[thrd_ndx]);
exit(-1);
}
}
}
return(0);
}