Update of /cvsroot/ltp/ltp/lib/ltp In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv3504/lib/ltp Added Files: Tag: makefile-upgrade Makefile Makefile.inc dataascii.c databin.c datapid.c file_lock.c forker.c get_high_address.c libtestsuite.c ltp.pc open_flags.c parse_opts.c pattern.c random_range.c rmobj.c search_path.c self_exec.c str_to_bytes.c string_to_tokens.c tlibio.c tst_cwd_has_free.c tst_is_cwd_nfs.c tst_is_cwd_tmpfs.c tst_kvercmp.c tst_res.c tst_sig.c tst_tmpdir.c write_log.c Log Message: - Move libraries and headers to more apppropriate locations. - Checkin updated runtest files. - Merge changes for common code between hugemap and the syscall's versions of li bipc. --- NEW FILE: libtestsuite.c --- /* * * 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 */ /* * NAME * libtestsuite.c * * DESCRIPTION * file containing generic routines which are used by some of the LTP * testsuite tests. Currently, the following routines are present in * this library: * * my_getpwnam(), do_file_setup() * * HISTORY * 11/03/2008 Renaud Lottiaux (Ren...@ke...) * - Add the following functions to synchronise father and sons processes * sync_pipe_create(), sync_pipe_wait(), sync_pipe_notify() */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <pwd.h> #include <errno.h> #include <fcntl.h> #include "test.h" #include "usctest.h" struct passwd * my_getpwnam(char *name) { struct passwd *saved_pwent; struct passwd *pwent; if ((pwent = getpwnam(name)) == NULL) { perror("getpwnam"); tst_brkm(TBROK, NULL, "getpwnam() failed"); } saved_pwent = (struct passwd *)malloc(sizeof(struct passwd)); *saved_pwent = *pwent; return(saved_pwent); } void do_file_setup(char *fname) { int fd; if ((fd = open(fname,O_RDWR|O_CREAT,0700)) == -1) { tst_resm(TBROK, "open(%s, O_RDWR|O_CREAT,0700) Failed, " "errno=%d : %s", fname, errno, strerror(errno)); } if (close(fd) == -1) { tst_resm(TWARN, "close(%s) Failed on file create, errno=%d : " "%s", fname, errno, strerror(errno)); } } int sync_pipe_create(int fd[]) { return pipe (fd); } int sync_pipe_close(int fd[]) { int r = 0; if (fd[0] != -1) r = close (fd[0]); if (fd[1] != -1) r |= close (fd[1]); return r; } int sync_pipe_wait(int fd[]) { char buf; int r; if (fd[1] != -1) { close (fd[1]); fd[1] = -1; } r = read (fd[0], &buf, 1); if ((r != 1) || (buf != 'A')) return -1; return 0; } int sync_pipe_notify(int fd[]) { char buf = 'A'; int r; if (fd[0] != -1) { close (fd[0]); fd[0] = -1; } r = write (fd[1], &buf, 1); if (r != 1) return -1; return 0; } --- NEW FILE: pattern.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ #include <string.h> #include "pattern.h" /* * The routines in this module are used to fill/check a data buffer * with/against a known pattern. */ int pattern_check(buf, buflen, pat, patlen, patshift) char *buf; int buflen; char *pat; int patlen; int patshift; { int nb, ncmp, nleft; char *cp; if (patlen) patshift = patshift % patlen; cp = buf; nleft = buflen; /* * The following 2 blocks of code are to compare the first patlen * bytes of buf. We need 2 checks if patshift is > 0 since we * must check the last (patlen - patshift) bytes, and then the * first (patshift) bytes. */ nb = patlen - patshift; if (nleft < nb) { return (memcmp(cp, pat + patshift, nleft) ? -1 : 0); } else { if (memcmp(cp, pat + patshift, nb)) return -1; nleft -= nb; cp += nb; } if (patshift > 0) { nb = patshift; if (nleft < nb) { return (memcmp(cp, pat, nleft) ? -1 : 0); } else { if (memcmp(cp, pat, nb)) return -1; nleft -= nb; cp += nb; } } /* * Now, verify the rest of the buffer using the algorithm described * in the function header. */ ncmp = cp - buf; while (ncmp < buflen) { nb = (ncmp < nleft) ? ncmp : nleft; if (memcmp(buf, cp, nb)) return -1; cp += nb; ncmp += nb; nleft -= nb; } return 0; } int pattern_fill(buf, buflen, pat, patlen, patshift) char *buf; int buflen; char *pat; int patlen; int patshift; { int trans, ncopied, nleft; char *cp; if (patlen) patshift = patshift % patlen; cp = buf; nleft = buflen; /* * The following 2 blocks of code are to fill the first patlen * bytes of buf. We need 2 sections if patshift is > 0 since we * must first copy the last (patlen - patshift) bytes into buf[0]..., * and then the first (patshift) bytes of pattern following them. */ trans = patlen - patshift; if (nleft < trans) { memcpy(cp, pat + patshift, nleft); return 0; } else { memcpy(cp, pat + patshift, trans); nleft -= trans; cp += trans; } if (patshift > 0) { trans = patshift; if (nleft < trans) { memcpy(cp, pat, nleft); return 0; } else { memcpy(cp, pat, trans); nleft -= trans; cp += trans; } } /* * Now, fill the rest of the buffer using the algorithm described * in the function header comment. */ ncopied = cp - buf; while (ncopied < buflen) { trans = (ncopied < nleft) ? ncopied : nleft; memcpy(cp, buf, trans); cp += trans; ncopied += trans; nleft -= trans; } return(0); } --- NEW FILE: tst_sig.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ /* $Id: tst_sig.c,v 1.1.2.1 2009/01/14 03:22:29 yaberauneya Exp $ */ /***************************************************************************** OS Testing - Silicon Graphics, Inc. FUNCTION IDENTIFIER : tst_sig Set up for unexpected signals. AUTHOR : David D. Fenner CO-PILOT : Bill Roske DATE STARTED : 06/06/90 This module may be linked with c-modules requiring unexpected signal handling. The parameters to tst_sig are as follows: fork_flag - set to FORK or NOFORK depending upon whether the calling program executes a fork() system call. It is normally the case that the calling program treats SIGCLD as an expected signal if fork() is being used. handler - a pointer to the unexpected signal handler to be executed after an unexpected signal has been detected. If handler is set to DEF_HANDLER, a default handler is used. This routine should be declared as function returning an int. cleanup - a pointer to a cleanup routine to be executed by the unexpected signal handler before tst_exit is called. This parameter is set to NULL if no cleanup routine is required. An external variable, T_cleanup is set so that other user-defined handlers have access to the cleanup routine. This routine should be declared as returning type void. ***************************************************************************/ #include <errno.h> #include <string.h> #include <signal.h> #include <unistd.h> #include "test.h" #define MAXMESG 150 /* size of mesg string sent to tst_res */ void (*T_cleanup)(); /* pointer to cleanup function */ /**************************************************************************** * STD_COPIES is defined in parse_opts.c but is externed here in order to * test whether SIGCHILD should be ignored or not. ***************************************************************************/ extern int STD_COPIES; static void def_handler(); /* default signal handler */ static void (*tst_setup_signal( int, void (*)(int)))(int); /**************************************************************************** * tst_sig() : set-up to catch unexpected signals. fork_flag is set to NOFORK * if SIGCLD is to be an "unexpected signal", otherwise it is set to * FORK. cleanup points to a cleanup routine to be executed before * tst_exit is called (cleanup is set to NULL if no cleanup is desired). * handler is a pointer to the signal handling routine (if handler is * set to NULL, a default handler is used). ***************************************************************************/ void tst_sig(int fork_flag, void (*handler)(), void (*cleanup)()) { char mesg[MAXMESG]; /* message buffer for tst_res */ int sig; #ifdef _SC_SIGRT_MIN long sigrtmin, sigrtmax; #endif /* * save T_cleanup and handler function pointers */ T_cleanup = cleanup; /* used by default handler */ if (handler == DEF_HANDLER) { /* use default handler */ handler = def_handler; } #ifdef _SC_SIGRT_MIN sigrtmin = sysconf(_SC_SIGRT_MIN); sigrtmax = sysconf(_SC_SIGRT_MAX); #endif /* * now loop through all signals and set the handlers */ for (sig = 1; sig < NSIG; sig++) { /* * SIGKILL is never unexpected. * SIGCLD is only unexpected when * no forking is being done. * SIGINFO is used for file quotas and should be expected */ #ifdef _SC_SIGRT_MIN if (sig >= sigrtmin && sig <= sigrtmax) continue; #endif switch (sig) { case SIGKILL: case SIGSTOP: case SIGCONT: #if !defined(_SC_SIGRT_MIN) && defined(__SIGRTMIN) && defined(__SIGRTMAX) /* Ignore all real-time signals */ case __SIGRTMIN: case __SIGRTMIN+1: case __SIGRTMIN+2: case __SIGRTMIN+3: case __SIGRTMIN+4: case __SIGRTMIN+5: case __SIGRTMIN+6: case __SIGRTMIN+7: case __SIGRTMIN+8: case __SIGRTMIN+9: case __SIGRTMIN+10: case __SIGRTMIN+11: case __SIGRTMIN+12: case __SIGRTMIN+13: case __SIGRTMIN+14: case __SIGRTMIN+15: /* __SIGRTMIN is 37 on HPPA rather than 32 * * as on i386, etc. */ #if !defined(__hppa__) case __SIGRTMAX-15: case __SIGRTMAX-14: case __SIGRTMAX-13: case __SIGRTMAX-12: case __SIGRTMAX-11: #endif case __SIGRTMAX-10: case __SIGRTMAX-9: case __SIGRTMAX-8: case __SIGRTMAX-7: case __SIGRTMAX-6: case __SIGRTMAX-5: case __SIGRTMAX-4: case __SIGRTMAX-3: case __SIGRTMAX-2: case __SIGRTMAX-1: case __SIGRTMAX: #endif #ifdef CRAY case SIGINFO: case SIGRECOVERY: /* allow chkpnt/restart */ #endif /* CRAY */ #ifdef SIGSWAP case SIGSWAP: #endif /* SIGSWAP */ #ifdef SIGCKPT case SIGCKPT: #endif #ifdef SIGRESTART case SIGRESTART: #endif /* * pthread-private signals SIGPTINTR and SIGPTRESCHED. * Setting a handler for these signals is disallowed when * the binary is linked against libpthread. */ #ifdef SIGPTINTR case SIGPTINTR: #endif /* SIGPTINTR */ #ifdef SIGPTRESCHED case SIGPTRESCHED: #endif /* SIGPTRESCHED */ #ifdef _SIGRESERVE case _SIGRESERVE: #endif #ifdef _SIGDIL case _SIGDIL: #endif #ifdef _SIGCANCEL case _SIGCANCEL: #endif #ifdef _SIGGFAULT case _SIGGFAULT: #endif break; case SIGCLD: if ( fork_flag == FORK || STD_COPIES > 1) continue; default: if (tst_setup_signal(sig, handler) == SIG_ERR) { (void) sprintf(mesg, "signal() failed for signal %d. error:%d %s.", sig, errno, strerror(errno)); tst_resm(TWARN, mesg); } break; } #ifdef __sgi /* On irix (07/96), signal() fails when signo is 33 or higher */ if ( sig+1 >= 33 ) break; #endif /* __sgi */ } /* endfor */ } /**************************************************************************** * def_handler() : default signal handler that is invoked when * an unexpected signal is caught. ***************************************************************************/ static void def_handler(int sig) { /* * Break remaining test cases, do any cleanup, then exit */ tst_brkm(TBROK, 0, "Unexpected signal %d received.", sig); /* now cleanup and exit */ if (T_cleanup) { (*T_cleanup)(); } tst_exit(); } /* * tst_setup_signal - A function like signal(), but we have * control over its personality. */ static void (*tst_setup_signal( int sig, void (*handler)(int)))(int) { struct sigaction my_act,old_act; int ret; my_act.sa_handler = handler; my_act.sa_flags = SA_RESTART; sigemptyset(&my_act.sa_mask); ret = sigaction(sig, &my_act, &old_act); if ( ret == 0 ) return( old_act.sa_handler ); else return( SIG_ERR ); } --- NEW FILE: Makefile --- include Makefile.inc ifeq ($(shell uname -s),HP-UX) CFLAGS += -Ae -D_LARGEFILE64_SOURCE +DA1.1 endif CFLAGS += $(if $(UCLINUX),-DUCLINUX) LIB := $(srcdir)/lib/libltp.a DESTDIR := $(prefix)/lib MAKE_TARGETS := $(LIB) MAKE_DEPS := $(patsubst %.c,%.o,$(wildcard *.c)) install: set -e; for i in $(MAKE_TARGETS); do \ $(INSTALL) -D -m 0775 $$i $(DESTDIR)/$$i; \ done; \ $(INSTALL) -D ltp.pc /usr/share/pkgconfig/ltp.pc $(eval $(__generic_lib)) --- NEW FILE: string_to_tokens.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ /********************************************************** * * OS Testing - Silicon Graphics, Inc. * * FUNCTION NAME : string_to_tokens * * FUNCTION TITLE : Break a string into its tokens * * SYNOPSIS: * * int string_to_tokens(arg_string, arg_array, array_size, separator) * char *arg_string; * char *arg_array[]; * int array_size; * char *separator; * * AUTHOR : Richard Logan * * DATE : 10/94 * * INITIAL RELEASE : UNICOS 7.0 * * DESCRIPTION * This function parses the string 'arg_string', placing pointers to * the 'separator' separated tokens into the elements of 'arg_array'. * The array is terminated with a null pointer. * 'arg_array' must contains at least 'array_size' elements. * Only the first 'array_size' minus one tokens will be placed into * 'arg_array'. If there are more than 'array_size'-1 tokens, the rest are * ignored by this routine. * * RETURN VALUE * This function returns the number of 'separator' separated tokens that * were found in 'arg_string'. * If 'arg_array' or 'separator' is NULL or 'array_size' is less than 2, -1 is returned. * * WARNING * This function uses strtok() to parse 'arg_string', and thus * physically alters 'arg_string' by placing null characters where the * separators originally were. * * *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ #include <stdio.h> #include <string.h> /* for string functions */ #include "string_to_tokens.h" int string_to_tokens(char *arg_string, char *arg_array[], int array_size, char *separator) { int num_toks = 0; /* number of tokens found */ char *strtok(); if ( arg_array == NULL || array_size <= 1 || separator == NULL ) return -1; /* * Use strtok() to parse 'arg_string', placing pointers to the * individual tokens into the elements of 'arg_array'. */ if ( (arg_array[num_toks] = strtok(arg_string, separator)) == NULL ) { return 0; } for (num_toks=1;num_toks<array_size; num_toks++) { if ( (arg_array[num_toks] = strtok(NULL, separator)) == NULL ) break; } if ( num_toks == array_size ) arg_array[num_toks] = NULL; /* * Return the number of tokens that were found in 'arg_string'. */ return(num_toks); } /* end of string_to_tokens */ --- NEW FILE: tst_is_cwd_tmpfs.c --- /* * AUTHOR * Ricky Ng-Adam <rn...@ya...>, 2005-01-01 * * DESCRIPTION * Check if current directory is on a tmpfs filesystem * If current directory is tmpfs, return 1 * If current directory is NOT tmpfs, return 0 * * */ #include <sys/vfs.h> #define TMPFS_MAGIC 0x01021994 /* man 2 statfs */ int tst_is_cwd_tmpfs() { struct statfs sf; statfs(".", &sf); /* Verify that the file is not on a tmpfs (in-memory) filesystem */ return sf.f_type == TMPFS_MAGIC?1:0; } --- NEW FILE: search_path.c --- /* $Header: /cvsroot/ltp/ltp/lib/ltp/Attic/search_path.c,v 1.1.2.1 2009/01/14 03:22:29 yaberauneya Exp $ */ /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ /********************************************************** * * UNICOS Feature Test and Evaluation - Cray Research, Inc. * * FUNCTION NAME : search_path * * FUNCTION TITLE : search PATH locations for desired filename * * SYNOPSIS: * int search_path(cmd, res_path, access_mode, fullpath) * char *cmd; * char *res_path; * int access_mode; * int fullpath; * * AUTHOR : Richard Logan * * INITIAL RELEASE : UNICOS 7.0 * * DESCRIPTION * Search_path will walk through PATH and attempt to find "cmd". If cmd is * a full or relative path, it is checked but PATH locations are not scanned. * search_path will put the resulting path in res_path. It is assumed * that res_path points to a string that is at least PATH_MAX * (or MAXPATHLEN on the suns) in size. Access_mode is just as is * says, the mode to be used on access to determine if cmd can be found. * If fullpath is set, res_path will contain the full path to cmd. * If it is not set, res_path may or may not contain the full path to cmd. * If fullpath is not set, the path in PATH prepended to cmd is used, * which could be a relative path. If fullpath is set, the current * directory is prepended to path/cmd before access is called. * If cmd is found, search_path will return 0. If cmd cannot be * found, 1 is returned. If an error has occurred, -1 is returned * and an error mesg is placed in res_path. * If the length of path/cmd is larger then PATH_MAX, then that path * location is skipped. * *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/param.h> #include <sys/stat.h> struct stat stbuf; #ifndef AS_CMD #define AS_CMD 0 #endif /* * Make sure PATH_MAX is defined. Define it to MAXPATHLEN, if set. Otherwise * set it to 1024. */ #ifndef PATH_MAX #ifndef MAXPATHLEN #define PATH_MAX 1024 #else /* MAXPATHLEN */ #define PATH_MAX MAXPATHLEN #endif /* MAXPATHLEN */ #endif /* PATH_MAX */ #if AS_CMD main(argc, argv) int argc; char **argv; { char path[PATH_MAX]; int ind; if (argc <= 1 ) { printf("missing argument\n"); exit(1); } for(ind=1;ind < argc; ind++) { if ( search_path(argv[ind], path, F_OK, 0) < 0 ) { printf("ERROR: %s\n", path); } else { printf("path of %s is %s\n", argv[ind], path); } } } #endif /* */ int search_path(cmd, res_path, access_mode, fullpath) char *cmd; /* The requested filename */ char *res_path; /* The resulting path or error mesg */ int access_mode; /* the mode used by access(2) */ int fullpath; /* if set, cwd will be prepended to all non-full paths */ { char *cp; /* used to scan PATH for directories */ int ret; /* return value from access */ char *pathenv; char tmppath[PATH_MAX]; char curpath[PATH_MAX]; char *path; int lastpath; int toolong=0; #if DEBUG printf("search_path: cmd = %s, access_mode = %d, fullpath = %d\n", cmd, access_mode, fullpath); #endif /* * full or relative path was given */ if ( (cmd[0] == '/') || ( (cp=strchr(cmd, '/')) != NULL )) { if ( access(cmd, access_mode) == 0 ) { if ( cmd[0] != '/' ) { /* relative path */ if ( getcwd(curpath, PATH_MAX) == NULL ) { strcpy(res_path, curpath); return -1; } if ( (strlen(curpath) + strlen(cmd) + 1) > (size_t)PATH_MAX ) { sprintf(res_path, "cmd (as relative path) and cwd is longer than %d", PATH_MAX); return -1; } sprintf(res_path, "%s/%s", curpath, cmd); } else strcpy(res_path, cmd); return 0; } else { sprintf(res_path, "file %s not found", cmd); return -1; } } /* get the PATH variable */ if ( (pathenv=getenv("PATH")) == NULL) { /* no path to scan, return */ sprintf(res_path, "Unable to get PATH env. variable"); return -1; } /* * walk through each path in PATH. * Each path in PATH is placed in tmppath. * pathenv cannot be modified since it will affect PATH. * If a signal came in while we have modified the PATH * memory, we could create a problem for the caller. */ curpath[0]='\0'; cp = pathenv; path = pathenv; lastpath = 0; for (;;) { if ( lastpath ) break; if ( cp != pathenv ) path = ++cp; /* already set on first iteration */ /* find end of current path */ for (; ((*cp != ':') && (*cp != '\0')); cp++); /* * copy path to tmppath so it can be NULL terminated * and so we do not modify path memory. */ strncpy(tmppath, path, (cp-path) ); tmppath[cp-path]='\0'; #if DEBUG printf("search_path: tmppath = %s\n", tmppath); #endif if ( *cp == '\0' ) lastpath=1; /* this is the last path entry */ /* Check lengths so not to overflow res_path */ if ( strlen(tmppath) + strlen(cmd) + 2 > (size_t)PATH_MAX ) { toolong++; continue; } sprintf(res_path, "%s/%s", tmppath, cmd); #if DEBUG printf("search_path: res_path = '%s'\n", res_path); #endif /* if the path is not full at this point, prepend the current * path to get the full path. * Note: this could not be wise to do when under a protected * directory. */ if ( fullpath && res_path[0] != '/' ) { /* not a full path */ if ( curpath[0] == '\0' ) { if ( getcwd(curpath, PATH_MAX) == NULL ) { strcpy(res_path, curpath); return -1; } } if ( (strlen(curpath) + strlen(res_path) + 2) > (size_t)PATH_MAX ) { toolong++; continue; } sprintf(tmppath, "%s/%s", curpath, res_path); strcpy(res_path, tmppath); #if DEBUG printf("search_path: full res_path= '%s'\n", res_path); #endif } if ( (ret=access(res_path, access_mode)) == 0 ) { #if DEBUG printf("search_path: found res_path = %s\n", res_path); #endif return 0; } } /* return failure */ if ( toolong ) sprintf(res_path, "Unable to find file, %d path/file strings were too long", toolong); else strcpy(res_path, "Unable to find file"); return 1; /* not found */ } --- NEW FILE: str_to_bytes.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ #include <stdio.h> #include <sys/param.h> #include "str_to_bytes.h" /**************************************************************************** * str_to_bytes(s) * * Computes the number of bytes described by string s. s is assumed to be * a base 10 positive (ie. >= 0) number followed by an optional single * character multiplier. The following multipliers are supported: * * char mult * ----------------- * b BSIZE or BBSIZE * k 1024 bytes * K 1024 * sizeof(long) * m 2^20 (1048576) * M 2^20 (1048576 * sizeof(long) * g 2^30 (1073741824) * G 2^30 (1073741824) * sizeof(long) * * for instance, "1k" and "1024" would both cause str_to_bytes to return 1024. * * Returns -1 if mult is an invalid character, or if the integer portion of * s is not a positive integer. * ****************************************************************************/ #if CRAY #define B_MULT BSIZE /* block size */ #elif sgi #define B_MULT BBSIZE /* block size */ #elif defined(__linux__) || defined(__sun) || defined(__hpux) #define B_MULT DEV_BSIZE /* block size */ #elif defined(_AIX) #define B_MULT UBSIZE #endif #define K_MULT 1024 /* Kilo or 2^10 */ #define M_MULT 1048576 /* Mega or 2^20 */ #define G_MULT 1073741824 /* Giga or 2^30 */ #define T_MULT 1099511627776 /* tera or 2^40 */ int str_to_bytes(s) char *s; { char mult, junk; int nconv; float num; nconv = sscanf(s, "%f%c%c", &num, &mult, &junk); if (nconv == 0 || nconv == 3 ) return -1; if (nconv == 1) return num; switch (mult) { case 'b': return (int)(num * (float)B_MULT); case 'k': return (int)(num * (float)K_MULT); case 'K': return (int)((num * (float)K_MULT) * sizeof(long)); case 'm': return (int)(num * (float)M_MULT); case 'M': return (int)((num * (float)M_MULT) * sizeof(long)); case 'g': return (int)(num * (float)G_MULT); case 'G': return (int)((num * (float)G_MULT) * sizeof(long)); default: return -1; } } long str_to_lbytes(s) char *s; { char mult, junk; long nconv; float num; nconv = sscanf(s, "%f%c%c", &num, &mult, &junk); if (nconv == 0 || nconv == 3 ) return -1; if (nconv == 1) return (long)num; switch (mult) { case 'b': return (long)(num * (float)B_MULT); case 'k': return (long)(num * (float)K_MULT); case 'K': return (long)((num * (float)K_MULT) * sizeof(long)); case 'm': return (long)(num * (float)M_MULT); case 'M': return (long)((num * (float)M_MULT) * sizeof(long)); case 'g': return (long)(num * (float)G_MULT); case 'G': return (long)((num * (float)G_MULT) * sizeof(long)); default: return -1; } } /* * Force 64 bits number when compiled as 32 IRIX binary. * This allows for a number bigger than 2G. */ long long str_to_llbytes(s) char *s; { char mult, junk; long nconv; double num; nconv = sscanf(s, "%lf%c%c", &num, &mult, &junk); if (nconv == 0 || nconv == 3 ) return -1; if (nconv == 1) return (long long)num; switch (mult) { case 'b': return (long long)(num * (float)B_MULT); case 'k': return (long long)(num * (float)K_MULT); case 'K': return (long long)((num * (float)K_MULT) * sizeof(long long)); case 'm': return (long long)(num * (float)M_MULT); case 'M': return (long long)((num * (float)M_MULT) * sizeof(long long)); case 'g': return (long long)(num * (float)G_MULT); case 'G': return (long long)((num * (float)G_MULT) * sizeof(long long)); default: return -1; } } #ifdef UNIT_TEST main(int argc, char **argv) { int ind; if (argc == 1 ) { fprintf(stderr, "missing str_to_bytes() parameteres\n"); exit(1); } for (ind=1; ind<argc; ind++) { printf("str_to_bytes(%s) returned %d\n", argv[ind], str_to_bytes(argv[ind])); printf("str_to_lbytes(%s) returned %ld\n", argv[ind], str_to_lbytes(argv[ind])); printf("str_to_llbytes(%s) returned %lld\n", argv[ind], str_to_llbytes(argv[ind])); } } #endif --- NEW FILE: tst_is_cwd_nfs.c --- /******************************************************************************/ /* 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 */ /******************************************************************************/ /* * AUTHOR * Kumar Gala <ga...@ke...>, 2007-11-14 * based on tst_is_cwd_tmpfs() * * DESCRIPTION * Check if current directory is on a nfs filesystem * If current directory is nfs, return 1 * If current directory is NOT nfs, return 0 * * */ /******************************************************************************/ #include <sys/vfs.h> #define NFS_MAGIC 0x6969 /* man 2 statfs */ int tst_is_cwd_nfs() { struct statfs sf; statfs(".", &sf); /* Verify that the file is not on a nfs filesystem */ return sf.f_type == NFS_MAGIC?1:0; } --- NEW FILE: file_lock.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <sys/param.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <sys/sysmacros.h> #include <string.h> /* memset, strerror */ #include "file_lock.h" #ifndef EFSEXCLWR #define EFSEXCLWR 503 #endif /* * String containing the last system call. * */ char Fl_syscall_str[128]; static char errmsg[256]; /*********************************************************************** * * Test interface to the fcntl system call. * It will loop if the LOCK_NB flags is NOT set. ***********************************************************************/ int file_lock(fd, flags, errormsg) int fd; int flags; char **errormsg; { register int cmd, ret; struct flock flocks; memset(&flocks, 0, sizeof(struct flock)); if (flags&LOCK_NB) cmd = F_SETLK; else cmd = F_SETLKW; flocks.l_whence = 0; flocks.l_start = 0; flocks.l_len = 0; if (flags&LOCK_UN) flocks.l_type = F_UNLCK; else if (flags&LOCK_EX) flocks.l_type = F_WRLCK; else if (flags&LOCK_SH) flocks.l_type = F_RDLCK; else { errno = EINVAL; if ( errormsg != NULL ) { sprintf(errmsg, "Programmer error, called file_lock with in valid flags\n"); *errormsg = errmsg; } return -1; } sprintf(Fl_syscall_str, "fcntl(%d, %d, &flocks): type:%d whence:%d, start:%lld len:%lld\n", fd, cmd, flocks.l_type, flocks.l_whence, (long long)flocks.l_start, (long long)flocks.l_len); while (1) { ret = fcntl(fd, cmd, &flocks); if ( ret < 0 ) { if ( cmd == F_SETLK ) switch (errno) { /* these errors are okay */ case EACCES: /* Permission denied */ case EINTR: /* interrupted system call */ #ifdef EFILESH case EFILESH: /* file shared */ #endif case EFSEXCLWR: /* File is write protected */ continue; /* retry getting lock */ } if ( errormsg != NULL ) { sprintf(errmsg, "fcntl(%d, %d, &flocks): errno:%d %s\n", fd, cmd, errno, strerror(errno)); *errormsg = errmsg; } return -1; } break; } return ret; } /* end of file_lock */ /*********************************************************************** * * Test interface to the fcntl system call. * It will loop if the LOCK_NB flags is NOT set. ***********************************************************************/ int record_lock(fd, flags, start, len, errormsg) int fd; int flags; int start; int len; char **errormsg; { register int cmd, ret; struct flock flocks; memset(&flocks, 0, sizeof(struct flock)); if (flags&LOCK_NB) cmd = F_SETLK; else cmd = F_SETLKW; flocks.l_whence = 0; flocks.l_start = start; flocks.l_len = len; if (flags&LOCK_UN) flocks.l_type = F_UNLCK; else if (flags&LOCK_EX) flocks.l_type = F_WRLCK; else if (flags&LOCK_SH) flocks.l_type = F_RDLCK; else { errno = EINVAL; if ( errormsg != NULL ) { sprintf(errmsg, "Programmer error, called record_lock with in valid flags\n"); *errormsg = errmsg; } return -1; } sprintf(Fl_syscall_str, "fcntl(%d, %d, &flocks): type:%d whence:%d, start:%lld len:%lld\n", fd, cmd, flocks.l_type, flocks.l_whence, (long long)flocks.l_start, (long long)flocks.l_len); while (1) { ret = fcntl(fd, cmd, &flocks); if ( ret < 0 ) { if ( cmd == F_SETLK ) switch (errno) { /* these errors are okay */ case EACCES: /* Permission denied */ case EINTR: /* interrupted system call */ #ifdef EFILESH case EFILESH: /* file shared */ #endif case EFSEXCLWR: /* File is write protected */ continue; /* retry getting lock */ } if ( errormsg != NULL ) { sprintf(errmsg, "fcntl(%d, %d, &flocks): errno:%d %s\n", fd, cmd, errno, strerror(errno)); *errormsg = errmsg; } return -1; } break; } return ret; } /* end of record_lock */ --- NEW FILE: tst_tmpdir.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ /* $Id: tst_tmpdir.c,v 1.1.2.1 2009/01/14 03:22:29 yaberauneya Exp $ */ /********************************************************** * * OS Testing - Silicon Graphics, Inc. * * FUNCTION NAME : tst_tmpdir, tst_rmdir * * FUNCTION TITLE : Create/remove a testing temp dir * * SYNOPSIS: * void tst_tmpdir(); * void tst_rmdir(); * * AUTHOR : Dave Fenner * * INITIAL RELEASE : UNICOS 8.0 * * DESCRIPTION * tst_tmpdir() is used to create a unique, temporary testing * directory, and make it the current working directory. * tst_rmdir() is used to remove the directory created by * tst_tmpdir(). * * Setting the env variable "TDIRECTORY" will override the creation * of a new temp dir. The directory specified by TDIRECTORY will * be used as the temporary directory, and no removal will be done * in tst_rmdir(). * * RETURN VALUE * Neither tst_tmpdir() or tst_rmdir() has a return value. * *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ #include <stdio.h> #include <errno.h> #include <stdlib.h> /* for getenv() */ #include <string.h> /* for string functions */ #include <unistd.h> /* for sysconf(), getcwd(), rmdir() */ #include <sys/types.h> /* for mkdir() */ #include <sys/stat.h> /* for mkdir() */ #include "test.h" #include "rmobj.h" /* * Define some useful macros. */ #define PREFIX_SIZE 4 #define STRING_SIZE 256 #define DIR_MODE 0777 /* mode of tmp dir that will be created */ #ifndef PATH_MAX #ifdef MAXPATHLEN #define PATH_MAX MAXPATHLEN #else #define PATH_MAX 1024 #endif #endif /* * Define function prototypes. */ static void tmpdir_cleanup(); /* * Define global variables. */ extern char *TCID; /* defined/initialized in main() */ extern int TST_TOTAL; /* defined/initialized in main() */ extern char *TESTDIR; /* the directory created; defined in */ /* tst_res.c */ /* * tst_tmpdir() - Create a unique temporary directory and chdir() to it. * It expects the caller to have defined/initialized the * TCID/TST_TOTAL global variables. The TESTDIR global * variable will be set to the directory that gets used * as the testing directory. * * NOTE: This function must be called BEFORE any activity * that would require CLEANUP. If tst_tmpdir() fails, it * cleans up afer itself and calls tst_exit() (i.e. does * not return). */ #undef FN_NAME #define FN_NAME "tst_tmpdir()" void tst_tmpdir() { char template[PATH_MAX]; /* template for mkstemp, mkdtemp */ int no_cleanup = 0; /* !0 means TDIRECTORY env var was set */ char *env_tmpdir; /* temporary storage for TMPDIR env var */ /* This is an AWEFUL hack to figure out if mkdtemp() is available */ #if defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2,2) # define HAVE_MKDTEMP 1 # else # define HAVE_MKDTEMP 0 int tfd; # endif #else # define HAVE_MKDTEMP 0 int tfd; #endif /* * If the TDIRECTORY env variable is not set, a temp dir will be * created. */ if ((TESTDIR = getenv(TDIRECTORY))) { /* * The TDIRECTORY env. variable is set, so no temp dir is created. * Also, no clean up will be done via tst_rmdir(). */ mkdir(TESTDIR,DIR_MODE); /*Try to create the directory if it does not exist already, user might forget to create one before exporting TDIRECTORY, Will fail if it already exists, no issues in that*/ no_cleanup++; #if UNIT_TEST printf("TDIRECTORY env var is set\n"); #endif } else { /* * Create a template for the temporary directory. Use the * environment variable TMPDIR if it is available, otherwise * use our default TEMPDIR. */ if ((env_tmpdir = getenv("TMPDIR"))) { snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", env_tmpdir, TCID); } else { snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID); } #if HAVE_MKDTEMP /* * Make the temporary directory in one shot using mkdtemp() */ if (mkdtemp(template) == NULL) tst_brkm(TBROK, tmpdir_cleanup, "%s: mkdtemp(%s) failed; errno = %d: %s", FN_NAME, template, errno, strerror(errno)); if ( (TESTDIR = strdup(template)) == NULL ) { //Error Handling for strdup() tst_brkm(TBROK, tmpdir_cleanup, "%s: strdup(%s) failed; errno = %d: %s", FN_NAME, template, errno, strerror(errno)); } #else /* * Make the template name, then the directory */ if ((tfd = mkstemp(template)) == -1) tst_brkm(TBROK, tmpdir_cleanup, "%s: mkstemp(%s) failed; errno = %d: %s", FN_NAME, template, errno, strerror(errno)); if ( close(tfd) == -1 ) { tst_brkm(TBROK, tmpdir_cleanup, "%s: close() failed; errno = %d: %s", FN_NAME, errno, strerror(errno)); } if ( unlink(template) == -1) { tst_brkm(TBROK, tmpdir_cleanup, "%s: unlink(%s) failed; errno = %d: %s", FN_NAME, template, errno, strerror(errno)); } if ( (TESTDIR = strdup(template)) == NULL ) { tst_brkm(TBROK, tmpdir_cleanup, "%s: strdup(%s) failed; errno = %d: %s", FN_NAME, template, errno, strerror(errno)); } if (mkdir(TESTDIR, DIR_MODE)) { /* If we start failing with EEXIST, wrap this section in * a loop so we can try again. */ tst_brkm(TBROK, tmpdir_cleanup, "%s: mkdir(%s, %#o) failed; errno = %d: %s", FN_NAME, TESTDIR, DIR_MODE, errno, strerror(errno)); } #endif /* * Change the group on this temporary directory to be that of the * gid of the person running the tests and permissions to 777. */ if ( chown(TESTDIR, -1, getgid()) == -1 ) tst_brkm(TBROK, tmpdir_cleanup, "chown(%s, -1, %d) failed; errno = %d: %s", TESTDIR, getgid(), errno, strerror(errno)); if ( chmod(TESTDIR,S_IRWXU | S_IRWXG | S_IRWXO) == -1 ) tst_brkm(TBROK, tmpdir_cleanup, "chmod(%s,777) failed; errno %d: %s", TESTDIR, errno, strerror(errno)); } #if UNIT_TEST printf("TESTDIR = %s\n", TESTDIR); #endif /* * Change to the temporary directory. If the chdir() fails, issue * TBROK messages for all test cases, attempt to remove the * directory (if it was created), and exit. If the removal also * fails, also issue a TWARN message. */ if ( chdir(TESTDIR) == -1 ) { tst_brkm(TBROK, NULL, "%s: chdir(%s) failed; errno = %d: %s", FN_NAME, TESTDIR, errno, strerror(errno) ); /* Try to remove the directory */ if ( !no_cleanup && rmdir(TESTDIR) == -1 ) tst_resm(TWARN, "%s: rmdir(%s) failed; errno = %d: %s", FN_NAME, TESTDIR, errno, strerror(errno) ); tmpdir_cleanup(); } #if UNIT_TEST printf("CWD is %s\n", getcwd((char *)NULL, PATH_MAX)); #endif /* * If we made through all this stuff, return. */ return; } /* tst_tmpdir() */ /* * * tst_rmdir() - Recursively remove the temporary directory created by * tst_tmpdir(). This function is intended ONLY as a * companion to tst_tmpdir(). If the TDIRECTORY * environment variable is set, no cleanup will be * attempted. */ #undef FN_NAME #define FN_NAME "tst_rmdir()" void tst_rmdir() { char *errmsg; char *tdirectory; char current_dir[PATH_MAX]; /* current working directory */ char parent_dir[PATH_MAX]; /* directory above TESTDIR */ char *basename; /* basename of the TESTDIR */ /* * If the TDIRECTORY env variable is set, this indicates that no * temp dir was created by tst_tmpdir(). Thus no cleanup will be * necessary. */ if ( (tdirectory = getenv(TDIRECTORY)) != NULL ) { #if UNIT_TEST printf("\"TDIRECORY\" env variable is set; no cleanup was performed\n"); #endif return; } /* * Check that TESTDIR is not NULL. */ if ( TESTDIR == NULL ) { tst_resm(TWARN, "%s: TESTDIR was NULL; no removal attempted", FN_NAME); return; } /* * Check that the value of TESTDIR is not "*" or "/". These could * have disastrous effects in a test run by root. */ if ( strcmp(TESTDIR, "/") == 0 ) { tst_resm(TWARN, "%s: Recursive remove of root directory not attempted", FN_NAME); return; } if ( strchr(TESTDIR, '*') != NULL ) { tst_resm(TWARN, "%s: Recursive remove of '*' not attempted", FN_NAME); return; } /* * Get the directory name of TESTDIR. If TESTDIR is a relative path, * get full path. */ if ( TESTDIR[0] != '/' ) { if ( getcwd(current_dir,PATH_MAX) == NULL ) strcpy(parent_dir, TESTDIR); else sprintf(parent_dir, "%s/%s", current_dir, TESTDIR); } else { strcpy(parent_dir, TESTDIR); } if ( (basename = strrchr(parent_dir, '/')) != NULL ) { *basename='\0'; /* terminate at end of parent_dir */ } /* * Change directory to parent_dir (The dir above TESTDIR). */ if ( chdir(parent_dir) != 0 ) tst_resm(TWARN, "%s: chdir(%s) failed; errno = %d: %s\nAttempting to remove temp dir anyway", FN_NAME, parent_dir, errno, strerror(errno)); /* * Attempt to remove the "TESTDIR" directory, using rmobj(). */ if ( rmobj(TESTDIR, &errmsg) == -1 ) tst_resm(TWARN, "%s: rmobj(%s) failed: %s", FN_NAME, TESTDIR, errmsg); return; } /* tst_rmdir() */ /* * tmpdir_cleanup() - This function is used when tst_tmpdir() * encounters an error, and must cleanup and exit. * It prints a warning message via tst_resm(), and * then calls tst_exit(). */ #undef FN_NAME #define FN_NAME "tst_tmpdir()" static void tmpdir_cleanup() { /* * Print a warning message and call tst_exit() to exit the test. */ tst_resm(TWARN, "%s: No user cleanup function called before exiting", FN_NAME); tst_exit(); } /* tmpdir_cleanup() */ #ifdef UNIT_TEST /**************************************************************************** * Unit test code: Takes input from stdin and can make the following * calls: tst_tmpdir(), tst_rmdir(). ****************************************************************************/ int TST_TOTAL = 10; char *TCID = "TESTTCID"; main() { int option; char *chrptr; printf("UNIT TEST of tst_tmpdir.c. Options to try:\n\ -1 : call tst_exit()\n\ 0 : call tst_tmpdir()\n\ 1 : call tst_rmdir()\n\n"); while ( 1 ) { printf("Enter options (-1, 0, 1): "); (void) scanf("%d%c", &option, &chrptr); switch ( option ) { case -1: tst_exit(); break; case 0: tst_tmpdir(); break; case 1: tst_rmdir(); break; } /* switch() */ } /* while() */ } #endif /* UNIT_TEST */ --- NEW FILE: forker.c --- /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ */ /************************************************************** * * OS Testing - Silicon Graphics, Inc. * * FUNCTION NAME : forker * background * * FUNCTION TITLE : fork desired number of copies of the current process * fork a process and return control to caller * * SYNOPSIS: * int forker(ncopies, mode, prefix) * int ncopies; * int mode; * char *prefix; * * int background(prefix); * char *prefix; * * extern int Forker_pids[]; * extern int Forker_npids; * * AUTHOR : Richard Logan * * CO-PILOT(s) : Dean Roehrich * * INITIAL RELEASE : UNICOS 8.0 * * DESIGN DESCRIPTION * The background function will do a fork of the current process. * The parent process will then exit, thus orphaning the * child process. Doing this will not nice the child process * like executing a cmd in the background using "&" from the shell. * If the fork fails and prefix is not NULL, a error message is printed * to stderr and the process will exit with a value of errno. * * The forker function will fork <ncopies> minus one copies * of the current process. There are two modes in how the forks * will be done. Mode 0 (default) will have all new processes * be childern of the parent process. Using Mode 1, * the parent process will have one child and that child will * fork the next process, if necessary, and on and on. * The forker function will return the number of successful * forks. This value will be different for the parent and each child. * Using mode 0, the parent will get the total number of successful * forks. Using mode 1, the newest child will get the total number * of forks. The parent will get a return value of 1. * * The forker function also updates the global variables * Forker_pids[] and Forker_npids. The Forker_pids array will * be updated to contain the pid of each new process. The * Forker_npids variable contains the number of entries * in Forker_pids. Note, not all processes will have * access to all pids via Forker_pids. If using mode 0, only the * parent process and the last process will have all information. * If using mode 1, only the last child process will have all information. * * If the prefix parameter is not NULL and the fork system call fails, * a error message will be printed to stderr. The error message * the be preceeded with prefix string. If prefix is NULL, * no error message is printed. * * SPECIAL REQUIREMENTS * None. * * UPDATE HISTORY * This should contain the description, author, and date of any * "interesting" modifications (i.e. info should helpful in * maintaining/enhancing this module). * username description * ---------------------------------------------------------------- * rrl This functions will first written during * the SFS testing days, 1993. * * BUGS/LIMITATIONS * The child pids are stored in the fixed array, Forker_pids. * The array only has space for 4098 pids. Only the first * 4098 pids will be stored in the array. * **************************************************************/ #include <stdio.h> #include <errno.h> #include <unistd.h> /* fork, getpid, sleep */ #include <string.h> #include <stdlib.h> /* exit */ #include "forker.h" int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */ int Forker_npids=0; /* number of entries in Forker_pids */ /*********************************************************************** * * This function will fork and the parent will exit zero and * the child will return. This will orphan the returning process * putting it in the background. * * Return Value * 0 : if fork did not fail * !0 : if fork failed, the return value will be the errno. ***********************************************************************/ int background(prefix) char *prefix; { switch (fork()) { case -1: if ( prefix != NULL ) fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n", prefix, __FILE__, errno, strerror(errno)); exit(errno); case 0: /* child process */ break; default: exit(0); } return 0; } /* end of background */ /*********************************************************************** * Forker will fork ncopies-1 copies of self. * ***********************************************************************/ int forker(ncopies, mode, prefix) int ncopies; int mode; /* 0 - all childern of parent, 1 - only 1 direct child */ char *prefix; /* if ! NULL, an message will be printed to stderr */ /* if fork fails. The prefix (program name) will */ /* preceed the message */ { int cnt; int pid; static int ind = 0; Forker_pids[ind]=0; for ( cnt=1; cnt < ncopies; cnt++ ) { switch ( mode ) { case 1 : /* only 1 direct child */ if ( (pid = fork()) == -1 ) { if ( prefix != NULL ) fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n", prefix, __F... [truncated message content] |