From 42f03f675735b0ab55f86824894706e39878b5cc Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sun, 3 Sep 2000 03:52:30 +0000 Subject: Importing Egor's testsuite. --- winsup/testsuite/libltp/include/dataascii.h | 65 ++ winsup/testsuite/libltp/include/databin.h | 44 + winsup/testsuite/libltp/include/file_lock.h | 40 + winsup/testsuite/libltp/include/forker.h | 63 ++ winsup/testsuite/libltp/include/open_flags.h | 73 ++ winsup/testsuite/libltp/include/pattern.h | 90 ++ winsup/testsuite/libltp/include/random_range.h | 45 + winsup/testsuite/libltp/include/rmobj.h | 12 + winsup/testsuite/libltp/include/search_path.h | 36 + winsup/testsuite/libltp/include/str_to_bytes.h | 39 + winsup/testsuite/libltp/include/string_to_tokens.h | 48 + winsup/testsuite/libltp/include/test.h | 216 +++++ winsup/testsuite/libltp/include/tlibio.h | 148 ++++ winsup/testsuite/libltp/include/usctest.h | 319 +++++++ winsup/testsuite/libltp/include/write_log.h | 169 ++++ winsup/testsuite/libltp/lib/dataascii.c | 218 +++++ winsup/testsuite/libltp/lib/databin.c | 298 +++++++ winsup/testsuite/libltp/lib/datapid.c | 374 ++++++++ winsup/testsuite/libltp/lib/forker.c | 285 ++++++ winsup/testsuite/libltp/lib/get_high_address.c | 15 + winsup/testsuite/libltp/lib/open_flags.c | 330 +++++++ winsup/testsuite/libltp/lib/parse_opts.c | 876 +++++++++++++++++++ winsup/testsuite/libltp/lib/pattern.c | 168 ++++ winsup/testsuite/libltp/lib/rmobj.c | 211 +++++ winsup/testsuite/libltp/lib/search_path.c | 251 ++++++ winsup/testsuite/libltp/lib/str_to_bytes.c | 211 +++++ winsup/testsuite/libltp/lib/string_to_tokens.c | 109 +++ winsup/testsuite/libltp/lib/tst_res.c | 964 +++++++++++++++++++++ winsup/testsuite/libltp/lib/tst_sig.c | 213 +++++ winsup/testsuite/libltp/lib/tst_tmpdir.c | 351 ++++++++ winsup/testsuite/libltp/lib/write_log.c | 468 ++++++++++ 31 files changed, 6749 insertions(+) create mode 100644 winsup/testsuite/libltp/include/dataascii.h create mode 100644 winsup/testsuite/libltp/include/databin.h create mode 100644 winsup/testsuite/libltp/include/file_lock.h create mode 100644 winsup/testsuite/libltp/include/forker.h create mode 100644 winsup/testsuite/libltp/include/open_flags.h create mode 100644 winsup/testsuite/libltp/include/pattern.h create mode 100644 winsup/testsuite/libltp/include/random_range.h create mode 100644 winsup/testsuite/libltp/include/rmobj.h create mode 100644 winsup/testsuite/libltp/include/search_path.h create mode 100644 winsup/testsuite/libltp/include/str_to_bytes.h create mode 100644 winsup/testsuite/libltp/include/string_to_tokens.h create mode 100644 winsup/testsuite/libltp/include/test.h create mode 100644 winsup/testsuite/libltp/include/tlibio.h create mode 100644 winsup/testsuite/libltp/include/usctest.h create mode 100644 winsup/testsuite/libltp/include/write_log.h create mode 100644 winsup/testsuite/libltp/lib/dataascii.c create mode 100644 winsup/testsuite/libltp/lib/databin.c create mode 100644 winsup/testsuite/libltp/lib/datapid.c create mode 100644 winsup/testsuite/libltp/lib/forker.c create mode 100644 winsup/testsuite/libltp/lib/get_high_address.c create mode 100644 winsup/testsuite/libltp/lib/open_flags.c create mode 100644 winsup/testsuite/libltp/lib/parse_opts.c create mode 100644 winsup/testsuite/libltp/lib/pattern.c create mode 100644 winsup/testsuite/libltp/lib/rmobj.c create mode 100644 winsup/testsuite/libltp/lib/search_path.c create mode 100644 winsup/testsuite/libltp/lib/str_to_bytes.c create mode 100644 winsup/testsuite/libltp/lib/string_to_tokens.c create mode 100644 winsup/testsuite/libltp/lib/tst_res.c create mode 100644 winsup/testsuite/libltp/lib/tst_sig.c create mode 100644 winsup/testsuite/libltp/lib/tst_tmpdir.c create mode 100644 winsup/testsuite/libltp/lib/write_log.c (limited to 'winsup/testsuite/libltp') diff --git a/winsup/testsuite/libltp/include/dataascii.h b/winsup/testsuite/libltp/include/dataascii.h new file mode 100644 index 000000000..cd75245e4 --- /dev/null +++ b/winsup/testsuite/libltp/include/dataascii.h @@ -0,0 +1,65 @@ +/* + * 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/ + */ +#ifndef _DATAASCII_H_ +#define _DATAASCII_H_ + +/*********************************************************************** + * int dataasciigen(listofchars, buffer, size, offset) + * + * This function fills buffer with ascii characters. + * The ascii characters are obtained from listofchars or the CHARS array + * if listofchars is NULL. + * Each char is selected by an index. The index is the remainder + * of count divided by the array size. + * This method allows more than one process to write to a location + * in a file without corrupting it for another process' point of view. + * + * The return value will be the number of character written in buffer + * (size). + * + ***********************************************************************/ +int dataasciigen(char *, char *, int, int); + +/*********************************************************************** + * int dataasciichk(listofchars, buffer, size, count, errmsg) + * + * This function checks the contents of a buffer produced by + * dataasciigen. + * + * return values: + * >= 0 : error at character count + * < 0 : no error + ***********************************************************************/ + +int dataasciichk(char *, char *, int, int, char**); + +#endif diff --git a/winsup/testsuite/libltp/include/databin.h b/winsup/testsuite/libltp/include/databin.h new file mode 100644 index 000000000..b71fbc0c1 --- /dev/null +++ b/winsup/testsuite/libltp/include/databin.h @@ -0,0 +1,44 @@ +#ifndef _DATABIN_H_ +#define _DATABIN_H_ + +/******************************************************************************* +* NAME +* databingen - fill a buffer with a data pattern +* +* SYNOPSIS +* (void) databingen(mode, buffer, bsize, offset) +* int mode; +* char *buffer; +* int bsize; +* int offset; +* +* DESCRIPTION +* datagen fills the buffer pointed to by 'buffer' with 'bsize' bytes +* of data of the form indicated by 'mode'. +* All modes (expect r -random) are file offset based. +* This allows more than process to do writing to the file without +* corrupting it if the same modes were used. +* They data modes to choose from, these are: +* +* 'a' - writes an alternating bit pattern (i.e. 0x5555555...) +* +* 'c' - writes a checkerboard pattern (i.e. 0xff00ff00ff00...) +* +* 'C' - writes counting pattern (i.e. 0 - 07, 0 - 07, ...); +* +* 'o' - writes all bits set (i.e. 0xffffffffffffff...) +* +* 'z' - writes all bits cleared (i.e. 0x000000000...); +* +* 'r' - writes random integers +* +* RETURN VALUE +* None +* +*******************************************************************************/ + +void databingen( int mode, unsigned char *buffer, int bsize, int offset ); + +void databinchedk( int mode, unsigned char *buffer, int bsize, int offset, char **errmsg); + +#endif diff --git a/winsup/testsuite/libltp/include/file_lock.h b/winsup/testsuite/libltp/include/file_lock.h new file mode 100644 index 000000000..8c9a94835 --- /dev/null +++ b/winsup/testsuite/libltp/include/file_lock.h @@ -0,0 +1,40 @@ +/* + * 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/ + */ +#ifndef _FILE_LOCK_H_ +#define _FILE_LOCK_H_ + +extern char Fl_syscall_str[128]; + +int file_lock( int , int, char ** ); +int record_lock( int , int , int , int , char ** ); + +#endif /* _FILE_LOCK_H_ */ diff --git a/winsup/testsuite/libltp/include/forker.h b/winsup/testsuite/libltp/include/forker.h new file mode 100644 index 000000000..effd5d66e --- /dev/null +++ b/winsup/testsuite/libltp/include/forker.h @@ -0,0 +1,63 @@ +/* + * 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/ + */ +#ifndef _FORKER_H_ +#define _FORKER_H_ + +#define FORKER_MAX_PIDS 4098 + +extern int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */ +extern int Forker_npids; /* 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. + */ +int background( char * ); + +/* + * Forker will fork ncopies-1 copies of self. + * + * arg 1: Number of copies of the process to be running after return. + * This value minus one is the number of forks performed. + * arg 2: mode: 0 - all children are first generation descendents. + * 1 - each subsequent child is a descendent of another + * descendent, resulting in only one direct descendent of the + * parent and each other child is a child of another child in + * relation to the parent. + * arg 3: prefix: string to preceed any error messages. A value of NULL + * results in no error messages on failure. + * returns: returns to parent the number of children forked. + */ +int forker( int , int , char * ); + +#endif /* _FORKER_H_ */ diff --git a/winsup/testsuite/libltp/include/open_flags.h b/winsup/testsuite/libltp/include/open_flags.h new file mode 100644 index 000000000..87fe6ff1d --- /dev/null +++ b/winsup/testsuite/libltp/include/open_flags.h @@ -0,0 +1,73 @@ +/* + * 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/ + */ +#ifndef _OPEN_FLAGS_H_ +#define _OPEN_FLAGS_H_ + +/*********************************************************************** + * This function attempts to convert open flag bits into human readable + * symbols (i.e. O_TRUNC). If there are more than one symbol, + * the string will be placed as a separator between symbols. + * Commonly used separators would be a comma "," or pipe "|". + * If is one and not all bits can be converted to + * symbols, the "UNKNOWN" symbol will be added to return string. + * + * Return Value + * openflags2symbols will return the indentified symbols. + * If no symbols are recognized the return value will be a empty + * string or the "UNKNOWN" symbol. + * + * Limitations + * Currently (05/96) all known symbols are coded into openflags2symbols. + * If new open flags are added this code will have to updated + * to know about them or they will not be recognized. + * + * The Open_symbols must be large enough to hold all possible symbols + * for a given system. + * + ***********************************************************************/ +char *openflags2symbols( int, char *, int ); + +/*********************************************************************** + * This function will take a string of comma separated open flags symbols + * and translate them into an open flag bitmask. + * If any symbol is not valid, -1 is returned. On this error condition + * the badname pointer is updated if not NULL. badname will point + * to the beginning location of where the invalid symbol was found. + * string will be returned unchanged. + * + * A signal received while parsing string could cause the string to + * contain a NULL character in the middle of it. + * + ***********************************************************************/ +int parse_open_flags( char *, char ** ); + +#endif diff --git a/winsup/testsuite/libltp/include/pattern.h b/winsup/testsuite/libltp/include/pattern.h new file mode 100644 index 000000000..74f841cae --- /dev/null +++ b/winsup/testsuite/libltp/include/pattern.h @@ -0,0 +1,90 @@ +/* + * 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/ + */ +#ifndef _PATTERN_H_ +#define _PATTERN_H_ + +/* + * pattern_check(buf, buflen, pat, patlen, patshift) + * + * Check a buffer of length buflen against repeated occurrances of + * a pattern whose length is patlen. Patshift can be used to rotate + * the pattern by patshift bytes to the left. + * + * Patshift may be greater than patlen, the pattern will be rotated by + * (patshift % patshift) bytes. + * + * pattern_check returns -1 if the buffer does not contain repeated + * occurrances of the indicated pattern (shifted by patshift). + * + * The algorithm used to check the buffer relies on the fact that buf is + * supposed to be repeated copies of pattern. The basic algorithm is + * to validate the first patlen bytes of buf against the pat argument + * passed in - then validate the next patlen bytes against the 1st patlen + * bytes - the next (2*patlen) bytes against the 1st (2*pathen) bytes, and + * so on. This algorithm only works when the assumption of a buffer full + * of repeated copies of a pattern holds, and gives MUCH better results + * then walking the buffer byte by byte. + * + * Performance wise, It appears to be about 5% slower than doing a straight + * memcmp of 2 buffers, but the big win is that it does not require a + * 2nd comparison buffer, only the pattern. + */ +int pattern_check( char * , int , char * , int , int ); + +/* + * pattern_fill(buf, buflen, pat, patlen, patshift) + * + * Fill a buffer of length buflen with repeated occurrances of + * a pattern whose length is patlen. Patshift can be used to rotate + * the pattern by patshift bytes to the left. + * + * Patshift may be greater than patlen, the pattern will be rotated by + * (patshift % patlen) bytes. + * + * If buflen is not a multiple of patlen, a partial pattern will be written + * in the last part of the buffer. This implies that a buffer which is + * shorter than the pattern length will receive only a partial pattern ... + * + * pattern_fill always returns 0 - no validation of arguments is done. + * + * The algorithm used to fill the buffer relies on the fact that buf is + * supposed to be repeated copies of pattern. The basic algorithm is + * to fill the first patlen bytes of buf with the pat argument + * passed in - then copy the next patlen bytes with the 1st patlen + * bytes - the next (2*patlen) bytes with the 1st (2*pathen) bytes, and + * so on. This algorithm only works when the assumption of a buffer full + * of repeated copies of a pattern holds, and gives MUCH better results + * then filling the buffer 1 byte at a time. + */ +int pattern_fill( char * , int , char * , int , int ); + +#endif diff --git a/winsup/testsuite/libltp/include/random_range.h b/winsup/testsuite/libltp/include/random_range.h new file mode 100644 index 000000000..d3e1cceb8 --- /dev/null +++ b/winsup/testsuite/libltp/include/random_range.h @@ -0,0 +1,45 @@ +/* + * 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/ + */ +#ifndef _RANDOM_RANGE_H_ +#define _RANDOM_RANGE_H_ + +int parse_ranges ( char *, int, int, int, int (*)(), char **, char ** ); +int range_min ( char *, int ); +int range_max ( char *, int ); +int range_mult ( char *, int ); +long random_range ( int, int, int, char ** ); +long random_rangel ( long, long, long, char ** ); +long long random_rangell ( long long, long long, long long, char ** ); +void random_range_seed( long ); +long random_bit ( long ); + +#endif diff --git a/winsup/testsuite/libltp/include/rmobj.h b/winsup/testsuite/libltp/include/rmobj.h new file mode 100644 index 000000000..4808ca258 --- /dev/null +++ b/winsup/testsuite/libltp/include/rmobj.h @@ -0,0 +1,12 @@ +#ifndef _RMOBJ_H_ +#define _RMOBJ_H_ + +/* + * rmobj() - Remove the specified object. If the specified object is a + * directory, recursively remove everything inside of it. If + * there are any problems, set errmsg (if it is not NULL) and + * return -1. Otherwise return 0. + */ +int rmobj( char *object , char **errmesg ); + +#endif diff --git a/winsup/testsuite/libltp/include/search_path.h b/winsup/testsuite/libltp/include/search_path.h new file mode 100644 index 000000000..131311b44 --- /dev/null +++ b/winsup/testsuite/libltp/include/search_path.h @@ -0,0 +1,36 @@ +/* + * 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$ */ + + +int search_path(char *cmd, char *res_path, int access_mode, int fullpath); diff --git a/winsup/testsuite/libltp/include/str_to_bytes.h b/winsup/testsuite/libltp/include/str_to_bytes.h new file mode 100644 index 000000000..100d37df5 --- /dev/null +++ b/winsup/testsuite/libltp/include/str_to_bytes.h @@ -0,0 +1,39 @@ +/* + * 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/ + */ +#ifndef _STR_TO_BYTES_ +#define _STR_TO_BYTES_ + +int str_to_bytes ( char * ); +long str_to_lbytes ( char * ); +long long str_to_llbytes( char * ); + +#endif diff --git a/winsup/testsuite/libltp/include/string_to_tokens.h b/winsup/testsuite/libltp/include/string_to_tokens.h new file mode 100644 index 000000000..9c0935ec5 --- /dev/null +++ b/winsup/testsuite/libltp/include/string_to_tokens.h @@ -0,0 +1,48 @@ +/* + * 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/ + */ +#ifndef _STRING_TO_TOKENS_H_ +#define _STRING_TO_TOKENS_H_ + +/* + * string_to_tokens() + * + * 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. + * + * NOTE: This function uses strtok() to parse 'arg_string', and thus + * physically alters 'arg_string' by placing null characters where the + * separators originally were. + */ +int string_to_tokens(char *, char **, int, char *); + +#endif diff --git a/winsup/testsuite/libltp/include/test.h b/winsup/testsuite/libltp/include/test.h new file mode 100644 index 000000000..6f955172e --- /dev/null +++ b/winsup/testsuite/libltp/include/test.h @@ -0,0 +1,216 @@ +/* + * 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$ */ + +#ifndef __TEST_H__ +#define __TEST_H__ + +#include +#include +#include + +#define TPASS 0 /* Test passed flag */ +#define TFAIL 1 /* Test failed flag */ +#define TBROK 2 /* Test broken flag */ +#define TWARN 4 /* Test warning flag */ +#define TRETR 8 /* Test retire flag */ +#define TINFO 16 /* Test information flag */ +#define TCONF 32 /* Test not appropriate for configuration flag */ + +/* + * To determine if you are on a Umk or Unicos system, + * use sysconf(_SC_CRAY_SYSTEM). But since _SC_CRAY_SYSTEM + * is not defined until 90, it will be define here if not already + * defined. + * if ( sysconf(_SC_CRAY_SYSTEM) == 1 ) + * on UMK + * else # returned 0 or -1 + * on Unicos + * This is only being done on CRAY systems. + */ +#ifdef CRAY +#ifndef _SC_CRAY_SYSTEM +#define _SC_CRAY_SYSTEM 140 +#endif /* ! _SC_CRAY_SYSTEM */ +#endif /* CRAY */ + +/* + * Ensure that NUMSIGS is defined. + * It should be defined in signal.h or sys/signal.h on + * UNICOS/mk and IRIX systems. On UNICOS systems, + * it is not defined, thus it is being set to UNICOS's NSIG. + * Note: IRIX's NSIG (signals are 1-(NSIG-1)) + * is not same meaning as UNICOS/UMK's NSIG (signals 1-NSIG) + */ +#ifndef NUMSIGS +#define NUMSIGS NSIG +#endif + + +/* defines for unexpected signal setup routine (set_usig.c) */ +#define FORK 1 /* SIGCLD is to be ignored */ +#define NOFORK 0 /* SIGCLD is to be caught */ +#define DEF_HANDLER 0 /* tells set_usig() to use default signal handler */ + +/* + * The following defines are used to control tst_res and t_result reporting. + */ + +#define TOUTPUT "TOUTPUT" /* The name of the environment variable */ + /* that can be set to one of the following */ + /* strings to control tst_res output */ + /* If not set, TOUT_VERBOSE_S is assumed */ + +#define TOUT_VERBOSE_S "VERBOSE" /* All test cases reported */ +#define TOUT_CONDENSE_S "CONDENSE" /* ranges are used where identical messages*/ + /* occur for sequential test cases */ +#define TOUT_NOPASS_S "NOPASS" /* No pass test cases are reported */ +#define TOUT_DISCARD_S "DISCARD" /* No output is reported */ + +#define TST_NOBUF "TST_NOBUF" /* The name of the environment variable */ + /* that can be set to control whether or not */ + /* tst_res will buffer output into 4096 byte */ + /* blocks of output */ + /* If not set, buffer is done. If set, no */ + /* internal buffering will be done in tst_res */ + /* t_result does not have internal buffering */ + +/* + * The following defines are used to control tst_tmpdir, tst_wildcard and t_mkchdir + */ + +#define TDIRECTORY "TDIRECTORY" /* The name of the environment variable */ + /* that if is set, the value (directory) */ + /* is used by all tests as their working */ + /* directory. tst_rmdir and t_rmdir will */ + /* not attempt to clean up. */ + /* This environment variable should only */ + /* be set when doing system testing since */ + /* tests will collide and break and fail */ + /* because of setting it. */ + +#define TEMPDIR "/tmp" /* This is the default temporary directory. */ + /* The environment variable TMPDIR is */ + /* used prior to this valid by tempnam(3). */ + /* To control the base location of the */ + /* temporary directory, set the TMPDIR */ + /* environment variable to desired path */ + +/* + * The following contains support for error message passing. + * See test_error.c for details. + */ +#define TST_ERR_MESG_SIZE 1023 /* max size of error message */ +#define TST_ERR_FILE_SIZE 511 /* max size of module name used by compiler */ +#define TST_ERR_FUNC_SIZE 127 /* max size of func name */ + +typedef struct { + int te_line; /* line where last error was reported. Use */ + /* "__LINE__" and let compiler do the rest */ + int te_level; /* If set, will prevent current stored */ + /* error to not be overwritten */ + char te_func[TST_ERR_FUNC_SIZE+1]; /* name of function of last error */ + /* Name of function or NULL */ + char te_file[TST_ERR_FILE_SIZE+1]; /* module of last error. Use */ + /* "__FILE__" and let compiler do the rest */ + char te_mesg[TST_ERR_MESG_SIZE+1]; /* string of last error */ + +} _TST_ERROR; + +extern _TST_ERROR Tst_error; /* defined in test_error.c */ +#if __STDC__ +extern void tst_set_error(char *file, int line, char *func, char *fmt, ...); +#else +extern void tst_set_error(); +#endif +extern void tst_clear_error(); + + +/* + * The following define contains the name of an environmental variable + * that can be used to specify the number of iterations. + * It is supported in parse_opts.c and USC_setup.c. + */ +#define USC_ITERATION_ENV "USC_ITERATIONS" + +/* + * The following define contains the name of an environmental variable + * that can be used to specify to iteration until desired time + * in floating point seconds has gone by. + * Supported in USC_setup.c. + */ +#define USC_LOOP_WALLTIME "USC_LOOP_WALLTIME" + +/* + * The following define contains the name of an environmental variable + * that can be used to specify that no functional checks are wanted. + * It is supported in parse_opts.c and USC_setup.c. + */ +#define USC_NO_FUNC_CHECK "USC_NO_FUNC_CHECK" + +/* + * The following define contains the name of an environmental variable + * that can be used to specify the delay between each loop iteration. + * The value is in seconds (fractional numbers are allowed). + * It is supported in parse_opts.c. + */ +#define USC_LOOP_DELAY "USC_LOOP_DELAY" + +/* + * The following prototypes are needed to remove compile errors + * on IRIX systems when compiled with -n32 and -64. + */ +extern void tst_res(int ttype, char *fname, char *arg_fmt, ...); +extern void tst_resm(int ttype, char *arg_fmt, ...); +extern void tst_brk(int ttype, char *fname, void (*func)(), + char *arg_fmt, ...); +extern void tst_brkloop(int ttype, char *fname, void (*func)(), + char *arg_fmt, ...); +extern void tst_brkm(int ttype, void (*func)(), char *arg_fmt, ...); +extern void tst_brkloopm(int ttype, void (*func)(), char *arg_fmt, ...); + +extern int tst_environ(); +extern void tst_exit(); +extern void tst_flush(); + +/* prototypes for the t_res.c functions */ +extern void t_result(char *tcid, int tnum, int ttype, char *tmesg); +extern void tt_exit(); +extern int t_environ(); +extern void t_breakum(char *tcid, int total, int typ, char *msg, void (*fnc)()); + +extern void tst_sig(int fork_flag, void (*handler)(), void (*cleanup)()); +extern void tst_tmpdir(); +extern void tst_rmdir(); + +#endif /* end of __TEST_H__ */ diff --git a/winsup/testsuite/libltp/include/tlibio.h b/winsup/testsuite/libltp/include/tlibio.h new file mode 100644 index 000000000..ac0d5705c --- /dev/null +++ b/winsup/testsuite/libltp/include/tlibio.h @@ -0,0 +1,148 @@ +/* + * 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/ + */ + +#define LIO_IO_SYNC 00001 /* read/write */ +#define LIO_IO_ASYNC 00002 /* reada/writea/aio_write/aio_read */ +#define LIO_IO_SLISTIO 00004 /* single stride sync listio */ +#define LIO_IO_ALISTIO 00010 /* single stride async listio */ +#define LIO_IO_SYNCV 00020 /* single-buffer readv/writev */ +#define LIO_IO_SYNCP 00040 /* pread/pwrite */ + +#ifdef sgi +#define LIO_IO_ATYPES 00077 /* all io types */ +#define LIO_IO_TYPES 00061 /* all io types, non-async */ +#endif /* sgi */ +#ifdef linux +#define LIO_IO_TYPES 00021 /* all io types */ +#endif /* linux */ +#ifdef CRAY +#define LIO_IO_TYPES 00017 /* all io types */ +#endif /* CRAY */ + +#define LIO_WAIT_NONE 00010000 /* return asap -- use with care */ +#define LIO_WAIT_ACTIVE 00020000 /* spin looking at iosw fields, or EINPROGRESS */ +#define LIO_WAIT_RECALL 00040000 /* call recall(2)/aio_suspend(3) */ +#define LIO_WAIT_SIGPAUSE 00100000 /* call pause */ +#define LIO_WAIT_SIGACTIVE 00200000 /* spin waiting for signal */ +#ifdef sgi +#define LIO_WAIT_CBSUSPEND 00400000 /* aio_suspend waiting for callback */ +#define LIO_WAIT_SIGSUSPEND 01000000 /* aio_suspend waiting for signal */ +#define LIO_WAIT_ATYPES 01760000 /* all async wait types, except nowait */ +#define LIO_WAIT_TYPES 00020000 /* all sync wait types (sorta) */ +#endif /* sgi */ +#ifdef linux +#define LIO_WAIT_TYPES 00300000 /* all wait types, except nowait */ +#endif /* linux */ +#ifdef CRAY +#define LIO_WAIT_TYPES 00360000 /* all wait types, except nowait */ +#endif /* CRAY */ + +/* meta wait io */ +/* 00 000 0000 */ + +#ifdef sgi +/* all callback wait types */ +#define LIO_WAIT_CBTYPES (LIO_WAIT_CBSUSPEND) +/* all signal wait types */ +#define LIO_WAIT_SIGTYPES (LIO_WAIT_SIGPAUSE|LIO_WAIT_SIGACTIVE|LIO_WAIT_SIGSUSPEND) +/* all aio_{read,write} or lio_listio */ +#define LIO_IO_ASYNC_TYPES (LIO_IO_ASYNC|LIO_IO_SLISTIO|LIO_IO_ALISTIO) +#endif /* sgi */ +#ifdef linux +/* all signal wait types */ +#define LIO_WAIT_SIGTYPES (LIO_WAIT_SIGPAUSE) +#endif /* linux */ +#ifdef CRAY +/* all signal wait types */ +#define LIO_WAIT_SIGTYPES (LIO_WAIT_SIGPAUSE|LIO_WAIT_SIGACTIVE) +#endif /* CRAY */ + +/* + * This bit provides a way to randomly pick an io type and wait method. + * lio_read_buffer() and lio_write_buffer() functions will call + * lio_random_methods() with the given method. + */ +#define LIO_RANDOM 010000000 + +/* + * This bit provides a way for the programmer to use async i/o with + * signals and to use their own signal handler. By default, + * the signal will only be given to the system call if the wait + * method is LIO_WAIT_SIGPAUSE or LIO_WAIT_SIGACTIVE. + * Whenever these wait methods are used, libio signal handler + * will be used. + */ +#define LIO_USE_SIGNAL 020000000 + +/* + * prototypes/structures for functions in the libio.c module. See comments + * in that module, or man page entries for information on the individual + * functions. + */ + +int stride_bounds(int offset, int stride, int nstrides, + int bytes_per_stride, int *min_byte, int *max_byte); + +int lio_set_debug(int level); +int lio_parse_io_arg1(char *string); +void lio_help1(char *prefex); +int lio_parse_io_arg2(char *string, char **badtoken); +void lio_help2(char *prefex); +int lio_write_buffer(int fd, int method, char *buffer, int size, + int sig, char **errmsg, long wrd); + +int lio_read_buffer(int fd, int method, char *buffer, int size, + int sig, char **errmsg, long wrd); +int lio_random_methods(long mask); + +#if CRAY +#include +int lio_wait4asyncio(int method, int fd, struct iosw **statptr); +int lio_check_asyncio(char *io_type, int size, struct iosw *status); +#endif /* CRAY */ +#ifdef sgi +#include +int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp); +int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method); +#endif /* sgi */ + +/* + * Define the structure that contains the infomation that is used + * by the parsing and help functions. + */ +struct lio_info_type { + char *token; + int bits; + char *desc; +}; + + diff --git a/winsup/testsuite/libltp/include/usctest.h b/winsup/testsuite/libltp/include/usctest.h new file mode 100644 index 000000000..afdd45f6b --- /dev/null +++ b/winsup/testsuite/libltp/include/usctest.h @@ -0,0 +1,319 @@ +/* + * 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$ */ + +/********************************************************** + * + * IRIX/Linux Feature Test and Evaluation - Silicon Graphics, Inc. + * + * FUNCTION NAME : usctest.h + * + * FUNCTION TITLE : System Call Test Macros + * + * SYNOPSIS: + * See DESCRIPTION below. + * + * AUTHOR : William Roske + * + * INITIAL RELEASE : UNICOS 7.0 + * + * DESCRIPTION + * TEST(SCALL) - calls a system call + * TEST_VOID(SCALL) - same as TEST() but for syscalls with no return value. + * TEST_CLEANUP - print the log of errno return counts if STD_ERRNO_LOG + * is set. + * TEST_PAUSEF(HAND) - Pause for SIGUSR1 if the pause flag is set. + * Use "hand" as the interrupt handling function + * TEST_PAUSE - Pause for SIGUSR1 if the pause flag is set. + * Use internal function to do nothing on signal and go on. + * TEST_LOOPING(COUNTER) - Conditional to check if test should + * loop. Evaluates to TRUE (1) or FALSE (0). + * TEST_ERROR_LOG(eno) - log that this errno was received, + * if STD_ERRNO_LOG is set. + * TEST_EXP_ENOS(array) - set the bits in TEST_VALID_ENO array at + * positions specified in integer "array" + * + * RETURN VALUE + * TEST(SCALL) - Global Variables set: + * int TEST_RETURN=return code from SCALL + * int TEST_ERRNO=value of errno at return from SCALL + * TEST_VOID(SCALL) - Global Variables set: + * int TEST_ERRNO=value of errno at return from SCALL + * TEST_CLEANUP - None. + * TEST_PAUSEF(HAND) - None. + * TEST_PAUSE - None. + * TEST_LOOPING(COUNTER) - True if COUNTER < STD_LOOP_COUNT or + * STD_INFINITE is set. + * TEST_ERROR_LOG(eno) - None + * TEST_EXP_ENOS(array) - None + * + * KNOWN BUGS + * If you use the TEST_PAUSE or TEST_LOOPING macros, you must + * link in parse_opts.o, which contains the code for those functions. + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ + +#ifndef __USCTEST_H__ +#define __USCTEST_H__ 1 + +#ifndef _SC_CLK_TCK +#include +#endif + +#include + +/* + * Ensure that PATH_MAX is defined + */ +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +#ifndef CRAY +#ifndef BSIZE +#define BSIZE BBSIZE +#endif +#endif + +/*********************************************************************** + * Define option_t structure type. + * Entries in this struct are used by the parse_opts routine + * to indicate valid options and return option arguments + ***********************************************************************/ +typedef struct { + char *option; /* Valid option string (one option only) like "a:" */ + int *flag; /* pointer to location to set true if option given */ + char **arg; /* pointer to location to place argument, if needed */ +} option_t; + +/*********************************************************************** + * The following globals are defined in parse_opts.c but must be + * externed here because they are used in the macros defined below. + ***********************************************************************/ +extern int STD_FUNCTIONAL_TEST, /* turned off by -f to not do functional test */ + STD_TIMING_ON, /* turned on by -t to print timing stats */ + STD_PAUSE, /* turned on by -p to pause before loop */ + STD_INFINITE, /* turned on by -c0 to loop forever */ + STD_LOOP_COUNT, /* changed by -cn to set loop count to n */ + STD_ERRNO_LOG, /* turned on by -e to log errnos returned */ + STD_ERRNO_LIST[], /* counts of errnos returned. indexed by errno */ + STD_COPIES, + STD_argind; + +extern float STD_LOOP_DURATION, /* wall clock time to iterate */ + STD_LOOP_DELAY; /* delay time after each iteration */ + +#define USC_MAX_ERRNO 2000 + +/********************************************************************** + * Prototype for parse_opts routine + **********************************************************************/ +extern char *parse_opts(int ac, char **av, option_t *user_optarr, void (*uhf)()); + + +/* + * define a structure + */ +struct usc_errno_t { + int flag; +}; + +/*********************************************************************** + **** + **** + **** + **********************************************************************/ +#ifdef _USC_LIB_ + +extern int TEST_RETURN; +extern int TEST_ERRNO; + +#else +/*********************************************************************** + * Global array of bit masks to indicate errnos that are expected. + * Bits set by TEST_EXP_ENOS() macro and used by TEST_CLEANUP() macro. + ***********************************************************************/ +struct usc_errno_t TEST_VALID_ENO[USC_MAX_ERRNO]; + +/*********************************************************************** + * Globals for returning the return code and errno from the system call + * test macros. + ***********************************************************************/ +int TEST_RETURN; +int TEST_ERRNO; + +/*********************************************************************** + * temporary variables for determining max and min times in TEST macro + ***********************************************************************/ +long btime, etime, tmptime; + +#endif /* _USC_LIB_ */ + +/*********************************************************************** + * structure for timing accumulator and counters + ***********************************************************************/ +struct tblock { + long tb_max; + long tb_min; + long tb_total; + long tb_count; +}; + +/*********************************************************************** + * The following globals are externed here so that they are accessable + * in the macros that follow. + ***********************************************************************/ +extern struct tblock tblock; +extern void STD_go(); +extern int (*_TMP_FUNC)(void); +extern void STD_opts_help(); + + +/*********************************************************************** + * TEST: calls a system call + * + * parameters: + * SCALL = system call and parameters to execute + * + ***********************************************************************/ +#define TEST(SCALL) TEST_RETURN = (unsigned) SCALL; TEST_ERRNO=errno; + +/*********************************************************************** + * TEST_VOID: calls a system call + * + * parameters: + * SCALL = system call and parameters to execute + * + * Note: This is IDENTICAL to the TEST() macro except that it is intended + * for use with syscalls returning no values (void syscall()). The + * Typecasting nothing (void) into an unsigned integer causes compilation + * errors. + * + ***********************************************************************/ +#define TEST_VOID(SCALL) SCALL; TEST_ERRNO=errno; + +/*********************************************************************** + * TEST_CLEANUP: print system call timing stats and errno log entries + * to stdout if STD_TIMING_ON and STD_ERRNO_LOG are set, respectively. + * Do NOT print ANY information if no system calls logged. + * + * parameters: + * none + * + ***********************************************************************/ +#define TEST_CLEANUP \ +if ( STD_ERRNO_LOG ) { \ + for (tmptime=0; tmptime--> + * --> + * + * The maximum length of this record is defined by the WLOG_REC_MAX_SIZE + * record. Note that the 2-byte record length forces this to be + * <= 64k bytes. + * + * Note that there is lots of bit-masking done here. The w_pathlen, + * w_hostlen, and w_patternlen fields MUST have enough bits to hold + * WLOG_MAX_PATH, WLOG_MAX_HOST, and WLOG_MAX_PATTERN bytes respectivly. + */ + +struct wlog_rec_disk { +#ifdef CRAY + uint w_offset : 44; /* file offset */ + uint w_extra0 : 20; /* EXTRA BITS IN WORD 0 */ +#else + uint w_offset : 32; /* file offset */ + uint w_extra0 : 32; /* EXTRA BITS IN WORD 0 */ +#endif + + uint w_nbytes : 32; /* # bytes written */ + uint w_oflags : 32; /* low-order open() flags */ + + uint w_pid : 17; /* pid doing the write */ + uint w_pathlen : 7; /* length of file path */ + uint w_patternlen: 6; /* length of pattern */ + uint w_hostlen : 4; /* length of host */ + uint w_done : 1; /* 1 if io confirmed done */ + uint w_async : 1; /* 1 if async write (writea) */ + uint w_extra2 : 28; /* EXTRA BITS IN WORD 2 */ +}; + +/* + * write log file datatype. wlog_open() initializes this structure + * which is then passed around to the various wlog_xxx routines. + */ + +struct wlog_file { + int w_afd; /* append fd */ + int w_rfd; /* random-access fd */ + char w_file[1024]; /* name of the write_log */ +}; + +/* + * return value defines for the user-supplied function to + * wlog_scan_backward(). + */ + +#define WLOG_STOP_SCAN 0 +#define WLOG_CONTINUE_SCAN 1 + +/* + * wlog prototypes + */ + +#if __STDC__ +extern int wlog_open(struct wlog_file *wfile, int trunc, int mode); +extern int wlog_close(struct wlog_file *wfile); +extern int wlog_record_write(struct wlog_file *wfile, + struct wlog_rec *wrec, long offset); +extern int wlog_scan_backward(struct wlog_file *wfile, int nrecs, + int (*func)(struct wlog_rec *rec), + long data); +#else +int wlog_open(); +int wlog_close(); +int wlog_record_write(); +int wlog_scan_backward(); +#endif + +extern char Wlog_Error_String[]; + +#endif /* _WRITE_LOG_H_ */ + diff --git a/winsup/testsuite/libltp/lib/dataascii.c b/winsup/testsuite/libltp/lib/dataascii.c new file mode 100644 index 000000000..4b18e38b6 --- /dev/null +++ b/winsup/testsuite/libltp/lib/dataascii.c @@ -0,0 +1,218 @@ +/* + * 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 +#include +#include "dataascii.h" + +#define CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghjiklmnopqrstuvwxyz\n" +#define CHARS_SIZE sizeof(CHARS) + +#ifdef UNIT_TEST +#include /* malloc */ +#endif + +static char Errmsg[80]; + +int +dataasciigen(listofchars, buffer, bsize, offset) +char *listofchars; /* a null terminated list of characters */ +char *buffer; +int bsize; +int offset; +{ + int cnt; + int total; + int ind; /* index into CHARS array */ + char *chr; + int chars_size; + char *charlist; + + chr=buffer; + total=offset+bsize; + + if ( listofchars == NULL ) { + charlist=CHARS; + chars_size=CHARS_SIZE; + } + else { + charlist=listofchars; + chars_size=strlen(listofchars); + } + + for(cnt=offset; cnt +#include +#include /* memset */ +#include /* rand */ +#include "databin.h" + +#if UNIT_TEST +#include +#endif + +static char Errmsg[80]; + +void +databingen (mode, buffer, bsize, offset) +int mode; /* either a, c, r, o, z or C */ +unsigned char *buffer; /* buffer pointer */ +int bsize; /* size of buffer */ +int offset; /* offset into the file where buffer starts */ +{ +int ind; + + switch (mode) + { + default: + case 'a': /* alternating bit pattern */ + memset(buffer,0x55,bsize); + break; + + case 'c': /* checkerboard pattern */ + memset(buffer,0xf0,bsize); + break; + + case 'C': /* */ + for (ind=0;ind< bsize;ind++) { + buffer[ind] = ((offset+ind)%8 & 0177); + } + break; + + case 'o': + memset(buffer,0xff,bsize); + break; + + case 'z': + memset(buffer,0x0,bsize); + break; + + case 'r': /* random */ + for (ind=0;ind< bsize;ind++) { + buffer[ind] = (rand () & 0177) | 0100; + } + } +} + +/*********************************************************************** + * + * return values: + * >= 0 : error at byte offset into the file, offset+buffer[0-(bsize-1)] + * < 0 : no error + ***********************************************************************/ +int +databinchk(mode, buffer, bsize, offset, errmsg) +int mode; /* either a, c, r, z, o, or C */ +unsigned char *buffer; /* buffer pointer */ +int bsize; /* size of buffer */ +int offset; /* offset into the file where buffer starts */ +char **errmsg; +{ + int cnt; + unsigned char *chr; + int total; + long expbits; + long actbits; + + chr=buffer; + total=bsize; + + if ( errmsg != NULL ) { + *errmsg = Errmsg; + } + + switch (mode) + { + default: + case 'a': /* alternating bit pattern */ + expbits=0x55; + break; + + case 'c': /* checkerboard pattern */ + expbits=0xf0; + break; + + case 'C': /* counting pattern */ + for (cnt=0;cnt< bsize;cnt++) { + expbits = ((offset+cnt)%8 & 0177); + + if ( buffer[cnt] != expbits ) { + sprintf(Errmsg, + "data mismatch at offset %d, exp:%#lo, act:%#o", + offset+cnt, expbits, buffer[cnt]); + return offset+cnt; + } + } + sprintf(Errmsg, "all %d bytes match desired pattern", bsize); + return -1; + + case 'o': + expbits=0xff; + break; + + case 'z': + expbits=0; + break; + + case 'r': + return -1; /* no check can be done for random */ + } + + for (cnt=0; cnt< word-offset in file (same #) >< pid > + +1234567890123456789012345678901234567890123456789012345678901234 +________________________________________________________________ +< pid >< offset in file of this word >< pid > + + +8 bits to a bytes == character + NBPW 8 +************/ + +#include +#include +#ifdef UNIT_TEST +#include +#include +#endif + +static char Errmsg[80]; + +#define LOWER16BITS(X) (X & 0177777) +#define LOWER32BITS(X) (X & 0xffffffff) + +/*** +#define HIGHBITS(WRD, bits) ( (-1 << (64-bits)) & WRD) +#define LOWBITS(WRD, bits) ( (-1 >> (64-bits)) & WRD) +****/ + +#define NBPBYTE 8 /* number bits per byte */ + +#ifndef DEBUG +#define DEBUG 0 +#endif + +/*********************************************************************** + * + * + * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 14 15 bytes + * 1234567890123456789012345678901234567890123456789012345678901234 bits + * ________________________________________________________________ 1 word + * < pid >< offset in file of this word >< pid > + * + * the words are put together where offset zero is the start. + * thus, offset 16 is the start of the second full word + * Thus, offset 8 is in middle of word 1 + ***********************************************************************/ +int +datapidgen(pid, buffer, bsize, offset) +int pid; +char *buffer; +int bsize; +int offset; +{ +#if CRAY + + int cnt; + int tmp; + char *chr; + long *wptr; + long word; + int woff; /* file offset for the word */ + int boff; /* buffer offset or index */ + int num_full_words; + + num_full_words = bsize/NBPW; + boff = 0; + + if ( cnt=(offset % NBPW) ) { /* partial word */ + + woff = offset - cnt; +#if DEBUG +printf("partial at beginning, cnt = %d, woff = %d\n", cnt, woff); +#endif + + word = ((LOWER16BITS(pid) << 48) | (LOWER32BITS(woff) << 16) | LOWER16BITS(pid)); + + chr = (char *)&word; + + for (tmp=0; tmp 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 +#include +#include /* fork, getpid, sleep */ +#include +#include "forker.h" + +extern int errno; + +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, __FILE__, errno, strerror(errno)); + return 0; + } + Forker_npids++; + + switch (pid ) { + case 0: /* child - continues the forking */ + + if ( Forker_npids < FORKER_MAX_PIDS ) + Forker_pids[Forker_npids-1]=getpid(); + break; + + default: /* parent - stop the forking */ + if ( Forker_npids < FORKER_MAX_PIDS ) + Forker_pids[Forker_npids-1]=pid; + return cnt-1; + } + + break; + + default : /* all new processes are childern of parent */ + if ( (pid = fork()) == -1 ) { + if ( prefix != NULL ) + fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n", + prefix, __FILE__, errno, strerror(errno)); + return cnt-1; + } + Forker_npids++; + + switch (pid ) { + case 0: /* child - stops the forking */ + if ( Forker_npids < FORKER_MAX_PIDS ) + Forker_pids[Forker_npids-1]=getpid(); + return cnt; + + default: /* parent - continues the forking */ + if ( Forker_npids < FORKER_MAX_PIDS ) + Forker_pids[Forker_npids-1]=pid; + break; + } + break; + } + } + + if ( Forker_npids < FORKER_MAX_PIDS ) + Forker_pids[Forker_npids]=0; + return cnt-1; + +} /* end of forker */ + + +#if UNIT_TEST + +/* + * The following is a unit test main for the background and forker + * functions. + */ + +int +main(argc, argv) +int argc; +char **argv; +{ + int ncopies=1; + int mode=0; + int ret; + int ind; + + if ( argc == 1 ) { + printf("Usage: %s ncopies [mode]\n", argv[0]); + exit(1); + } + + if ( sscanf(argv[1], "%i", &ncopies) != 1 ) { + printf("%s: ncopies argument must be integer\n", argv[0]); + exit(1); + } + + if ( argc == 3 ) + if ( sscanf(argv[2], "%i", &mode) != 1 ) { + printf("%s: mode argument must be integer\n", argv[0]); + exit(1); + } + + printf("Starting Pid = %d\n", getpid()); + ret=background(argv[0]); + printf("After background() ret:%d, pid = %d\n", ret, getpid()); + + ret=forker(ncopies, mode, argv[0]); + + printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n", + ncopies, mode, argv[0], ret, getpid()); + + printf("%d My version of Forker_pids[], Forker_npids = %d\n", + getpid(), Forker_npids); + + for (ind=0; ind + +char * +get_high_address() +{ + return (char *)sbrk(0) + 16384; +} diff --git a/winsup/testsuite/libltp/lib/open_flags.c b/winsup/testsuite/libltp/lib/open_flags.c new file mode 100644 index 000000000..eed39ee33 --- /dev/null +++ b/winsup/testsuite/libltp/lib/open_flags.c @@ -0,0 +1,330 @@ +/* + * 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 : parse_open_flags + * openflags2symbols + * + * FUNCTION TITLE : converts open flag symbols into bitmask + * converts open flag bitmask into symbols + * + * SYNOPSIS: + * int parse_open_flags(symbols, badname) + * char *symbols; + * char **badname; + * + * char *openflags2symbols(openflags, sep, mode) + * int openflags; + * char *sep; + * int mode; + * + * AUTHOR : Richard Logan + * + * CO-PILOT(s) : Dean Roehrich + * + * INITIAL RELEASE : UNICOS 8.0 + * + * DESIGN DESCRIPTION + * The parse_open_flags function can be used to convert + * a list of comma separated open(2) flag symbols (i.e. O_TRUNC) + * into the bitmask that can be used by open(2). + * If a symbol is unknown and is not NULL, + * will updated to point that symbol in . + * Parse_open_flags will return -1 on this error. + * Otherwise parse_open_flags will return the open flag bitmask. + * If parse_open_flags returns, will left unchanged. + * + * The openflags2symbols function attempts to convert open flag + * bits into human readable symbols (i.e. O_TRUNC). If there + * are more than one symbol, the string will be placed as + * a separator between symbols. Commonly used separators would + * be a comma "," or pipe "|". If is one and not all + * bits can be converted to symbols, the "UNKNOWN" + * symbol will be added to return string. + * Openflags2symbols will return the indentified symbols. + * If no symbols are recognized the return value will be a empty + * string or the "UNKNOWN" symbol. + * + * 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 code was first created during the beginning + * of the SFS testing days. I think that was in 1993. + * This code was updated in 05/96. + * (05/96) openflags2symbols was written. + * + * BUGS/LIMITATIONS + * Currently (05/96) all known symbols are coded into openflags2symbols. + * If new open flags are added this code will have to updated + * to know about them or they will not be recognized. + * + **************************************************************/ + +#include +#include +#include +#include +#include /* strcat */ +#include "open_flags.h" + +#define UNKNOWN_SYMBOL "UNKNOWN" + +static char Open_symbols[512]; /* space for openflags2symbols return value */ + +struct open_flag_t { + char *symbol; + int flag; +}; + +static struct open_flag_t Open_flags[] = { + { "O_RDONLY", O_RDONLY }, + { "O_WRONLY", O_WRONLY }, + { "O_RDWR", O_RDWR }, + { "O_SYNC", O_SYNC }, + { "O_CREAT", O_CREAT }, + { "O_TRUNC", O_TRUNC }, + { "O_EXCL", O_EXCL }, + { "O_APPEND", O_APPEND }, + { "O_NONBLOCK", O_NONBLOCK }, +#if O_NOCTTY + { "O_NOCTTY", O_NOCTTY }, +#endif +#if O_DSYNC + { "O_DSYNC", O_DSYNC }, +#endif +#if O_RSYNC + { "O_RSYNC", O_RSYNC }, +#endif +#if O_ASYNC + { "O_ASYNC", O_ASYNC }, +#endif +#if O_PTYIGN + { "O_PTYIGN", O_PTYIGN }, +#endif +#if O_NDELAY + { "O_NDELAY", O_NDELAY }, +#endif +#if O_RAW + { "O_RAW", O_RAW }, +#endif +#ifdef O_SSD + { "O_SSD", O_SSD }, +#endif +#if O_BIG + { "O_BIG", O_BIG }, +#endif +#if O_PLACE + { "O_PLACE", O_PLACE }, +#endif +#if O_RESTART + { "O_RESTART", O_RESTART }, +#endif +#if O_SFSXOP + { "O_SFSXOP", O_SFSXOP }, +#endif +#if O_SFS_DEFER_TM + { "O_SFS_DEFER_TM", O_SFS_DEFER_TM }, +#endif +#if O_WELLFORMED + { "O_WELLFORMED", O_WELLFORMED }, +#endif +#if O_LDRAW + { "O_LDRAW", O_LDRAW }, +#endif +#if O_T3D + { "O_T3D", O_T3D }, +#endif /* O_T3D */ +#if O_PARALLEL + { "O_PARALLEL", O_PARALLEL }, + { "O_FSA", O_PARALLEL|O_WELLFORMED|O_RAW }, /* short cut */ +#endif /* O_PARALLEL */ +#ifdef O_LARGEFILE + { "O_LARGEFILE", O_LARGEFILE }, +#endif +#ifdef O_DIRECT + { "O_DIRECT", O_DIRECT }, +#endif +#ifdef O_PRIV + { "O_PRIV", O_PRIV }, +#endif + +}; + +int +parse_open_flags(char *string, char **badname) +{ + int bits = 0; + char *name; + char *cc; + char savecc; + int found; + int ind; + + name=string; + cc=name; + + while ( 1 ) { + + for(; ((*cc != ',') && (*cc != '\0')); cc++); + savecc = *cc; + *cc = '\0'; + + found = 0; + + for(ind=0; ind < sizeof(Open_flags)/sizeof(struct open_flag_t); ind++) { + if ( strcmp(name, Open_flags[ind].symbol) == 0 ) { + bits |= Open_flags[ind].flag; + found=1; + break; + } + } + + *cc = savecc; /* restore string */ + + if ( found == 0 ) { /* invalid name */ + if ( badname != NULL ) + *badname = name; + return -1; + } + + if ( savecc == '\0' ) + break; + + name = ++cc; + + } /* end while */ + + return bits; + +} /* end of parse_open_flags */ + + +char * +openflags2symbols(int openflags, char *sep, int mode) +{ + int ind; + int size; + int bits = openflags; + int havesome=0; + + Open_symbols[0]='\0'; + + size=sizeof(Open_flags)/sizeof(struct open_flag_t); + + /* + * Deal with special case of O_RDONLY. If O_WRONLY nor O_RDWR + * bits are not set, assume O_RDONLY. + */ + + if ( (bits & (O_WRONLY | O_RDWR)) == 0 ) { + strcat(Open_symbols, "O_RDONLY"); + havesome=1; + } + + /* + * Loop through all but O_RDONLY elments of Open_flags + */ + for(ind=1; ind < size; ind++) { + + if ( (bits & Open_flags[ind].flag) == Open_flags[ind].flag ) { + if ( havesome ) + strcat(Open_symbols, sep); + + strcat(Open_symbols, Open_flags[ind].symbol); + havesome++; + + /* remove flag bits from bits */ + bits = bits & (~Open_flags[ind].flag); + } + } + + /* + * If not all bits were identified and mode was equal to 1, + * added UNKNOWN_SYMBOL to return string + */ + if ( bits && mode == 1 ) { /* not all bits were identified */ + if ( havesome ) + strcat(Open_symbols, sep); + strcat(Open_symbols, UNKNOWN_SYMBOL); + } + + return Open_symbols; + +} /* end of openflags2symbols */ + + +#ifdef UNIT_TEST + +/* + * The following code provides a UNIT test main for + * parse_open_flags and openflags2symbols functions. + */ + +int +main(argc, argv) +int argc; +char **argv; +{ + int bits; + int ret; + char *err; + + if (argc == 1 ) { + printf("Usage: %s openflagsbits\n\t%s symbols\n", argv[0], argv[0]); + exit(1); + } + + if ( sscanf(argv[1], "%i", &bits) == 1 ) { + printf("openflags2symbols(%#o, \",\", 1) returned %s\n", + bits, openflags2symbols(bits, ",", 1)); + + } else { + ret=parse_open_flags(argv[1], &err); + if ( ret == -1 ) + printf("parse_open_flags(%s, &err) returned -1, err = %s\n", + argv[0], err); + else + printf("parse_open_flags(%s, &err) returned %#o\n", argv[0], ret); + } + + exit(0); +} + +#endif /* end of UNIT_TEST */ diff --git a/winsup/testsuite/libltp/lib/parse_opts.c b/winsup/testsuite/libltp/lib/parse_opts.c new file mode 100644 index 000000000..2758ebfb7 --- /dev/null +++ b/winsup/testsuite/libltp/lib/parse_opts.c @@ -0,0 +1,876 @@ +/* + * 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$ */ + +/********************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : parse_opts + * + * FUNCTION TITLE : parse standard & user options for system call tests + * + * SYNOPSIS: + * #include "usctest.h" + * + * char *parse_opts(ac, av, user_optarr, uhf) + * int ac; + * char **av; + * option_t user_optarr[]; + * void (*uhf)(); + * + * AUTHOR : William Roske/Richard Logan + * + * INITIAL RELEASE : UNICOS 7.0 + * + * DESCRIPTION + * The parse_opts library routine takes that argc and argv parameters + * recevied by main() and an array of structures defining user options. + * It parses the command line setting flag and argument locations + * associated with the options. It uses getopt to do the actual cmd line + * parsing. uhf() is a function to print user define help + * + * This module contains the functions usc_global_setup_hook and + * usc_test_looping, which are called by marcos defined in usctest.h. + * + * RETURN VALUE + * parse_opts returns a pointer to an error message if an error occurs. + * This pointer is (char *)NULL if parsing is successful. + * + *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __CYGWIN__ +#include +#endif + + +#if UNIT_TEST +#include +#endif /* UNIT_TEST */ + +#include "test.h" +#define _USC_LIB_ 1 /* indicates we are the library to the usctest.h include */ +#include "usctest.h" + +#ifndef USC_COPIES +#define USC_COPIES "USC_COPIES" +#endif + +#ifndef UNIT_TEST +#define UNIT_TEST 0 +#endif + +#ifndef DEBUG +#define DEBUG 0 +#endif + +/* The timing information block. */ +struct tblock tblock={0,((long) -1)>>1,0,0}; + + +/* Define flags and args for standard options */ +int STD_FUNCTIONAL_TEST=1, /* flag indicating to do functional testing code */ + STD_TIMING_ON=0, /* flag indicating to print timing stats */ + STD_PAUSE=0, /* flag indicating to pause before actual start, */ + /* for contention mode */ + STD_INFINITE=0, /* flag indciating to loop forever */ + STD_LOOP_COUNT=1, /* number of iterations */ + STD_COPIES=1, /* number of copies */ + STD_ERRNO_LOG=0; /* flag indicating to do errno logging */ + +float STD_LOOP_DURATION=0.0, /* duration value in fractional seconds */ + STD_LOOP_DELAY=0.0; /* loop delay value in fractional seconds */ + + +char **STD_opt_arr = NULL; /* array of option strings */ +int STD_nopts=0, /* number of elements in STD_opt_arr */ + STD_argind=1; /* argv index to next argv element */ + /* (first argument) */ + /* To getopt users, it is like optind */ + +/* + * The following variables are to support system testing additions. + */ +static int STD_TP_barrier=0; /* flag to do barrier in TEST_PAUSE */ + /* 2 - wait_barrier(), 3 - set_barrier(), * - barrier() */ +static int STD_LP_barrier=0; /* flag to do barrier in TEST_LOOPING */ + /* 2 - wait_barrier(), 3 - set_barrier(), * - barrier() */ +static int STD_TP_shmem_sz=0; /* shmalloc this many words per pe in TEST_PAUSE */ +static int STD_LD_shmem=0; /* flag to do shmem_puts and shmem_gets during delay */ +static int STD_LP_shmem=0; /* flag to do shmem_puts and gets during TEST_LOOPING */ +static int STD_LD_recfun=0; /* do recressive function calls in loop delay */ +static int STD_LP_recfun=0; /* do recressive function calls in TEST_LOOPING */ +static int STD_TP_sbrk=0; /* do sbrk in TEST_PAUSE */ +static int STD_LP_sbrk=0; /* do sbrk in TEST_LOOPING */ +static char *STD_start_break=0; /* original sbrk size */ +static int Debug=0; + +struct std_option_t { + char *optstr; + char *help; + char *flag; + char **arg; +} std_options[] = { + { "c:", " -c n Run n copies concurrently\n", NULL, NULL}, + { "e" , " -e Turn on errno logging\n", NULL, NULL}, + { "f" , " -f Turn off functional testing\n", NULL, NULL}, + { "h" , " -h Show this help screen\n", NULL, NULL}, + { "i:", " -i n Execute test n times\n", NULL, NULL}, + { "I:", " -I x Execute test for x seconds\n", NULL, NULL}, + { "p" , " -p Pause for SIGUSR1 before starting\n", NULL, NULL}, + { "P:", " -P x Pause for x seconds between iterations\n", NULL, NULL}, + { "t" , " -t Turn on syscall timing\n", NULL, NULL}, + {NULL, NULL, NULL, NULL}}; + +void print_help(void (*user_help)()); + +/* + * Structure for usc_recressive_func argument + */ +struct usc_bigstack_t { + char space[4096]; +}; + +static struct usc_bigstack_t *STD_bigstack=NULL; + +/* + * Counter of errnos returned (-e option). Indexed by errno. + * Make the array USC_MAX_ERRNO long. That is the first Fortran + * Lib errno. No syscall should return an errno that high. + */ +int STD_ERRNO_LIST[USC_MAX_ERRNO]; + +/* define the string length for Mesg and Mesg2 strings */ +#define STRLEN 2048 + +static char Mesg2[STRLEN]; /* holds possible return string */ +static void usc_recressive_func(); + +/* + * Define bits for options that might have env variable default + */ +#define OPT_iteration 01 +#define OPT_nofunccheck 02 +#define OPT_duration 04 +#define OPT_delay 010 +#define OPT_copies 020 + + +/********************************************************************** + * parse_opts: + **********************************************************************/ +char * +parse_opts(int ac, char **av, option_t *user_optarr, void (*uhf)()) +{ + int found; /* flag to indicate that an option specified was */ + /* found in the user's list */ + int k; /* scratch integer for returns and short time usage */ + float ftmp; /* tmp float for parsing env variables */ + char *ptr; /* used in getting env variables */ + int options=0; /* no options specified */ + int optstrlen, i; + char *optionstr; + int opt; /* return of getopt */ + + /* + * If not the first time this function is called, release the old STD_opt_arr + * vector. + */ + + if ( STD_opt_arr != NULL ) { + free(STD_opt_arr); + STD_opt_arr=NULL; + } + /* Calculate how much space we need for the option string */ + optstrlen = 0; + for (i = 0; std_options[i].optstr; ++i) + optstrlen += strlen(std_options[i].optstr); + if (user_optarr) + for (i = 0; user_optarr[i].option; ++i) { + if (strlen(user_optarr[i].option) > 2) + return "parse_opts: ERROR - Only short options are allowed"; + optstrlen += strlen(user_optarr[i].option); + } + optstrlen += 1; + + /* Create the option string for getopt */ + optionstr = (char *)malloc(optstrlen); + if (!optionstr) + return "parse_opts: ERROR - Could not allocate memory for optionstr"; + + for (i = 0; std_options[i].optstr; ++i) + strcat(optionstr, std_options[i].optstr); + if (user_optarr) + for (i = 0; user_optarr[i].option; ++i) + /* only add the option if it wasn't there already */ + if (strchr(optionstr, user_optarr[i].option[0]) == NULL) + strcat(optionstr, user_optarr[i].option); + +#if DEBUG > 1 + printf("STD_nopts = %d\n", STD_nopts); +#endif + + /* + * Loop through av parsing options. + */ + while ( (opt = getopt(ac, av, optionstr)) > 0) { + + STD_argind = optind; +#if DEBUG > 0 + printf("parse_opts: getopt returned '%c'\n", opt); +#endif + + switch (opt) { + case '?': /* Unknown option */ + return "Unknown option"; + break; + case ':': /* Missing Arg */ + return "Missing argument"; + break; + case 'i': /* Iterations */ + options |= OPT_iteration; + STD_LOOP_COUNT = atoi(optarg); + if (STD_LOOP_COUNT == 0) STD_INFINITE = 1; + break; + case 'P': /* Delay between iterations */ + options |= OPT_delay; + STD_LOOP_DELAY = atof(optarg); + break; + case 'I': /* Time duration */ + options |= OPT_duration; + STD_LOOP_DURATION = atof(optarg); + if ( STD_LOOP_DURATION == 0.0 ) STD_INFINITE=1; + break; + case 'c': /* Copies */ + options |= OPT_copies; + STD_COPIES = atoi(optarg); + break; + case 'f': /* Functional testing */ + STD_FUNCTIONAL_TEST = 0; + break; + case 'p': /* Pause for SIGUSR1 */ + STD_PAUSE = 1; + break; + case 't': /* syscall timing */ + STD_TIMING_ON = 1; + break; + case 'e': /* errno loggin */ + STD_ERRNO_LOG = 1; + break; + case 'h': /* Help */ + print_help(uhf); + exit(0); + break; + default: + + /* Check all the user specified options */ + found=0; + for(i = 0; user_optarr[i].option; ++i) { + + if (opt == user_optarr[i].option[0]) { + /* Yup, This is a user option, set the flag and look for argument */ + if ( user_optarr[i].flag ) { + *user_optarr[i].flag=1; + } + found++; + + /* save the argument at the user's location */ + if ( user_optarr[i].option[strlen(user_optarr[i].option)-1] == ':' ) { + *user_optarr[i].arg=optarg; + } + break; /* option found - break out of the for loop */ + } + } + /* This condition "should never happen". SO CHECK FOR IT!!!! */ + if ( ! found ) { + sprintf(Mesg2, + "parse_opts: ERROR - option:\"%c\" NOT FOUND... INTERNAL ERROR", opt); + return(Mesg2); + } + } + + } /* end of while */ + + STD_argind = optind; + + /* + * Turn on debug + */ + if ( (ptr=getenv("USC_DEBUG")) != NULL ) { + Debug=1; + printf("env USC_DEBUG is defined, turning on debug\n"); + } + if ( (ptr=getenv("USC_VERBOSE")) != NULL ) { + Debug=1; + printf("env USC_VERBOSE is defined, turning on debug\n"); + } + + /* + * If the USC_ITERATION_ENV environmental variable is set to + * a number, use that number as iteration count (same as -c option). + * The -c option with arg will be used even if this env var is set. + */ + if ( !(options & OPT_iteration) && (ptr=getenv(USC_ITERATION_ENV)) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1) { + if ( k == 0 ) { /* if arg is 0, set infinite loop flag */ + STD_INFINITE=1; + if ( Debug ) + printf("Using env %s, set STD_INFINITE to 1\n", + USC_ITERATION_ENV); + } else { /* else, set the loop count to the arguement */ + STD_LOOP_COUNT=k; + if ( Debug ) + printf("Using env %s, set STD_LOOP_COUNT to %d\n", + USC_ITERATION_ENV, k); + } + } + } + + /* + * If the USC_NO_FUNC_CHECK environmental variable is set, we'll + * unset the STD_FUNCTIONAL_TEST variable. + */ + if ( !(options & OPT_nofunccheck) && (ptr=getenv(USC_NO_FUNC_CHECK)) != NULL ) { + STD_FUNCTIONAL_TEST=0; /* Turn off functional testing */ + if ( Debug ) + printf("Using env %s, set STD_FUNCTIONAL_TEST to 0\n", + USC_NO_FUNC_CHECK); + } + + /* + * If the USC_LOOP_WALLTIME environmental variable is set, + * use that number as duration (same as -I option). + * The -I option with arg will be used even if this env var is set. + */ + + if ( !(options & OPT_duration) && (ptr=getenv(USC_LOOP_WALLTIME)) != NULL ) { + if ( sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0 ) { + STD_LOOP_DURATION=ftmp; + if ( Debug ) + printf("Using env %s, set STD_LOOP_DURATION to %f\n", + USC_LOOP_WALLTIME, ftmp); + if ( STD_LOOP_DURATION == 0.0 ) { /* if arg is 0, set infinite loop flag */ + STD_INFINITE=1; + if ( Debug ) + printf("Using env %s, set STD_INFINITE to 1\n", USC_LOOP_WALLTIME); + } + } + } + if ( !(options & OPT_duration) && (ptr=getenv("USC_DURATION")) != NULL ) { + if ( sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0 ) { + STD_LOOP_DURATION=ftmp; + if ( Debug ) + printf("Using env USC_DURATION, set STD_LOOP_DURATION to %f\n", ftmp); + if ( STD_LOOP_DURATION == 0.0 ) { /* if arg is 0, set infinite loop flag */ + STD_INFINITE=1; + if ( Debug ) + printf("Using env USC_DURATION, set STD_INFINITE to 1\n"); + } + } + } + /* + * If the USC_LOOP_DELAY environmental variable is set, + * use that number as delay in factional seconds (same as -P option). + * The -P option with arg will be used even if this env var is set. + */ + if ( !(options & OPT_delay) && (ptr=getenv(USC_LOOP_DELAY)) != NULL ) { + if ( sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0 ) { + STD_LOOP_DELAY=ftmp; + if ( Debug ) + printf("Using env %s, set STD_LOOP_DELAY = %f\n", + USC_LOOP_DELAY, ftmp); + } + } + + /* + * If the USC_COPIES environmental variable is set, + * use that number as copies (same as -c option). + * The -c option with arg will be used even if this env var is set. + */ + if ( !(options & OPT_copies) && (ptr=getenv(USC_COPIES)) != NULL ) { + if ( sscanf(ptr, "%d", &STD_COPIES) == 1 && STD_COPIES >= 0 ) { + if ( Debug ) + printf("Using env %s, set STD_COPIES = %d\n", + USC_COPIES, STD_COPIES); + } + } + + /* + * The following are special system testing envs to turn on special + * hooks in the code. + */ + if ( (ptr=getenv("USC_TP_BARRIER")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_TP_barrier=k; + } + else + STD_TP_barrier=1; + if ( Debug ) + printf("using env USC_TP_BARRIER, Set STD_TP_barrier to %d\n", + STD_TP_barrier); + } + + if ( (ptr=getenv("USC_LP_BARRIER")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_LP_barrier=k; + } + else + STD_LP_barrier=1; + if ( Debug ) + printf("using env USC_LP_BARRIER, Set STD_LP_barrier to %d\n", + STD_LP_barrier); + } + + if ( (ptr=getenv("USC_TP_SHMEM")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_TP_shmem_sz=k; + if ( Debug ) + printf("Using env USC_TP_SHMEM, Set STD_TP_shmem_sz to %d\n", + STD_TP_shmem_sz); + } + } + + if ( (ptr=getenv("USC_LP_SHMEM")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_LP_shmem=k; + if ( Debug ) + printf("Using env USC_LP_SHMEM, Set STD_LP_shmem to %d\n", + STD_LP_shmem); + } + } + + if ( (ptr=getenv("USC_LD_SHMEM")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_LD_shmem=k; + if ( Debug ) + printf("Using env USC_LD_SHMEM, Set STD_LD_shmem to %d\n", + STD_LD_shmem); + } + } + + if ( (ptr=getenv("USC_TP_SBRK")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_TP_sbrk=k; + if ( Debug ) + printf("Using env USC_TP_SBRK, Set STD_TP_sbrk to %d\n", + STD_TP_sbrk); + } + } + + if ( (ptr=getenv("USC_LP_SBRK")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_LP_sbrk=k; + if ( Debug ) + printf("Using env USC_LP_SBRK, Set STD_LP_sbrk to %d\n", + STD_LP_sbrk); + } + } + + if ( (ptr=getenv("USC_LP_RECFUN")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_LP_recfun=k; + if ( STD_bigstack != (struct usc_bigstack_t *)NULL ) + STD_bigstack=(struct usc_bigstack_t *) + malloc(sizeof(struct usc_bigstack_t)); + if ( Debug ) + printf("Using env USC_LP_RECFUN, Set STD_LP_recfun to %d\n", + STD_LP_recfun); + } + } + + if ( (ptr=getenv("USC_LD_RECFUN")) != NULL ) { + if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) { + STD_LD_recfun=k; + if ( STD_bigstack != (struct usc_bigstack_t *)NULL ) + STD_bigstack=(struct usc_bigstack_t *) + malloc(sizeof(struct usc_bigstack_t)); + if ( Debug ) + printf("Using env USC_LD_RECFUN, Set STD_LD_recfun to %d\n", + STD_LD_recfun); + } + } + +#if UNIT_TEST + printf("The following variables after option and env parsing:\n"); + printf("STD_FUNCTIONAL_TEST = %d\n", STD_FUNCTIONAL_TEST); + printf("STD_LOOP_DURATION = %f\n", STD_LOOP_DURATION); + printf("STD_LOOP_DELAY = %f\n", STD_LOOP_DELAY); + printf("STD_COPIES = %d\n", STD_COPIES); + printf("STD_LOOP_COUNT = %d\n", STD_LOOP_COUNT); + printf("STD_INFINITE = %d\n", STD_INFINITE); + printf("STD_TIMING_ON = %d\n", STD_TIMING_ON); + printf("STD_ERRNO_LOG = %d\n", STD_ERRNO_LOG); + printf("STD_PAUSE = %d\n", STD_PAUSE); +#endif + + return((char *) NULL); + +} /* end of parse_opts */ + +/********************************************************************* + * print_help() - print help message and user help message + *********************************************************************/ +void print_help(void (*user_help)()) +{ + STD_opts_help(); + + if (user_help) user_help(); +} + +/********************************************************************* + * STD_opts_help() - return a help string for the STD_OPTIONS. + *********************************************************************/ +void +STD_opts_help() +{ + int i; + + for(i = 0; std_options[i].optstr; ++i) { + if (std_options[i].help) + printf(std_options[i].help); + } +} + +/* + * routine to goto when we get the SIGUSR1 for STD_PAUSE + */ +void STD_go(int sig) +{ + return; +} + +/*********************************************************************** + * This function will do desired end of global setup test + * hooks. + * Currently it will only do a pause waiting for sigusr1 if + * STD_PAUSE is set. + * + ***********************************************************************/ +int +usc_global_setup_hook() +{ + int cnt; + /* temp variable to store old signal action to be restored after pause */ + int (*_TMP_FUNC)(void); + + /* + * Fork STD_COPIES-1 copies. + */ + for(cnt=1;cnt +#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); +} diff --git a/winsup/testsuite/libltp/lib/rmobj.c b/winsup/testsuite/libltp/lib/rmobj.c new file mode 100644 index 000000000..63122c446 --- /dev/null +++ b/winsup/testsuite/libltp/lib/rmobj.c @@ -0,0 +1,211 @@ +/* + * 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$ */ + +/********************************************************** + * + * OS Testing - Silicon Graphics, Inc. + * + * FUNCTION NAME : rmobj() + * + * FUNCTION TITLE : Remove an object + * + * SYNOPSIS: + * int rmobj(char *obj, char **errmsg) + * + * AUTHOR : Kent Rogers + * + * INITIAL RELEASE : UNICOS 7.0 + * + * USER DESCRIPTION + * This routine will remove the specified object. If the specified + * object is a directory, it will recursively remove the directory + * and everything underneath it. It assumes that it has privilege + * to remove everything that it tries to remove. If rmobj() encounters + * any problems, and errmsg is not NULL, errmsg is set to point to a + * string explaining the error. + * + * DETAILED DESCRIPTION + * Allocate space for the directory and its contents + * Open the directory to get access to what is in it + * Loop through the objects in the directory: + * If the object is not "." or "..": + * Determine the file type by calling lstat() + * If the object is not a directory: + * Remove the object with unlink() + * Else: + * Call rmobj(object) to remove the object's contents + * Determine the link count on object by calling lstat() + * If the link count >= 3: + * Remove the directory with unlink() + * Else + * Remove the directory with rmdir() + * Close the directory and free the pointers + * + * RETURN VALUE + * If there are any problems, rmobj() will set errmsg (if it was not + * NULL) and return -1. Otherwise it will return 0. + * + ************************************************************/ +#include /* for errno */ +#include /* for NULL */ +#include /* for malloc() */ +#include /* for string function */ +#include /* for PATH_MAX */ +#include /* for opendir(), readdir(), closedir(), stat() */ +#include /* for [l]stat() */ +#include /* for opendir(), readdir(), closedir() */ +#include /* for rmdir(), unlink() */ +#include "rmobj.h" + +#define SYSERR strerror(errno) + +int +rmobj(char *obj, char **errmsg) +{ + int ret_val = 0; /* return value from this routine */ + DIR *dir; /* pointer to a directory */ + struct dirent *dir_ent; /* pointer to directory entries */ + char dirobj[PATH_MAX]; /* object inside directory to modify */ + struct stat statbuf; /* used to hold stat information */ + static char err_msg[1024]; /* error message */ + + /* Determine the file type */ + if ( lstat(obj, &statbuf) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "lstat(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + + /* Take appropriate action, depending on the file type */ + if ( (statbuf.st_mode & S_IFMT) == S_IFDIR ) { + /* object is a directory */ + + /* Do NOT perform the request if the directory is "/" */ + if ( !strcmp(obj, "/") ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "Cannot remove /"); + *errmsg = err_msg; + } + return -1; + } + + /* Open the directory to get access to what is in it */ + if ( (dir = opendir(obj)) == NULL ) { + if ( rmdir(obj) != 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } else { + return 0; + } + } + + /* Loop through the entries in the directory, removing each one */ + for ( dir_ent = (struct dirent *)readdir(dir); + dir_ent != NULL; + dir_ent = (struct dirent *)readdir(dir)) { + + /* Don't remove "." or ".." */ + if ( !strcmp(dir_ent->d_name, ".") || !strcmp(dir_ent->d_name, "..") ) + continue; + + /* Recursively call this routine to remove the current entry */ + sprintf(dirobj, "%s/%s", obj, dir_ent->d_name); + if ( rmobj(dirobj, errmsg) != 0 ) + ret_val = -1; + } + + /* Close the directory */ + closedir(dir); + + /* If there were problems removing an entry, don't attempt to + remove the directory itself */ + if ( ret_val == -1 ) + return -1; + + /* Get the link count, now that all the entries have been removed */ + if ( lstat(obj, &statbuf) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "lstat(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + + /* Remove the directory itself */ + if ( statbuf.st_nlink >= 3 ) { + /* The directory is linked; unlink() must be used */ + if ( unlink(obj) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "unlink(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } else { + /* The directory is not linked; rmdir() can be used */ + if ( rmdir(obj) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } + } else { + /* object is not a directory; just use unlink() */ + if ( unlink(obj) < 0 ) { + if ( errmsg != NULL ) { + sprintf(err_msg, "unlink(%s) failed; errno=%d: %s", + obj, errno, SYSERR); + *errmsg = err_msg; + } + return -1; + } + } /* if obj is a directory */ + + /* + * Everything must have went ok. + */ + return 0; +} /* rmobj() */ diff --git a/winsup/testsuite/libltp/lib/search_path.c b/winsup/testsuite/libltp/lib/search_path.c new file mode 100644 index 000000000..d6570cb59 --- /dev/null +++ b/winsup/testsuite/libltp/lib/search_path.c @@ -0,0 +1,251 @@ +/* $Header$ */ + +/* + * (C) COPYRIGHT CRAY RESEARCH, INC. + * UNPUBLISHED PROPRIETARY INFORMATION. + * ALL RIGHTS RESERVED. + */ +/********************************************************** + * + * 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 +#include +#include +#include +#include +#include +#include + +extern int errno; + +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 */ +} + diff --git a/winsup/testsuite/libltp/lib/str_to_bytes.c b/winsup/testsuite/libltp/lib/str_to_bytes.c new file mode 100644 index 000000000..beecb71b6 --- /dev/null +++ b/winsup/testsuite/libltp/lib/str_to_bytes.c @@ -0,0 +1,211 @@ +/* + * 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 +#include +#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 linux +#define B_MULT DEV_BSIZE /* block size */ +#elif __CYGWIN__ +#include +#define B_MULT S_BLKSIZE /* block size */ +#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 +#include /* 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 +#include +#include /* for I/O functions, BUFSIZ */ +#include /* for getenv() */ +#include /* for varargs stuff */ +#include /* for access() */ +#include "test.h" /* for output display mode & result type */ + /* defines */ + +/* + * Define some useful macros. + */ +#define VERBOSE 1 /* flag values for the T_mode variable */ +#define CONDENSE 2 +#define NOPASS 3 +#define DISCARD 4 + +#define MAXMESG 80 /* max length of internal messages */ +#define USERMESG 2048 /* max length of user message */ +#define TRUE 1 +#define FALSE 0 + +/* + * EXPAND_VAR_ARGS - Expand the variable portion (arg_fmt) of a result + * message into the specified string. + */ +#define EXPAND_VAR_ARGS(arg_fmt, str) { \ + va_list ap; /* varargs mechanism */ \ + \ + if ( arg_fmt != NULL ) { \ + if ( Expand_varargs == TRUE ) { \ + va_start(ap, arg_fmt); \ + vsprintf(str, arg_fmt, ap); \ + va_end(ap); \ + Expand_varargs = FALSE; \ + } else { \ + strcpy(str, arg_fmt); \ + } \ + } else { \ + str[0] = '\0'; \ + } \ +} /* EXPAND_VAR_ARGS() */ + +/* + * Define local function prototypes. + */ +static void check_env(); +static void tst_condense(int tnum, int ttype, char *tmesg); +static void tst_print(char *tcid, int tnum, int trange, int ttype, char *tmesg); +static void cat_file(char *filename); + + +/* + * Define some static/global variables. + */ +static FILE *T_out = NULL; /* tst_res() output file descriptor */ +static char *File; /* file whose contents is part of result */ +static int T_exitval = 0; /* exit value used by tst_exit() */ +static int T_mode = VERBOSE; /* flag indicating print mode: VERBOSE, */ + /* CONDENSE, NOPASS, DISCARD */ + +static int Expand_varargs = TRUE; /* if TRUE, expand varargs stuff */ +static char Warn_mesg[MAXMESG]; /* holds warning messages */ + +/* + * These are used for condensing output when NOT in verbose mode. + */ +static int Buffered = FALSE; /* TRUE if condensed output is currently */ + /* buffered (i.e. not yet printed) */ +static char *Last_tcid; /* previous test case id */ +static int Last_num; /* previous test case number */ +static int Last_type; /* previous test result type */ +static char *Last_mesg; /* previous test result message */ + + +/* + * These globals may be externed by the test. + */ +int Tst_count = 0; /* current count of test cases executed; NOTE: */ + /* Tst_count may be externed by other programs */ +int Tst_lptotal = 0; /* tst_brkloop() external */ +int Tst_lpstart = 0; /* tst_brkloop() external */ +int Tst_range = 1; /* for specifying multiple results */ +int Tst_nobuf = 1; /* this is a no-op; buffering is never done, but */ + /* this will stay for compatibility reasons */ + +/* + * These globals must be defined in the test. + */ +extern char *TCID; /* Test case identifier from the test source */ +extern int TST_TOTAL; /* Total number of test cases from the test */ + /* source */ + +/* + * This global is used by the temp. dir. maintenance functions, + * tst_tmpdir()/tst_rmdir(), tst_wildcard()/tst_tr_rmdir(). It is the + * name of the directory created (if any). It is defined here, so that + * it only has to be declared once and can then be referenced from more + * than one module. Also, since the temp. dir. maintenance functions + * rely on the tst_res.c package this seemed like a reasonable place. + */ +char *TESTDIR = NULL; + +/* + * tst_res() - Main result reporting function. Handle test information + * appropriately depending on output display mode. Call + * tst_condense() or tst_print() to actually print results. + * All result functions (tst_resm(), tst_brk(), etc.) + * eventually get here to print the results. + */ +void +tst_res(int ttype, char *fname, char *arg_fmt, ...) +{ + int i; + char tmesg[USERMESG]; /* expanded message */ + +#if DEBUG + printf("IN tst_res; Tst_count = %d; Tst_range = %d\n", + Tst_count, Tst_range); fflush(stdout); +#endif + + /* + * Expand the arg_fmt string into tmesg, if necessary. + */ + EXPAND_VAR_ARGS(arg_fmt, tmesg); + + /* + * Save the test result type by ORing ttype into the current exit + * value (used by tst_exit()). + */ + T_exitval |= ttype; + + /* + * Unless T_out has already been set by tst_environ(), make tst_res() + * output go to standard output. + */ + if ( T_out == NULL ) + T_out = stdout; + + /* + * Check TOUTPUT environment variable (if first time) and set T_mode + * flag. + */ + check_env(); + + /* + * A negative or NULL range is invalid. + */ + if ( Tst_range <= 0 ) { + Tst_range = 1; + tst_print(TCID, 0, 1, TWARN, + "tst_res(): Tst_range must be positive"); + } + + /* + * If a filename was specified, set 'File' if it exists. + */ + if ( fname != NULL && access(fname, F_OK) == 0 ) + File = fname; + + /* + * Set the test case number and print the results, depending on the + * display type. + */ + if ( ttype == TWARN || ttype == TINFO ) { + /* + * Handle WARN and INFO results (test case number is 0). + */ + if ( Tst_range > 1 ) { + tst_print(TCID, 0, 1, TWARN, + "tst_res(): Range not valid for TINFO or TWARN types"); + } + tst_print(TCID, 0, 1, ttype, tmesg); + } else { + /* + * Handle all other types of results other than WARN and INFO. + */ + if ( Tst_count < 0 ) + tst_print(TCID, 0, 1, TWARN, + "tst_res(): Tst_count < 0 is not valid"); + + /* + * Process each display type. + */ + switch ( T_mode ) { + case DISCARD: + /* do not print any results */ + break; + + case NOPASS: /* passing result types are filtered by tst_print() */ + case CONDENSE: + tst_condense(Tst_count + 1, ttype, tmesg); + break; + + default: /* VERBOSE */ + for ( i = 1 ; i <= Tst_range ; i++ ) + tst_print(TCID, Tst_count + i, Tst_range, ttype, tmesg); + break; + } /* end switch() */ + + /* + * Increment Tst_count. + */ + Tst_count += Tst_range; + } /* if ( ttype == TWARN || ttype == TINFO ) */ + + /* + * Reset some values. + */ + Tst_range = 1; + Expand_varargs = TRUE; +} /* tst_res() */ + + +/* + * tst_condense() - Handle test cases in CONDENSE or NOPASS mode (i.e. + * buffer the current result and print the last result + * if different than the current). If a file was + * specified, print the current result and do not + * buffer it. + */ +static void +tst_condense(int tnum, int ttype, char *tmesg) +{ + char *file; + +#if DEBUG + printf("IN tst_condense: tcid = %s, tnum = %d, ttype = %d, tmesg = %s\n", + TCID, tnum, ttype, tmesg); + fflush(stdout); +#endif + + /* + * If this result is the same as the previous result, return. + */ + if ( Buffered == TRUE ) { + if ( strcmp(Last_tcid, TCID) == 0 && Last_type == ttype && + strcmp(Last_mesg, tmesg) == 0 && File == NULL ) + return; + + /* + * This result is different from the previous result. First, + * print the previous result. + */ + file = File; + File = NULL; + tst_print(Last_tcid, Last_num, tnum - Last_num, Last_type, + Last_mesg); + free(Last_tcid); + free(Last_mesg); + File = file; + } /* if ( Buffered == TRUE ) */ + + /* + * If a file was specified, print the current result since we have no + * way of retaining the file contents for comparing with future + * results. Otherwise, buffer the current result info for next time. + */ + if ( File != NULL ) { + tst_print(TCID, tnum, Tst_range, ttype, tmesg); + Buffered = FALSE; + } else { + Last_tcid = (char *)malloc(strlen(TCID) + 1); + strcpy(Last_tcid, TCID); + Last_num = tnum; + Last_type = ttype; + Last_mesg = (char *)malloc(strlen(tmesg) + 1); + strcpy(Last_mesg, tmesg); + Buffered = TRUE; + } +} /* tst_condense() */ + + +/* + * tst_flush() - Print any messages pending because of CONDENSE mode, + * and flush T_out. + */ +void +tst_flush() +{ +#if DEBUG + printf("IN tst_flush\n"); + fflush(stdout); +#endif + + /* + * Print out last line if in CONDENSE or NOPASS mode. + */ + if ( Buffered == TRUE && (T_mode == CONDENSE || T_mode == NOPASS) ) { + tst_print(Last_tcid, Last_num, Tst_count - Last_num + 1, + Last_type, Last_mesg); + Buffered = FALSE; + } + fflush(T_out); +} /* tst_flush() */ + + +/* + * tst_print() - Actually print a line or range of lines to the output + * stream. + */ +static void +tst_print(char *tcid, int tnum, int trange, int ttype, char *tmesg) +{ + char type[5]; + +#if DEBUG + printf("IN tst_print: tnum = %d, trange = %d, ttype = %d, tmesg = %s\n", + tnum, trange, ttype, tmesg); + fflush(stdout); +#endif + + /* + * Save the test result type by ORing ttype into the current exit + * value (used by tst_exit()). This is already done in tst_res(), but + * is also done here to catch internal warnings. For internal warnings, + * tst_print() is called directly with a case of TWARN. + */ + T_exitval |= ttype; + + /* + * If output mode is DISCARD, or if the output mode is NOPASS and + * this result is not one of FAIL, BROK, or WARN, just return. This + * check is necessary even though we check for DISCARD mode inside of + * tst_res(), since occasionally we get to this point without going + * through tst_res() (e.g. internal TWARN messages). + */ + if ( T_mode == DISCARD || (T_mode == NOPASS && ttype != TFAIL && + ttype != TBROK && ttype != TWARN) ) + return; + + /* + * Fill in the type string according to ttype. + */ + switch ( ttype ) { + case TPASS: + strcpy(type, "PASS"); + break; + case TFAIL: + strcpy(type, "FAIL"); + break; + case TBROK: + strcpy(type, "BROK"); + break; + case TRETR: + strcpy(type, "RETR"); + break; + case TCONF: + strcpy(type, "CONF"); + break; + case TWARN: + strcpy(type, "WARN"); + break; + case TINFO: + strcpy(type, "INFO"); + break; + default: + strcpy(type, "????"); + break; + } /* switch ( ttype ) */ + + /* + * Build the result line and print it. + */ + if ( T_mode == VERBOSE ) { + fprintf(T_out, "%-8s %4d %s : %s\n", tcid, tnum, type, tmesg); + } else { + /* condense results if a range is specified */ + if ( trange > 1 ) + fprintf(T_out, "%-8s %4d-%-4d %s : %s\n", + tcid, tnum, tnum + trange - 1, type, tmesg); + else + fprintf(T_out, "%-8s %4d %s : %s\n", + tcid, tnum, type, tmesg); + } + + /* + * If tst_res() was called with a file, append file contents to the + * end of last printed result. + */ + if ( File != NULL ) + cat_file(File); + File = NULL; +} /* tst_print() */ + + +/* + * check_env() - Check the value of the environment variable TOUTPUT and + * set the global variable T_mode. The TOUTPUT environment + * variable should be set to "VERBOSE", "CONDENSE", + * "NOPASS", or "DISCARD". If TOUTPUT does not exist or + * is not set to a valid value, the default is "VERBOSE". + */ +static void +check_env() +{ + static int first_time = 1; + char *value; /* value of TOUTPUT environment variable */ + +#if DEBUG + printf("IN check_env\n"); + fflush(stdout); +#endif + + if ( !first_time ) + return; + + first_time = 0; + + if ( (value = getenv(TOUTPUT)) == NULL ) { + /* TOUTPUT not defined, use default */ + T_mode = VERBOSE; + } else if ( strcmp(value, TOUT_CONDENSE_S) == 0 ) { + T_mode = CONDENSE; + } else if ( strcmp(value, TOUT_NOPASS_S) == 0 ) { + T_mode = NOPASS; + } else if ( strcmp(value, TOUT_DISCARD_S) == 0 ) { + T_mode = DISCARD; + } else { + /* default */ + T_mode = VERBOSE; + } + + return; +} /* check_env() */ + + +/* + * tst_exit() - Call exit() with the value T_exitval, set up by + * tst_res(). T_exitval has a bit set for most of the + * result types that were seen (including TPASS, TFAIL, + * TBROK, TWARN, TCONF). Also, print the last result (if + * necessary) before exiting. + */ +void +tst_exit() +{ +#if DEBUG + printf("IN tst_exit\n"); fflush(stdout); + fflush(stdout); +#endif + + /* + * Call tst_flush() flush any ouput in the buffer or the last + * result not printed because of CONDENSE mode. + */ + tst_flush(); + + /* + * Mask out TRETR, TINFO, and TCONF results from the exit status. + */ + exit(T_exitval & ~(TRETR | TINFO | TCONF)); +} /* tst_exit() */ + + +/* + * tst_environ() - Preserve the tst_res() output location, despite any + * changes to stdout. + */ +int +tst_environ() +{ + FILE *fdopen(); + + if ( (T_out = fdopen(dup(fileno(stdout)), "w")) == NULL ) + return(-1); + else + return(0); +} /* tst_environ() */ + + +/* + * tst_brk() - Fail or break current test case, and break the remaining + * tests cases. + */ +void +tst_brk(int ttype, char *fname, void (*func)(), char *arg_fmt, ...) +{ + char tmesg[USERMESG]; /* expanded message */ + +#if DEBUG + printf("IN tst_brk\n"); fflush(stdout); + fflush(stdout); +#endif + + /* + * Expand the arg_fmt string into tmesg, if necessary. + */ + EXPAND_VAR_ARGS(arg_fmt, tmesg); + + /* + * Only FAIL, BROK, CONF, and RETR are supported by tst_brk(). + */ + if ( ttype != TFAIL && ttype != TBROK && ttype != TCONF && + ttype != TRETR ) { + sprintf(Warn_mesg, "tst_brk(): Invalid Type: %d. Using TBROK", + ttype); + tst_print(TCID, 0, 1, TWARN, Warn_mesg); + ttype = TBROK; + } + + /* + * Print the first result, if necessary. + */ + if ( Tst_count < TST_TOTAL ) + tst_res(ttype, fname, tmesg); + + /* + * Determine the number of results left to report. + */ + Tst_range = TST_TOTAL - Tst_count; + + /* + * Print the rest of the results, if necessary. + */ + if ( Tst_range > 0 ) { + if ( ttype == TCONF ) + tst_res(ttype, NULL, + "Remaining cases not appropriate for configuration"); + else if ( ttype == TRETR ) + tst_res(ttype, NULL, "Remaining cases retired"); + else + tst_res(TBROK, NULL, "Remaining cases broken"); + } else { + Tst_range = 1; + Expand_varargs = TRUE; + } /* if ( Tst_range > 0 ) */ + + /* + * If no cleanup function was specified, just return to the caller. + * Otherwise call the specified function. If specified function + * returns, call tst_exit(). + */ + if ( func != NULL ) { + (*func)(); + tst_exit(); + } + + return; +} /* tst_brk() */ + + +/* + * tst_brkloop() - Fail or break current test case, and break the + * remaining test cases within test case loop. + */ +void +tst_brkloop(int ttype, char *fname, void (*func)(), char *arg_fmt, ...) +{ + char tmesg[USERMESG]; /* expanded message */ + +#if DEBUG + printf("IN tst_brkloop\n"); fflush(stdout); + fflush(stdout); +#endif + + /* + * Expand the arg_fmt string into tmesg. + */ + EXPAND_VAR_ARGS(arg_fmt, tmesg); + + /* + * Verify that Tst_lpstart & Tst_lptotal are valid. + */ + if ( Tst_lpstart < 0 || Tst_lptotal < 0 ) { + tst_print(TCID, 0, 1, TWARN, + "tst_brkloop(): Tst_lpstart & Tst_lptotal must both be assigned non-negative values"); + Expand_varargs = TRUE; + return; + } + + /* + * Only FAIL, BROK, CONF, and RETR are supported by tst_brkloop(). + */ + if ( ttype != TFAIL && ttype != TBROK && ttype != TCONF && + ttype != TRETR ) { + sprintf(Warn_mesg, + "tst_brkloop(): Invalid Type: %d. Using TBROK", + ttype); + tst_print(TCID, 0, 1, TWARN, Warn_mesg); + ttype = TBROK; + } + + /* + * Print the first result, if necessary. + */ + if ( Tst_count < Tst_lpstart + Tst_lptotal ) + tst_res(ttype, fname, tmesg); + + /* + * Determine the number of results left to report. + */ + Tst_range = Tst_lptotal + Tst_lpstart - Tst_count; + + /* + * Print the rest of the results, if necessary. + */ + if ( Tst_range > 0 ) { + if ( ttype == TCONF ) + tst_res(ttype, NULL, + "Remaining cases in loop not appropriate for configuration"); + else if ( ttype == TRETR ) + tst_res(ttype, NULL, "Remaining cases in loop retired"); + else + tst_res(TBROK, NULL, "Remaining cases in loop broken"); + } else { + Tst_range = 1; + Expand_varargs = TRUE; + } /* if ( Tst_range > 0 ) */ + + /* + * If a cleanup function was specified, call it. + */ + if ( func != NULL ) + (*func)(); +} /* tst_brkloop() */ + + +/* + * tst_resm() - Interface to tst_res(), with no filename. + */ +void +tst_resm(int ttype, char *arg_fmt, ...) +{ + char tmesg[USERMESG]; /* expanded message */ + +#if DEBUG + printf("IN tst_resm\n"); fflush(stdout); + fflush(stdout); +#endif + + /* + * Expand the arg_fmt string into tmesg. + */ + EXPAND_VAR_ARGS(arg_fmt, tmesg); + + /* + * Call tst_res with a null filename argument. + */ + tst_res(ttype, NULL, tmesg); +} /* tst_resm() */ + + +/* + * tst_brkm() - Interface to tst_brk(), with no filename. + */ +void +tst_brkm(int ttype, void (*func)(), char *arg_fmt, ...) +{ + char tmesg[USERMESG]; /* expanded message */ + +#if DEBUG + printf("IN tst_brkm\n"); fflush(stdout); + fflush(stdout); +#endif + + /* + * Expand the arg_fmt string into tmesg. + */ + EXPAND_VAR_ARGS(arg_fmt, tmesg); + + /* + * Call tst_brk with a null filename argument. + */ + tst_brk(ttype, NULL, func, tmesg); +} /* tst_brkm() */ + + +/* + * tst_brkloopm() - Interface to tst_brkloop(), with no filename. + */ +void +tst_brkloopm(int ttype, void (*func)(), char *arg_fmt, ...) +{ + char tmesg[USERMESG]; /* expanded message */ + +#if DEBUG + printf("IN tst_brkloopm\n"); + fflush(stdout); +#endif + + /* + * Expand the arg_fmt string into tmesg. + */ + EXPAND_VAR_ARGS(arg_fmt, tmesg); + + /* + * Call tst_brkloop with a null filename argument. + */ + tst_brkloop(ttype, NULL, func, tmesg); +} /* tst_brkloopm() */ + + +/* + * cat_file() - Print the contents of a file to standard out. + */ +static void +cat_file(char *filename) +{ + FILE *fp; /* file pointer */ + int b_read; /* number of bytes read with read() */ + int b_written; /* number of bytes written with write() */ + char buffer[BUFSIZ]; /* read/write buffer; BUFSIZ defined in */ + /* stdio.h */ + +#if DEBUG + printf("IN cat_file\n"); fflush(stdout); +#endif + + /* + * Open the file for reading. + */ + if ( (fp = fopen(filename, "r")) == NULL ) { + sprintf(Warn_mesg, + "tst_res(): fopen(%s, \"r\") failed; errno = %d: %s", + filename, errno, strerror(errno)); + tst_print(TCID, 0, 1, TWARN, Warn_mesg); + return; + } /* if ( fopen(filename, "r") == -1 ) */ + + /* + * While something to read, continue to read blocks. + * From fread(3) man page: + * If an error occurs, or the end-of-file is reached, the return + * value is zero. + */ + errno = 0; + while ( (b_read = fread((void *)buffer, 1, BUFSIZ, fp)) != (size_t)0 ) { + /* + * Write what was read to the result output stream. + */ + if ( (b_written = fwrite((void *)buffer, 1, b_read, T_out)) != + b_read ) { + sprintf(Warn_mesg, + "tst_res(): While trying to cat \"%s\", fwrite() wrote only %d of %d bytes", + filename, b_written, b_read); + tst_print(TCID, 0, 1, TWARN, Warn_mesg); + break; + } /* if ( b_written != b_read ) */ + } /* while ( fread() != 0 ) */ + + /* + * Check for an fread() error. + */ + if ( !feof(fp) ) { + sprintf(Warn_mesg, + "tst_res(): While trying to cat \"%s\", fread() failed, errno = %d: %s", + filename, errno, strerror(errno)); + tst_print(TCID, 0, 1, TWARN, Warn_mesg); + } /* if ( !feof() ) */ + + /* + * Close the file. + */ + if ( fclose(fp) == EOF ) { + sprintf(Warn_mesg, + "tst_res(): While trying to cat \"%s\", fclose() failed, errno = %d: %s", + filename, errno, strerror(errno)); + tst_print(TCID, 0, 1, TWARN, Warn_mesg); + } /* if ( fclose(fp) == EOF ) */ +} /* cat_file() */ + + + +#ifdef UNIT_TEST +/**************************************************************************** + * Unit test code: Takes input from stdin and can make the following + * calls: tst_res(), tst_resm(), tst_brk(), tst_brkm(), + * tst_flush_buf(), tst_exit(). + ****************************************************************************/ +int TST_TOTAL = 10; +char *TCID = "TESTTCID"; + +#define RES "tst_res.c UNIT TEST message; ttype = %d; contents of \"%s\":" +#define RESM "tst_res.c UNIT TEST message; ttype = %d" + +main() +{ + int ttype; + int range; + char *chrptr; + char chr; + char fname[MAXMESG]; + + printf("UNIT TEST of tst_res.c. Options for ttype:\n\ + -1 : call tst_exit()\n\ + -2 : call tst_flush()\n\ + -3 : call tst_brk()\n\ + -4 : call tst_brkloop()\n\ + -5 : call tst_res() with a range\n\ + 0 : call tst_res(TPASS, ...)\n\ + 1 : call tst_res(TFAIL, ...)\n\ + 2 : call tst_res(TBROK, ...)\n\ + 4 : call tst_res(TWARN, ...)\n\ + 8 : call tst_res(TRETR, ...)\n\ + 16 : call tst_res(TINFO, ...)\n\ + 32 : call tst_res(TCONF, ...)\n\n"); + + while ( 1 ) { + printf("Enter ttype (-5,-4,-3,-2,-1,0,1,2,4,8,16,32): "); + (void) scanf("%d%c", &ttype, &chr); + + + switch ( ttype ) { + case -1: + tst_exit(); + break; + + case -2: + tst_flush(); + break; + + case -3: + printf("Enter the current type (1=FAIL, 2=BROK, 8=RETR, 32=CONF): "); + (void) scanf("%d%c", &ttype, &chr); + printf("Enter file name ( for none): "); + gets(fname); + if ( strcmp(fname, "") == 0 ) + tst_brkm(ttype, tst_exit, RESM, ttype); + else + tst_brk(ttype, fname, tst_exit, RES, ttype, fname); + break; + + case -4: + printf("Enter the size of the loop: "); + (void) scanf("%d%c", &range, &chr); + Tst_lpstart = Tst_count; + Tst_lptotal = range; + printf("Enter the current type (1=FAIL, 2=BROK, 8=RETR, 32=CONF): "); + (void) scanf("%d%c", &ttype, &chr); + printf("Enter file name ( for none): "); + gets(fname); + if ( strcmp(fname, "") == 0 ) + tst_brkloopm(ttype, NULL, RESM, ttype); + else + tst_brkloop(ttype, fname, NULL, RES, ttype, fname); + break; + + case -5: + printf("Enter the size of the range: "); + (void) scanf("%d%c", &Tst_range, &chr); + printf("Enter the current type (0,1,2,4,8,16,32): "); + (void) scanf("%d%c", &ttype, &chr); + /* fall through to tst_res() call */ + + default: + printf("Enter file name ( for none): "); + gets(fname); + if ( strcmp(fname, "") == 0 ) + tst_resm(ttype, RESM, ttype); + else + tst_res(ttype, fname, RES, ttype, fname); + break; + } /* switch() */ + } /* while() */ +} +#endif /* UNIT_TEST */ diff --git a/winsup/testsuite/libltp/lib/tst_sig.c b/winsup/testsuite/libltp/lib/tst_sig.c new file mode 100644 index 000000000..c0d5bbf46 --- /dev/null +++ b/winsup/testsuite/libltp/lib/tst_sig.c @@ -0,0 +1,213 @@ +/* + * 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$ */ + +/***************************************************************************** + 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. + +***************************************************************************/ + +#ifndef CRAY +#define _BSD_SIGNALS 1 /* Specify that we are using BSD signal interface */ +#endif + +#include +#include +#include +#include "test.h" + +#define MAXMESG 150 /* size of mesg string sent to tst_res */ + +void (*T_cleanup)(); /* pointer to cleanup function */ + +extern int errno; +static void def_handler(); /* default signal handler */ + +/**************************************************************************** + * 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; + + /* + * save T_cleanup and handler function pointers + */ + T_cleanup = cleanup; /* used by default handler */ + + if (handler == DEF_HANDLER) { + /* use default handler */ + handler = def_handler; + } + + /* + * 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 + */ + + switch (sig) { + case SIGKILL: + case SIGSTOP: + case SIGCONT: +#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 */ + + break; + + case SIGCLD: + if ( fork_flag == FORK ) + continue; + + default: + if (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) +{ + char mesg[MAXMESG]; /* holds tst_res message */ + + /* first reset trap for this signal (except SIGCLD - its weird) */ + if ((sig != SIGCLD) && (sig != SIGSTOP) && (sig != SIGCONT)) { + if (signal(sig, def_handler) == SIG_ERR) { + (void) sprintf(mesg, + "def_handler: signal() failed for signal %d. error:%d %s.", + sig, errno, strerror(errno)); + tst_resm(TWARN, mesg); + } + } + + (void) sprintf(mesg, "Unexpected signal %d received.", sig); + + /* + * Break remaining test cases, do any cleanup, then exit + */ + tst_brkm(TBROK, 0, mesg); + + /* now cleanup and exit */ + if (T_cleanup) { + (*T_cleanup)(); + } + + tst_exit(); +} diff --git a/winsup/testsuite/libltp/lib/tst_tmpdir.c b/winsup/testsuite/libltp/lib/tst_tmpdir.c new file mode 100644 index 000000000..ef1e2cd70 --- /dev/null +++ b/winsup/testsuite/libltp/lib/tst_tmpdir.c @@ -0,0 +1,351 @@ +/* + * 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$ */ + +/********************************************************** + * + * 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 +#include +#include /* for getenv() */ +#include /* for string functions */ +#include /* for sysconf(), getcwd(), rmdir() */ +#include /* for mkdir() */ +#include /* 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 prefix[PREFIX_SIZE]; /* first three characters from TCID */ + int no_cleanup = 0; /* !0 means TDIRECTORY env var was set */ + + /* + * If the TDIRECTORY env variable is not set, a temp dir will be + * created. + */ + if ( (TESTDIR = getenv(TDIRECTORY)) == NULL ) { + /* + * Create a unique name based on the first three characters of the + * TCID. The last byte in "prefix" is for the null. + */ + strncpy(prefix, TCID, PREFIX_SIZE - 1); + prefix[PREFIX_SIZE-1] = '\0'; + if ( (TESTDIR = tempnam(TEMPDIR, prefix)) == NULL ) + tst_brkm(TBROK, tmpdir_cleanup, "%s: tempnam(%s, %s) failed", + FN_NAME, TEMPDIR, prefix); + + /* + * Create the temporary directory. + */ + if ( mkdir(TESTDIR, DIR_MODE) == -1 ) + tst_brkm(TBROK, tmpdir_cleanup, + "%s: mkdir(%s, %#o) failed; errno = %d: %s", + FN_NAME, TESTDIR, DIR_MODE, errno, strerror(errno)); + + /* + * Change the group on this temporary directory to be that of the + * gid of the person running the tests. + */ + if ( chown(TESTDIR, -1, getgid()) == -1 ) + tst_brkm(TBROK, tmpdir_cleanup, + "chown(%s, -1, %d) failed; errno = %d: %s", + TESTDIR, getgid(), errno, strerror(errno)); + } else { + /* + * The TDIRECTORY env. variable is set, so no temp dir is created. + * Also, no clean up will be done via tst_rmdir(). + */ + no_cleanup++; +#if UNIT_TEST + printf("TDIRECTORY env var is set\n"); +#endif + } + +#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 */ diff --git a/winsup/testsuite/libltp/lib/write_log.c b/winsup/testsuite/libltp/lib/write_log.c new file mode 100644 index 000000000..316dfe79b --- /dev/null +++ b/winsup/testsuite/libltp/lib/write_log.c @@ -0,0 +1,468 @@ +/* + * 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/ + */ +/* + * This module contains code for logging writes to files, and for + * perusing the resultant logfile. The main intent of all this is + * to provide a 'write history' of a file which can be examined to + * judge the state of a file (ie. whether it is corrupted or not) based + * on the write activity. + * + * The main abstractions available to the user are the wlog_file, and + * the wlog_rec. A wlog_file is a handle encapsulating a write logfile. + * It is initialized with the wlog_open() function. This handle is + * then passed to the various wlog_xxx() functions to provide transparent + * access to the write logfile. + * + * The wlog_rec datatype is a structure which contains all the information + * about a file write. Examples include the file name, offset, length, + * pattern, etc. In addition there is a bit which is cleared/set based + * on whether or not the write has been confirmed as complete. This + * allows the write logfile to contain information on writes which have + * been initiated, but not yet completed (as in async io). + * + * There is also a function to scan a write logfile in reverse order. + * + * NOTE: For target file analysis based on a write logfile, the + * assumption is made that the file being written to is + * locked from simultaneous access, so that the order of + * write completion is predictable. This is an issue when + * more than 1 process is trying to write data to the same + * target file simultaneously. + * + * The history file created is a collection of variable length records + * described by scruct wlog_rec_disk in write_log.h. See that module for + * the layout of the data on disk. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "write_log.h" + +#ifndef BSIZE +#ifdef linux +#define BSIZE DEV_BSIZE +#else +#ifdef __CYGWIN__ +#define BSIZE S_BLKSIZE +#else +#define BSIZE BBSIZE +#endif +#endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 255 +/*#define PATH_MAX pathconf("/", _PC_PATH_MAX)*/ +#endif + +char Wlog_Error_String[256]; + +#if __STDC__ +static int wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag); +static int wlog_rec_unpack(struct wlog_rec *wrec, char *buf); +#else +static int wlog_rec_pack(); +static int wlog_rec_unpack(); +#endif + +/* + * Initialize a write logfile. wfile is a wlog_file structure that has + * the w_file field filled in. The rest of the information in the + * structure is initialized by the routine. + * + * The trunc flag is used to indicate whether or not the logfile should + * be truncated if it currently exists. If it is non-zero, the file will + * be truncated, otherwise it will be appended to. + * + * The mode argument is the [absolute] mode which the file will be + * given if it does not exist. This mode is not affected by your process + * umask. + */ + +int +wlog_open(wfile, trunc, mode) +struct wlog_file *wfile; +int trunc; +int mode; +{ + int omask, oflags; + + if (trunc) + trunc = O_TRUNC; + + omask = umask(0); + + /* + * Open 1 file descriptor as O_APPEND + */ + + oflags = O_WRONLY | O_APPEND | O_CREAT | trunc; + wfile->w_afd = + open(wfile->w_file, oflags, mode); + umask(omask); + + if (wfile->w_afd == -1) { + sprintf(Wlog_Error_String, + "Could not open write_log - open(%s, %#o, %#o) failed: %s\n", + wfile->w_file, oflags, mode, strerror(errno)); + return -1; + } + + /* + * Open the next fd as a random access descriptor + */ + + oflags = O_RDWR; + if ((wfile->w_rfd = open(wfile->w_file, oflags)) == -1) { + sprintf(Wlog_Error_String, + "Could not open write log - open(%s, %#o) failed: %s\n", + wfile->w_file, oflags, strerror(errno)); + close(wfile->w_afd); + wfile->w_afd = -1; + return -1; + } + + return 0; +} + +/* + * Release all resources associated with a wlog_file structure allocated + * with the wlog_open() call. + */ + +int +wlog_close(wfile) +struct wlog_file *wfile; +{ + close(wfile->w_afd); + close(wfile->w_rfd); + return 0; +} + +/* + * Write a wlog_rec structure to a write logfile. Offset is used to + * control where the record will be written. If offset is < 0, the + * record will be appended to the end of the logfile. Otherwise, the + * record which exists at the indicated offset will be overlayed. This + * is so that we can record writes which are outstanding (with the w_done + * bit in wrec cleared), but not completed, and then later update the + * logfile when the write request completes (as with async io). When + * offset is >= 0, only the fixed length portion of the record is + * rewritten. See text in write_log.h for details on the format of an + * on-disk record. + * + * The return value of the function is the byte offset in the logfile + * where the record begins. + * + * Note: It is the callers responsibility to make sure that the offset + * parameter 'points' to a valid record location when a record is to be + * overlayed. This is guarenteed by saving the return value of a previous + * call to wlog_record_write() which wrote the record to be overlayed. + * + * Note2: The on-disk version of the wlog_rec is MUCH different than + * the user version. Don't expect to od the logfile and see data formatted + * as it is in the wlog_rec structure. Considerable data packing takes + * place before the record is written. + */ + +int +wlog_record_write(wfile, wrec, offset) +struct wlog_file *wfile; +struct wlog_rec *wrec; +long offset; +{ + int reclen; + char wbuf[WLOG_REC_MAX_SIZE + 2]; + + /* + * If offset is -1, we append the record at the end of file + * + * Otherwise, we overlay wrec at the file offset indicated and assume + * that the caller passed us the correct offset. We do not record the + * fname in this case. + */ + + reclen = wlog_rec_pack(wrec, wbuf, (offset < 0)); + + if (offset < 0) { + /* + * Since we're writing a complete new record, we must also tack + * its length onto the end so that wlog_scan_backward() will work. + * Length is asumed to fit into 2 bytes. + */ + + wbuf[reclen] = reclen / 256; + wbuf[reclen+1] = reclen % 256; + reclen += 2; + + write(wfile->w_afd, wbuf, reclen); + offset = lseek(wfile->w_afd, 0, SEEK_CUR) - reclen; + } else { + lseek(wfile->w_rfd, offset, SEEK_SET); + write(wfile->w_rfd, wbuf, reclen); + } + + return offset; +} + +/* + * Function to scan a logfile in reverse order. Wfile is a valid + * wlog_file structure initialized by wlog_open(). nrecs is the number + * of records to scan (all records are scanned if nrecs is 0). func is + * a user-supplied function to call for each record found. The function + * will be passed a single parameter - a wlog_rec structure . + */ + +int +wlog_scan_backward(wfile, nrecs, func, data) +struct wlog_file *wfile; +int nrecs; +int (*func)(); +long data; +{ + int fd, leftover, nbytes, offset, recnum, reclen, rval; + char buf[BSIZE*32], *bufend, *cp, *bufstart; + char albuf[WLOG_REC_MAX_SIZE]; + struct wlog_rec wrec; + + fd = wfile->w_rfd; + + /* + * Move to EOF. offset will always hold the current file offset + */ + + lseek(fd, 0, SEEK_END); + offset = lseek(fd, 0, SEEK_CUR); + + bufend = buf + sizeof(buf); + bufstart = buf; + + recnum = 0; + leftover = 0; + while ((!nrecs || recnum < nrecs) && offset > 0) { + /* + * Check for beginning of file - if there aren't enough bytes + * remaining to fill buf, adjust bufstart. + */ + + if (offset + leftover < sizeof(buf)) { + bufstart = bufend - (offset + leftover); + offset = 0; + } else { + offset -= sizeof(buf) - leftover; + } + + /* + * Move to the proper file offset, and read into buf + */ + + lseek(fd, offset, SEEK_SET); + nbytes = read(fd, bufstart, bufend - bufstart - leftover); + + if (nbytes == -1) { + sprintf(Wlog_Error_String, + "Could not read history file at offset %d - read(%d, %#o, %d) failed: %s\n", + offset, fd, (int)bufstart, + bufend - bufstart - leftover, strerror(errno)); + return -1; + } + + cp = bufend; + leftover = 0; + + while (cp >= bufstart) { + + /* + * If cp-bufstart is not large enough to hold a piece + * of record length information, copy remainder to end + * of buf and continue reading the file. + */ + + if (cp - bufstart < 2) { + leftover = cp - bufstart; + memcpy(bufend - leftover, bufstart, leftover); + break; + } + + /* + * Extract the record length. We must do it this way + * instead of casting cp to an int because cp might + * not be word aligned. + */ + + reclen = (*(cp-2) * 256) + *(cp -1); + + /* + * If cp-bufstart isn't large enough to hold a + * complete record, plus the length information, copy + * the leftover bytes to the end of buf and continue + * reading. + */ + + if (cp - bufstart < reclen + 2) { + leftover = cp - bufstart; + memcpy(bufend - leftover, bufstart, leftover); + break; + } + + /* + * Adjust cp to point at the start of the record. + * Copy the record into wbuf so that it is word + * aligned and pass the record to the user supplied + * function. + */ + + cp -= reclen + 2; + memcpy(albuf, cp, reclen); + + wlog_rec_unpack(&wrec, albuf); + + /* + * Call the user supplied function - + * stop if instructed to. + */ + + if ((rval = (*func)(&wrec, data)) == WLOG_STOP_SCAN) { + break; + } + + recnum++; + + if (nrecs && recnum >= nrecs) + break; + } + } + + return 0; +} + +/* + * The following 2 routines are used to pack and unpack the user + * visible wlog_rec structure to/from a character buffer which is + * stored or read from the write logfile. Any changes to either of + * these routines must be reflected in the other. + */ + +static int +wlog_rec_pack(wrec, buf, flag) +struct wlog_rec *wrec; +char *buf; +int flag; +{ + char *file, *host, *pattern; + struct wlog_rec_disk *wrecd; + + wrecd = (struct wlog_rec_disk *)buf; + + wrecd->w_pid = (uint)wrec->w_pid; + wrecd->w_offset = (uint)wrec->w_offset; + wrecd->w_nbytes = (uint)wrec->w_nbytes; + wrecd->w_oflags = (uint)wrec->w_oflags; + wrecd->w_done = (uint)wrec->w_done; + wrecd->w_async = (uint)wrec->w_async; + + wrecd->w_pathlen = (wrec->w_pathlen > 0) ? (uint)wrec->w_pathlen : 0; + wrecd->w_hostlen = (wrec->w_hostlen > 0) ? (uint)wrec->w_hostlen : 0; + wrecd->w_patternlen = (wrec->w_patternlen > 0) ? (uint)wrec->w_patternlen : 0; + + /* + * If flag is true, we should also pack the variable length parts + * of the wlog_rec. By default, we only pack the fixed length + * parts. + */ + + if (flag) { + file = buf + sizeof(struct wlog_rec_disk); + host = file + wrecd->w_pathlen; + pattern = host + wrecd->w_hostlen; + + if (wrecd->w_pathlen > 0) + memcpy(file, wrec->w_path, wrecd->w_pathlen); + + if (wrecd->w_hostlen > 0) + memcpy(host, wrec->w_host, wrecd->w_hostlen); + + if (wrecd->w_patternlen > 0) + memcpy(pattern, wrec->w_pattern, wrecd->w_patternlen); + + return (sizeof(struct wlog_rec_disk) + + wrecd->w_pathlen + wrecd->w_hostlen + wrecd->w_patternlen); + } else { + return sizeof(struct wlog_rec_disk); + } +} + +static int +wlog_rec_unpack(wrec, buf) +struct wlog_rec *wrec; +char *buf; +{ + char *file, *host, *pattern; + struct wlog_rec_disk *wrecd; + + bzero((char *)wrec, sizeof(struct wlog_rec)); + wrecd = (struct wlog_rec_disk *)buf; + + wrec->w_pid = wrecd->w_pid; + wrec->w_offset = wrecd->w_offset; + wrec->w_nbytes = wrecd->w_nbytes; + wrec->w_oflags = wrecd->w_oflags; + wrec->w_hostlen = wrecd->w_hostlen; + wrec->w_pathlen = wrecd->w_pathlen; + wrec->w_patternlen = wrecd->w_patternlen; + wrec->w_done = wrecd->w_done; + wrec->w_async = wrecd->w_async; + + if (wrec->w_pathlen > 0) { + file = buf + sizeof(struct wlog_rec_disk); + memcpy(wrec->w_path, file, wrec->w_pathlen); + } + + if (wrec->w_hostlen > 0) { + host = buf + sizeof(struct wlog_rec_disk) + wrec->w_pathlen; + memcpy(wrec->w_host, host, wrec->w_hostlen); + } + + if (wrec->w_patternlen > 0) { + pattern = buf + sizeof(struct wlog_rec_disk) + + wrec->w_pathlen + wrec->w_hostlen; + memcpy(wrec->w_pattern, pattern, wrec->w_patternlen); + } + + return 0; +} -- cgit v1.2.3