1 /********************************************************** 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 31 *********************************************************/ 32 33 /********************************************************** 34 * 35 * OS Testing - Silicon Graphics, Inc. 36 * 37 * FUNCTION NAME : tst_tmpdir, tst_rmdir 38 * 39 * FUNCTION TITLE : Create/remove a testing temp dir 40 * 41 * SYNOPSIS: 42 * void tst_tmpdir(); 43 * void tst_rmdir(); 44 * 45 * AUTHOR : Dave Fenner 46 * 47 * INITIAL RELEASE : UNICOS 8.0 48 * 49 * DESCRIPTION 50 * tst_tmpdir() is used to create a unique, temporary testing 51 * directory, and make it the current working directory. 52 * tst_rmdir() is used to remove the directory created by 53 * tst_tmpdir(). 54 * 55 * RETURN VALUE 56 * Neither tst_tmpdir() or tst_rmdir() has a return value. 57 * 58 *********************************************************/ 59 60 #include <sys/mman.h> 61 #include <sys/types.h> 62 #include <sys/stat.h> 63 #include <assert.h> 64 #include <errno.h> 65 #include <libgen.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <unistd.h> 70 71 #include "test.h" 72 #include "rmobj.h" 73 #include "ltp_priv.h" 74 #include "lapi/futex.h" 75 76 /* 77 * Define some useful macros. 78 */ 79 #define DIR_MODE (S_IRWXU|S_IRWXG|S_IRWXO) 80 81 #ifndef PATH_MAX 82 #ifdef MAXPATHLEN 83 #define PATH_MAX MAXPATHLEN 84 #else 85 #define PATH_MAX 1024 86 #endif 87 #endif 88 89 /* 90 * Define global variables. 91 */ 92 extern char *TCID; /* defined/initialized in main() */ 93 static char *TESTDIR = NULL; /* the directory created */ 94 95 static char test_start_work_dir[PATH_MAX]; 96 97 /* lib/tst_checkpoint.c */ 98 extern futex_t *tst_futexes; 99 100 int tst_tmpdir_created(void) 101 { 102 return TESTDIR != NULL; 103 } 104 105 char *tst_get_tmpdir(void) 106 { 107 /* Smack the user for calling things out of order. */ 108 if (TESTDIR == NULL) 109 tst_brkm(TBROK, NULL, "you must call tst_tmpdir() first"); 110 return strdup(TESTDIR); 111 } 112 113 const char *tst_get_startwd(void) 114 { 115 return test_start_work_dir; 116 } 117 118 void tst_tmpdir(void) 119 { 120 char template[PATH_MAX]; 121 char *env_tmpdir; 122 char *errmsg, *c; 123 124 /* 125 * Create a template for the temporary directory. Use the 126 * environment variable TMPDIR if it is available, otherwise 127 * use our default TEMPDIR. 128 */ 129 env_tmpdir = getenv("TMPDIR"); 130 if (env_tmpdir) { 131 c = strchr(env_tmpdir, '/'); 132 /* 133 * Now we force environment variable TMPDIR to be an absolute 134 * pathname, which dose not make much sense, but it will 135 * greatly simplify code in tst_rmdir(). 136 */ 137 if (c != env_tmpdir) { 138 tst_brkm(TBROK, NULL, "You must specify an absolute " 139 "pathname for environment variable TMPDIR"); 140 } 141 snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", env_tmpdir, TCID); 142 } else { 143 snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID); 144 } 145 146 /* Make the temporary directory in one shot using mkdtemp. */ 147 if (mkdtemp(template) == NULL) 148 tst_brkm(TBROK | TERRNO, NULL, 149 "%s: mkdtemp(%s) failed", __func__, template); 150 if ((TESTDIR = strdup(template)) == NULL) 151 tst_brkm(TBROK | TERRNO, NULL, 152 "%s: strdup(%s) failed", __func__, template); 153 154 if (chown(TESTDIR, -1, getgid()) == -1) 155 tst_brkm(TBROK | TERRNO, NULL, 156 "chown(%s, -1, %d) failed", TESTDIR, getgid()); 157 if (chmod(TESTDIR, DIR_MODE) == -1) 158 tst_brkm(TBROK | TERRNO, NULL, 159 "chmod(%s, %#o) failed", TESTDIR, DIR_MODE); 160 161 if (getcwd(test_start_work_dir, sizeof(test_start_work_dir)) == NULL) { 162 tst_resm(TINFO, "Failed to record test working dir"); 163 test_start_work_dir[0] = '\0'; 164 } 165 166 /* 167 * Change to the temporary directory. If the chdir() fails, issue 168 * TBROK messages for all test cases, attempt to remove the 169 * directory (if it was created), and exit. If the removal also 170 * fails, also issue a TWARN message. 171 */ 172 if (chdir(TESTDIR) == -1) { 173 tst_resm(TERRNO, "%s: chdir(%s) failed", __func__, TESTDIR); 174 175 /* Try to remove the directory */ 176 if (rmobj(TESTDIR, &errmsg) == -1) { 177 tst_resm(TWARN, "%s: rmobj(%s) failed: %s", 178 __func__, TESTDIR, errmsg); 179 } 180 181 tst_exit(); 182 } 183 } 184 185 void tst_rmdir(void) 186 { 187 char *errmsg; 188 189 /* 190 * Check that TESTDIR is not NULL. 191 */ 192 if (TESTDIR == NULL) { 193 tst_resm(TWARN, 194 "%s: TESTDIR was NULL; no removal attempted", 195 __func__); 196 return; 197 } 198 199 /* 200 * Unmap the backend file. 201 * This is needed to overcome the NFS "silly rename" feature. 202 */ 203 if (tst_futexes) { 204 msync((void *)tst_futexes, getpagesize(), MS_SYNC); 205 munmap((void *)tst_futexes, getpagesize()); 206 } 207 208 /* 209 * Attempt to remove the "TESTDIR" directory, using rmobj(). 210 */ 211 if (rmobj(TESTDIR, &errmsg) == -1) { 212 tst_resm(TWARN, "%s: rmobj(%s) failed: %s", 213 __func__, TESTDIR, errmsg); 214 } 215 } 216