1 /******************************************************************************/
2 /* */
3 /* Copyright (c) International Business Machines Corp., 2001 */
4 /* */
5 /* This program is free software; you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation; either version 2 of the License, or */
8 /* (at your option) any later version. */
9 /* */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
13 /* the GNU General Public License for more details. */
14 /* */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program; if not, write to the Free Software */
17 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 /* */
19 /******************************************************************************/
20
21 /******************************************************************************/
22 /* */
23 /* History: Oct - 10 - 2001 Created - Manoj Iyer, IBM Austin TX. */
24 /* email:manjo@austin.ibm.com */
25 /* - create a directory tree that is */
26 /* unique to each process. The base directory */
27 /* looks like hostname.<pid of the process> */
28 /* the subdirectories will be <pid>.0 <pid.1> etc*/
29 /* eg: */
30 /* hostname.1234 */
31 /* |_ 1234.0 */
32 /* |_ 1234.1 */
33 /* |_1234.2 */
34 /* |.... */
35 /* hostname - hostname of the machine */
36 /* 1234 - pid of the current process. */
37 /* Each of these directories are populated with */
38 /* N number of ".c" files and a makefile that can*/
39 /* compile the ".c" files and also initiate */
40 /* compile of ".c" files in the subdirectories */
41 /* under it. */
42 /* */
43 /* Oct - 11 - 2001 Modified */
44 /* - fixed a bug in the makefiles, the last make-*/
45 /* file was expecting subdirectories. Added */
46 /* code to generate a different makefile for */
47 /* the last subdirectory. */
48 /* - Added logic to first compile all the c files*/
49 /* and upon completion remove them. */
50 /* - Added multithreading, arguments handling. */
51 /* By default the program will generate 8 */
52 /* threads, each creating by default 100 deep */
53 /* directory tree each containing default 100 */
54 /* ".c" files and one makefile. */
55 /* - Added usage message. */
56 /* */
57 /* Oct - 12 - 2001 Modified */
58 /* - Added logic to print missing arguments to */
59 /* options. */
60 /* */
61 /* Oct - 15 - 2001 Modified */
62 /* - Added logic to remove the files, makefiles */
63 /* and subdirectories that were created. */
64 /* - Added logic to print debug messages. */
65 /* */
66 /* Oct - 16 - 2001 Modified */
67 /* - Added sync() calls to commit changes. */
68 /* - Fixed bug. pthread_join() returns 0 when */
69 /* pthread_join fails, if the thread function */
70 /* fails pthread_join() will put the exit value*/
71 /* of the thread function in the thread_return */
72 /* output argument. */
73 /* - Debugging function crte_mk_rm fails to */
74 /* create fies, problem appears only in multi- */
75 /* threaded case. */
76 /* */
77 /* Oct - 17 - 2001 Checked in */
78 /* - GPL statement was added and the initial ver */
79 /* - checked into CVS. */
80 /* - note: this version works only if it is run */
81 /* single threaded, when its run multithreaded */
82 /* random thread will fail on open() sys call */
83 /* problem currently under investigation. */
84 /* */
85 /* Oct - 20 - 2001 Modified */
86 /* - fixed a whole bunch of problems. */
87 /* - created function init_compile. Apparently */
88 /* this code works!!. */
89 /* - removed system() system call that was doing */
90 /* make and make clean. init_compile() replaces*/
91 /* this piece of code. */
92 /* - on supplying the full pathname to unlink() */
93 /* solved most of the problems with rm_file_mk */
94 /* function. */
95 /* - reset the default vaulues for MAXT = 8 */
96 /* MAXD = 100 and MAXF = 100. */
97 /* ie. maximum number of threads = 8 */
98 /* directory depth (num of sub dirs) = 100 */
99 /* numeber of .c fils in each sub dir = 100*/
100 /* - finally program is now in working state. */
101 /* */
102 /* Nov - 01 - 2001 Modified. */
103 /* - fixed usage message default MAXT is 8 not 1 */
104 /* - fixed make to compile the files silently */
105 /* */
106 /* Nov - 19 - 2001 Modified. */
107 /* - changed th_status in function main() from */
108 /* dynamic variable to static array. */
109 /* */
110 /* File: make_tree.c */
111 /* */
112 /* Description: This program is designed stress the NFS implimentation. */
113 /* Many bugs were uncovered in the AIX operating system */
114 /* implimentation of NFS when AIX kernel was built over NFS. */
115 /* Source directory on a remote machine (one server many clients)*/
116 /* NFS-mounted on to a directory on a local machine from which */
117 /* the kernel build was initiated. Apparently many defects/bugs */
118 /* were uncovered when multiple users tried to build the kernel */
119 /* by NFS mounting the kernel source from a remote machine and */
120 /* tried to build the kernel on a local machine. AIX build envi- */
121 /* ronment is set up to create the object files and executable */
122 /* on the local machine. */
123 /* This testcase will try to recreate such a senario. */
124 /* Spawn N number of threads. Each thread does the following. */
125 /* * Create a directory tree. */
126 /* * Populate it with ".c" files and makefiles. */
127 /* * initate a build. Executable will print hello world when exed*/
128 /* * clean up all the executables that were created. */
129 /* * recurssively remove each subdir and its contents. */
130 /* The test is aimed at stressing the NFS client and server. */
131 /* hostname.1234 */
132 /* | */
133 /* | - 1234.0.0.c */
134 /* | - 1234.0.1.c */
135 /* | - .......... */
136 /* | - makefile */
137 /* | */
138 /* |_ 1234.0 */
139 /* | */
140 /* | - 1234.1.0.c */
141 /* | - 1234.1.1.c */
142 /* | - .......... */
143 /* | - makefile */
144 /* | */
145 /* |_ 1234.1 */
146 /* | */
147 /* | - 1234.2.0.c */
148 /* | - 1234.2.1.c */
149 /* | - .......... */
150 /* | - makefile */
151 /* | */
152 /* |_1234.2 */
153 /* |.... */
154 /* */
155 /* Setup: - on the server side: */
156 /* * create a directory /nfs_test */
157 /* * make an entry in /etc/exports file like this... */
158 /* "/nfs_test *(rw,no_root_squash)" */
159 /* * run command "exportfs -a" */
160 /* - on client side: */
161 /* * create a directory say for eg: /nfs_cli */
162 /* * mount -t nfs servername:/nfs_test /nfs_cli */
163 /* * set up the tescase in /nfs_cli directory */
164 /* - I reccomend that you have atleast 8 client machines running */
165 /* this test, linux has 8 NFSD's running by default, you might*/
166 /* have to increase it as per your requirement. */
167 /* */
168 /* Note: - assumed that NFS services are installed and configured */
169 /* - you have atleast 2 machines to act as client and server */
170 /* (you can have muiltiple client machines and one server) */
171 /* - large amount of disk space, this depends on the number of */
172 /* of clients you will have, if you have only one client, I */
173 /* reccomend that the server have atleast 4 Giga bytes of */
174 /* disk space (paranoid!). */
175 /* */
176 /******************************************************************************/
177
178 #include <stdio.h>
179 #include <sys/stat.h>
180 #include <sys/wait.h>
181 #include <unistd.h>
182 #include <stdlib.h>
183 #include <fcntl.h>
184 #include <unistd.h>
185 #include <pthread.h>
186 #include <sys/mount.h>
187 #include <linux/limits.h>
188 #include <errno.h>
189 #include <linux/unistd.h>
190
191 #define gettid() syscall(__NR_gettid)
192
193 #ifdef DEBUG
194 #define dprt(fmt, args...) printf(fmt, ## args)
195 #else
196 #define dprt(fmt, args...)
197 #endif
198
199 #define MAKE_EXE 1 /* initate a make */
200 #define MAKE_CLEAN 0 /* initate a make clean */
201
202 #define PTHREAD_EXIT(val) do {\
203 exit_val = val; \
204 dprt("pid[%d]: exiting with %d\n", gettid(),exit_val); \
205 pthread_exit((void *)exit_val); \
206 } while (0)
207
208 #define OPT_MISSING(prog, opt) do{\
209 fprintf(stderr, "%s: option -%c ", prog, opt); \
210 fprintf(stderr, "requires an argument\n"); \
211 usage(prog); \
212 } while (0)
213
214 #define MAXD 100 /* default number of directories to create. */
215 #define MAXF 100 /* default number of files to create. */
216 #define MAXT 8 /* default number of threads to create. */
217
218 /******************************************************************************/
219 /* */
220 /* Function: usage */
221 /* */
222 /* Description: Print the usage message. */
223 /* */
224 /* Return: exits with -1 */
225 /* */
226 /******************************************************************************/
usage(char * progname)227 static void usage(char *progname)
228 { /* name of this program */
229 fprintf(stderr,
230 "Usage: %s -d NUMDIR -f NUMFILES -h -t NUMTHRD\n"
231 "\t -d Number of subdirectories to generate: Default: 100\n"
232 "\t -f Number of c files in each subdirectory: Default: 100\n"
233 "\t -h Help!\n"
234 "\t -t Number of threads to generate: Default: 8\n",
235 progname);
236 exit(-1);
237 }
238
239 /******************************************************************************/
240 /* */
241 /* Function: init_compile */
242 /* */
243 /* Description: This function compiles the .c files and removes the exeutables*/
244 /* This function does the same function as the system() system */
245 /* call, the code is available in the system() man page. When */
246 /* called with the parameter MAKE_EXE it will initiate make in */
247 /* the first directory created, the makefile is designed to build*/
248 /* recursively all the files in the subdirectories below. */
249 /* When called with the MAKE_CLEAN parameter it will remove the */
250 /* executables that were created design is similar to the case */
251 /* were it initiates a make. */
252 /* */
253 /* Return: exits with 1 on error, 0 on success */
254 /* */
255 /******************************************************************************/
init_compile(int what_todo,char * base_dir,char * hname)256 static int init_compile(int what_todo, /* do a compile or clean */
257 char *base_dir, /* base directory of the test */
258 char *hname)
259 { /* hostname of the machine */
260 int status; /* return status of execve process */
261 pid_t pid; /* pid of the process that does compile */
262 char *dirname; /* location where compile is initated */
263 char *command; /* make or make clean command. */
264
265 if ((dirname = malloc(sizeof(char) * 2048)) == NULL) { /* just paranoid */
266 perror("init_compile(): dirname malloc()");
267 return 1;
268 }
269
270 if ((command = malloc(sizeof(char) * 1024)) == NULL) { /* just paranoid */
271 perror("init_compile(): dirname malloc()");
272 return 1;
273 }
274
275 what_todo ? sprintf(command, "make -s") : sprintf(command,
276 "make -s clean");
277
278 sprintf(dirname, "%s/%s.%ld", base_dir, hname, gettid());
279
280 if (chdir(dirname) == -1) {
281 dprt("pid[%d]: init_compile(): dir name = %s\n", gettid(),
282 dirname);
283 perror("init_compile() chdir()");
284 free(dirname);
285 return 1;
286 }
287
288 dprt("pid[%d]: init_compile(): command = %s\n", gettid(), command);
289
290 if ((pid = fork()) == -1) {
291 perror("init_compile(): fork()");
292 return 1;
293 }
294 if (!pid) {
295 char *argv[4];
296
297 argv[0] = "/bin/sh";
298 argv[1] = "-c";
299 argv[2] = command;
300 argv[3] = 0;
301
302 if (execv("/bin/sh", argv) == -1) {
303 perror("init_compile(): execv()");
304 return 1;
305 }
306 }
307 do {
308 if (waitpid(pid, &status, 0) == -1) {
309 if (errno != EINTR) {
310 fprintf(stderr,
311 "init_compile(): waitpid() failed\n");
312 return 1;
313 }
314 } else {
315 if (chdir(base_dir) == -1) {
316 dprt("pid[%d]: init_compile(): dir = %s\n",
317 gettid(), dirname);
318 perror("init_compile(): chdir()");
319 return 1;
320 }
321
322 dprt("pid[%d]: init_compile(): status = %d\n",
323 gettid(), status);
324 dprt("we are here %d\n", __LINE__);
325 return status;
326 }
327
328 } while (1);
329 }
330
331 /******************************************************************************/
332 /* */
333 /* Function: rm_file_dir */
334 /* */
335 /* Description: This function removes the .c files makefiles and directories. */
336 /* First removes the files in the files in the last directory */
337 /* first then removes the last directory, then cycles through */
338 /* each subdirectory and does the same. */
339 /* */
340 /* Return: exits with 1 on error, 0 on success */
341 /* */
342 /******************************************************************************/
rm_file_dir(int numsdir,int numfiles,char * hname,char * base_dir)343 static int rm_file_dir(int numsdir, /* how many subdirs to remove */
344 int numfiles, /* number of files to remove per dir */
345 char *hname, /* hostname of the client machine */
346 char *base_dir)
347 { /* directory where the test is located */
348 int filecnt; /* index to the num of files to remove */
349 int dircnt; /* index into directory tree */
350 int sindex = numsdir; /* num subdirectory tree to remove */
351 char *dirname; /* name of the directory to chdir() */
352 char *tmpdirname; /* temp name for directory, for swap */
353 char *filename; /* name of the cfile to remove */
354 char *subdir; /* name of the sub dir to remove */
355
356 if ((dirname = malloc(sizeof(char) * 2048)) == NULL) { /* just paranoid */
357 perror("crte_mk_rm(): dirname malloc()");
358 return 1;
359 }
360
361 if ((tmpdirname = malloc(sizeof(char) * 2048)) == NULL) { /* just paranoid */
362 perror("crte_mk_rm(): tmpdirname malloc()");
363 return 1;
364 }
365
366 if ((filename = malloc(sizeof(char) * 2048)) == NULL) { /* just paranoid */
367 perror("crte_mk_rm(): filename malloc()");
368 return 1;
369 }
370
371 if ((subdir = malloc(sizeof(char) * 2048)) == NULL) { /* just paranoid */
372 perror("crte_mk_rm(): subdir malloc()");
373 return 1;
374 }
375
376 dprt("pid[%d]: base directory: %s\n", gettid(), base_dir);
377 while (sindex) {
378 /* get the name of the last directory created. */
379 for (dircnt = 0; dircnt < sindex; dircnt++) {
380 if (dircnt == 0)
381 sprintf(dirname, "%s/%s.%ld", base_dir, hname,
382 gettid());
383 else {
384 sprintf(tmpdirname, "%s/%ld.%d", dirname,
385 gettid(), dircnt);
386 sprintf(dirname, "%s", tmpdirname);
387 }
388 sync();
389 }
390
391 dprt("pid[%d]: cd'ing to last created dir: %s\n", gettid(),
392 dirname);
393
394 sindex--;
395
396 /* remove all the ".c" files and makefile in this directory */
397 for (filecnt = 0; filecnt < numfiles; filecnt++) {
398 sprintf(filename, "%s/%ld.%d.%d.c", dirname, gettid(),
399 dircnt - 1, filecnt);
400 dprt("pid[%d]: removing file: %s\n", gettid(),
401 filename);
402
403 if (unlink(filename)) {
404 dprt("pid[%d]: failed removing file: %s\n",
405 gettid(), filename);
406 perror("rm_file_dir(): unlink()");
407 free(tmpdirname);
408 free(dirname);
409 free(filename);
410 free(subdir);
411 return 1;
412 }
413 sync();
414 }
415
416 sprintf(filename, "%s/%s", dirname, "makefile");
417 dprt("pid[%d]: removing %s\n", gettid(), filename);
418 if (unlink(filename)) {
419 perror
420 ("rm_file_dir() cound not remove makefile unlink()");
421 free(tmpdirname);
422 free(dirname);
423 free(filename);
424 free(subdir);
425 return 1;
426 }
427 sync();
428
429 /* the last directory does not have any more sub directories */
430 /* nothing to remove. */
431 dprt("pid[%d]: in directory count(dircnt): %d\n", gettid(),
432 dircnt);
433 dprt("pid[%d]: last directory(numsdir): %d\n", gettid(),
434 numsdir);
435 if (dircnt < numsdir) {
436 /* remove the sub directory */
437 sprintf(subdir, "%s/%ld.%d", dirname, gettid(), dircnt);
438 dprt("pid[%d]: removing subdirectory: %s\n", gettid(),
439 subdir);
440 if (rmdir(subdir) == -1) {
441 perror("rm_file_dir() rmdir()");
442 free(tmpdirname);
443 free(dirname);
444 free(filename);
445 free(subdir);
446 return 1;
447 }
448 sync();
449 }
450 }
451
452 free(tmpdirname);
453 free(dirname);
454 free(filename);
455 free(subdir);
456 return 0;
457 }
458
459 /******************************************************************************/
460 /* */
461 /* Function: crte_mk_rm */
462 /* */
463 /* Description: This function gets executed by each thread that is created. */
464 /* crte_mk_rm() created the directory tree, polpulates it with */
465 /* ".c" files and a makefile that will compile the ".c" files and*/
466 /* initiate the makefile in the subdirectory under it. Once the */
467 /* c source files are compiled it will remove them. */
468 /* */
469 /* Input: The argument pointer contains the following. */
470 /* arg[0] - number of directories to create, depth of the tree. */
471 /* arg[1] - number of ".c" files to create in each dir branch. */
472 /* */
473 /* Return: -1 on failure */
474 /* 0 on success */
475 /* */
476 /******************************************************************************/
crte_mk_rm(void * args)477 static void *crte_mk_rm(void *args)
478 {
479 int dircnt; /* index to the number of subdirectories */
480 int fd; /* file discriptor of the files genetated */
481 int filecnt; /* index to the number of ".c" files created */
482 int numchar[2]; /* number of characters written to buffer */
483 char *dirname; /* name of the directory/idirectory tree */
484 char *tmpdirname; /* name of a temporary directory, for swaping */
485 char *cfilename; /* name of the ".c" file created */
486 char *mkfilename; /* name of the makefile - which is "makefile" */
487 char *hostname; /* hostname of the client machine */
488 char *prog_buf; /* buffer containing contents of the ".c" file */
489 char *make_buf; /* buffer the contents of the makefile */
490 char *pwd; /* contains the current working directory */
491 long *locargptr = /* local pointer to arguments */
492 (long *)args;
493 volatile int exit_val = 0; /* exit value of the pthreads */
494
495 if ((dirname = malloc(sizeof(char) * 2048)) == NULL) { /* just paranoid */
496 perror("crte_mk_rm(): dirname malloc()");
497 PTHREAD_EXIT(-1);
498 }
499
500 if ((tmpdirname = malloc(sizeof(char) * 2048)) == NULL) {
501 perror("crte_mk_rm(): tmpdirname malloc()");
502 PTHREAD_EXIT(-1);
503 }
504
505 if ((cfilename = malloc(sizeof(char) * 2048)) == NULL) {
506 perror("crte_mk_rm(): cfilename malloc()");
507 PTHREAD_EXIT(-1);
508 }
509
510 if ((mkfilename = malloc(sizeof(char) * 2048)) == NULL) {
511 perror("crte_mk_rm(): mkfilename malloc()");
512 PTHREAD_EXIT(-1);
513 }
514
515 if ((prog_buf = malloc(sizeof(char) * 4096)) == NULL) {
516 perror("crte_mk_rm(): prog_buf malloc()");
517 PTHREAD_EXIT(-1);
518 }
519
520 if ((pwd = malloc(PATH_MAX)) == NULL) {
521 perror("crte_mk_rm(): pwd malloc()");
522 PTHREAD_EXIT(-1);
523 }
524
525 if ((hostname = malloc(sizeof(char) * 1024)) == NULL) {
526 perror("crte_mk_rm(): hostname malloc()");
527 PTHREAD_EXIT(-1);
528 }
529
530 if (gethostname(hostname, 255) == -1) {
531 perror("crte_mk_rm(): gethostname()");
532 PTHREAD_EXIT(-1);
533 }
534 if (!getcwd(pwd, PATH_MAX)) {
535 perror("crte_mk_rm(): getcwd()");
536 PTHREAD_EXIT(-1);
537 }
538
539 numchar[0] = sprintf(prog_buf,
540 "main()\n{\n\t printf(\"hello world\");\n}\n");
541
542 for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++) {
543 /* First create the base directory, then create the subdirectories */
544 if (dircnt == 0)
545 sprintf(dirname, "%s.%ld", hostname, gettid());
546 else {
547 sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(),
548 dircnt);
549 sprintf(dirname, "%s", tmpdirname);
550 }
551 sync();
552
553 dprt("pid[%d] creating directory: %s\n", gettid(), dirname);
554 if (mkdir(dirname, 0777) == -1) {
555 perror("crte_mk_rm(): mkdir()");
556 PTHREAD_EXIT(-1);
557 }
558 }
559
560 sync();
561 usleep(10);
562 for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++) {
563 if (dircnt == 0)
564 sprintf(dirname, "%s/%s.%ld", pwd, hostname, gettid());
565 else {
566 sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(),
567 dircnt);
568 sprintf(dirname, "%s", tmpdirname);
569 }
570 sync();
571 if ((make_buf = malloc(sizeof(char) * 4096)) == NULL) {
572 perror("crte_mk_rm(): make_buf malloc()");
573 PTHREAD_EXIT(-1);
574 }
575 sprintf(mkfilename, "%s/makefile", dirname);
576 {
577 /* HACK! I could not write "%.c" to the makefile */
578 /* there is probably a correct way to do it */
579 char *dotc = malloc(10);
580 dotc = ".c";
581 sync();
582 usleep(10);
583 if (dircnt == (locargptr[0] - 1)) {
584 numchar[1] = sprintf(make_buf,
585 "CFLAGS := -O -w -g\n"
586 "SUBDIRS = %ld.%d\n"
587 "SRCS=$(wildcard *.c)\n"
588 "TARGETS=$(patsubst %%%s,\%%,$(SRCS))\n"
589 "all:\t $(TARGETS)\n"
590 "clean:\n"
591 "\trm -f $(TARGETS)\n",
592 gettid(), dircnt + 1,
593 dotc);
594 } else {
595 numchar[1] = sprintf(make_buf,
596 "CFLAGS := -O -w -g\n"
597 "SUBDIRS = %ld.%d\n"
598 "SRCS=$(wildcard *.c)\n"
599 "TARGETS=$(patsubst %%%s,\%%,$(SRCS))\n\n\n"
600 "all:\t $(TARGETS)\n"
601 "\t@for i in $(SUBDIRS); do $(MAKE) -C $$i ; done\n\n"
602 "clean:\n"
603 "\trm -f $(TARGETS)\n"
604 "\t@for i in $(SUBDIRS); do $(MAKE) -C $$i clean ; done\n",
605 gettid(), dircnt + 1,
606 dotc);
607 }
608 }
609
610 sync();
611 usleep(10);
612 dprt("pid[%d]: creating in dir: %s\n", gettid(), mkfilename);
613 /* create the makefile, complies .c files and initiates make in */
614 /* subdirectories. */
615 if ((fd = open(mkfilename, O_CREAT | O_RDWR,
616 S_IRWXU | S_IRWXG | S_IRWXO)) == -1) {
617 dprt(" pid[%d]: failed to create makefile\n", gettid());
618 dprt("pid[%d]: failed in directory %s\n", gettid(),
619 dirname);
620 perror("crte_mk_rm() failed creating makefile: open()");
621 PTHREAD_EXIT(-1);
622 } else {
623 sync();
624 if (write(fd, make_buf, numchar[1]) == -1) {
625 perror("crte_mk_rm(): write()");
626 PTHREAD_EXIT(-1);
627 }
628
629 free(make_buf);
630
631 if (close(fd) == -1) {
632 perror("crte_mk_rm(): close()");
633 PTHREAD_EXIT(-1);
634 }
635 }
636 }
637
638 for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++) {
639 if (dircnt == 0)
640 sprintf(dirname, "%s/%s.%ld", pwd, hostname, gettid());
641 else {
642 sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(),
643 dircnt);
644 sprintf(dirname, "%s", tmpdirname);
645 }
646 sync();
647 /* In each directory create N ".c" files and a makefile. */
648 for (filecnt = 0; filecnt < (int)locargptr[1]; filecnt++) {
649 sprintf(cfilename, "%s/%ld.%d.%d.c", dirname, gettid(),
650 dircnt, filecnt);
651 dprt("pid[%d]: creating file: %s\n", gettid(),
652 cfilename);
653 if ((fd =
654 open(cfilename, O_CREAT | O_RDWR,
655 S_IRWXU | S_IRWXG | S_IRWXO)) == -1) {
656 fprintf(stderr,
657 "open() failed to create file %s\n",
658 cfilename);
659 perror
660 ("crte_mk_rm(): failed creating .c files: open()");
661 PTHREAD_EXIT(-1);
662 } else {
663 sync();
664 /* write the code, this program prints hello world */
665 if (write(fd, prog_buf, numchar[0]) == -1) {
666 perror("crte_mk_rm(): write()");
667 PTHREAD_EXIT(-1);
668 }
669
670 fsync(fd);
671
672 if (close(fd) == -1) {
673 perror("crte_mk_rm(): close()");
674 PTHREAD_EXIT(-1);
675 }
676 }
677
678 }
679 }
680
681 if (init_compile(MAKE_EXE, pwd, hostname) == 1) {
682 fprintf(stderr, "init_compile() make failed\n");
683 PTHREAD_EXIT(-1);
684 } else {
685 if (init_compile(MAKE_CLEAN, pwd, hostname) == 1) {
686 fprintf(stderr, "init_compile() make clean failed\n");
687 PTHREAD_EXIT(-1);
688 }
689 }
690
691 sync();
692 /* remove all the files makefiles and subdirecotries */
693 if (rm_file_dir((int)locargptr[0], (int)locargptr[1], hostname, pwd)) {
694 fprintf(stderr, "crte_mk_rm(): rm_file_dir() failed\n");
695 PTHREAD_EXIT(-1);
696 }
697 /* if it made it this far exit with success */
698 PTHREAD_EXIT(0);
699 }
700
701 /******************************************************************************/
702 /* */
703 /* Function: main */
704 /* */
705 /* Description: This is the entry point to the program. This function will */
706 /* parse the input arguments and set the values accordingly. If */
707 /* no arguments (or desired) are provided default values are used*/
708 /* refer the usage function for the arguments that this program */
709 /* takes. It also creates the threads which do most of the dirty */
710 /* work. If the threads exits with a value '0' the program exits */
711 /* with success '0' else it exits with failure '-1'. */
712 /* */
713 /* Return: -1 on failure */
714 /* 0 on success */
715 /* */
716 /******************************************************************************/
main(int argc,char ** argv)717 int main(int argc, /* number of input parameters */
718 char **argv)
719 { /* pointer to the command line arguments. */
720 int c; /* command line options */
721 int num_thrd = MAXT; /* number of threads to create */
722 int num_dirs = MAXD; /* number of subdirectories to create */
723 int num_files = MAXF; /* number of files in each subdirectory */
724 int thrd_ndx; /* index into the array of thread ids */
725 void *th_status; /* exit status of LWP's */
726 pthread_t thrdid[30]; /* maxinum of 30 threads allowed */
727 long chld_args[3]; /* arguments to the thread function */
728 extern int optopt; /* options to the program */
729
730 while ((c = getopt(argc, argv, "d:f:ht:")) != -1) {
731 switch (c) {
732 case 'd': /* specify how deep the tree needs to grow */
733 if ((num_dirs = atoi(optarg)) == 0)
734 OPT_MISSING(argv[0], optopt);
735 else if (num_dirs < 0) {
736 fprintf(stdout,
737 "WARNING: bad argument. Using default\n");
738 num_dirs = MAXD;
739 }
740 break;
741 case 'f': /* how many ".c" files in each directory. */
742 if ((num_files = atoi(optarg)) == 0)
743 OPT_MISSING(argv[0], optopt);
744 else if (num_files < 0) {
745 fprintf(stdout,
746 "WARNING: bad argument. Using default\n");
747 num_files = MAXF;
748 }
749 break;
750 case 'h':
751 usage(argv[0]);
752 break;
753 case 't':
754 if ((num_thrd = atoi(optarg)) == 0)
755 OPT_MISSING(argv[0], optopt);
756 else if (num_thrd < 0) {
757 fprintf(stdout,
758 "WARNING: bad argument. Using default\n");
759 num_thrd = MAXT;
760 }
761 break;
762 default:
763 usage(argv[0]);
764 break;
765 }
766 }
767
768 chld_args[0] = num_dirs;
769 chld_args[1] = num_files;
770
771 for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
772 if (pthread_create
773 (&thrdid[thrd_ndx], NULL, crte_mk_rm, chld_args)) {
774 perror("crte_mk_rm(): pthread_create()");
775 exit(-1);
776 }
777 }
778
779 sync();
780
781 for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
782 if (pthread_join(thrdid[thrd_ndx], &th_status) != 0) {
783 perror("crte_mk_rm(): pthread_join()");
784 exit(-1);
785 } else {
786 dprt("WE ARE HERE %d\n", __LINE__);
787 if (th_status == (void *)-1) {
788 fprintf(stderr,
789 "thread [%ld] - process exited with errors\n",
790 thrdid[thrd_ndx]);
791 exit(-1);
792 }
793 }
794 }
795 return (0);
796 }
797