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
tst_tmpdir_created(void)100 int tst_tmpdir_created(void)
101 {
102 return TESTDIR != NULL;
103 }
104
tst_get_tmpdir(void)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
tst_get_startwd(void)113 const char *tst_get_startwd(void)
114 {
115 return test_start_work_dir;
116 }
117
tst_tmpdir(void)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
tst_rmdir(void)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