Adapt copyright for a new version
[ltp-debian.git] / lib / tst_tmpdir.c
blob9c9809efd5522ca9ea8470f108aaac24458ffb97
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
26 * http://www.sgi.com
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
33 /* $Id: tst_tmpdir.c,v 1.14 2009/07/20 10:59:32 vapier Exp $ */
35 /**********************************************************
37 * OS Testing - Silicon Graphics, Inc.
39 * FUNCTION NAME : tst_tmpdir, tst_rmdir
41 * FUNCTION TITLE : Create/remove a testing temp dir
43 * SYNOPSIS:
44 * void tst_tmpdir();
45 * void tst_rmdir();
47 * AUTHOR : Dave Fenner
49 * INITIAL RELEASE : UNICOS 8.0
51 * DESCRIPTION
52 * tst_tmpdir() is used to create a unique, temporary testing
53 * directory, and make it the current working directory.
54 * tst_rmdir() is used to remove the directory created by
55 * tst_tmpdir().
57 * Setting the env variable "TDIRECTORY" will override the creation
58 * of a new temp dir. The directory specified by TDIRECTORY will
59 * be used as the temporary directory, and no removal will be done
60 * in tst_rmdir().
62 * RETURN VALUE
63 * Neither tst_tmpdir() or tst_rmdir() has a return value.
65 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
66 #include <stdio.h>
67 #include <errno.h>
68 #include <stdlib.h> /* for getenv() */
69 #include <string.h> /* for string functions */
70 #include <unistd.h> /* for sysconf(), getcwd(), rmdir() */
71 #include <sys/types.h> /* for mkdir() */
72 #include <sys/stat.h> /* for mkdir() */
73 #include "test.h"
74 #include "rmobj.h"
77 * Define some useful macros.
79 #define PREFIX_SIZE 4
80 #define STRING_SIZE 256
81 #define DIR_MODE 0777 /* mode of tmp dir that will be created */
83 #ifndef PATH_MAX
84 #ifdef MAXPATHLEN
85 #define PATH_MAX MAXPATHLEN
86 #else
87 #define PATH_MAX 1024
88 #endif
89 #endif
92 * Define function prototypes.
94 static void tmpdir_cleanup();
97 * Define global variables.
99 extern char *TCID; /* defined/initialized in main() */
100 extern int TST_TOTAL; /* defined/initialized in main() */
101 extern char *TESTDIR; /* the directory created; defined in */
102 /* tst_res.c */
105 * tst_tmpdir() - Create a unique temporary directory and chdir() to it.
106 * It expects the caller to have defined/initialized the
107 * TCID/TST_TOTAL global variables. The TESTDIR global
108 * variable will be set to the directory that gets used
109 * as the testing directory.
111 * NOTE: This function must be called BEFORE any activity
112 * that would require CLEANUP. If tst_tmpdir() fails, it
113 * cleans up afer itself and calls tst_exit() (i.e. does
114 * not return).
116 #undef FN_NAME
117 #define FN_NAME "tst_tmpdir()"
119 void tst_tmpdir(void)
121 char template[PATH_MAX]; /* template for mkstemp, mkdtemp */
122 int no_cleanup = 0; /* !0 means TDIRECTORY env var was set */
123 char *env_tmpdir; /* temporary storage for TMPDIR env var */
124 /* This is an AWEFUL hack to figure out if mkdtemp() is available */
125 #if defined(__GLIBC_PREREQ)
126 # if __GLIBC_PREREQ(2,2)
127 # define HAVE_MKDTEMP 1
128 # else
129 # define HAVE_MKDTEMP 0
130 int tfd;
131 # endif
132 #else
133 # define HAVE_MKDTEMP 0
134 int tfd;
135 #endif
137 * If the TDIRECTORY env variable is not set, a temp dir will be
138 * created.
140 if ((TESTDIR = getenv(TDIRECTORY))) {
142 * The TDIRECTORY env. variable is set, so no temp dir is created.
143 * Also, no clean up will be done via tst_rmdir().
145 mkdir(TESTDIR,DIR_MODE); /*Try to create the directory if it does not exist already,
146 user might forget to create one before exporting TDIRECTORY,
147 Will fail if it already exists, no issues in that*/
148 no_cleanup++;
149 #if UNIT_TEST
150 printf("TDIRECTORY env var is set\n");
151 #endif
152 } else {
154 * Create a template for the temporary directory. Use the
155 * environment variable TMPDIR if it is available, otherwise
156 * use our default TEMPDIR.
158 if ((env_tmpdir = getenv("TMPDIR"))) {
159 snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", env_tmpdir, TCID);
160 } else {
161 snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID);
165 #if HAVE_MKDTEMP
167 * Make the temporary directory in one shot using mkdtemp()
169 if (mkdtemp(template) == NULL)
170 tst_brkm(TBROK, tmpdir_cleanup,
171 "%s: mkdtemp(%s) failed; errno = %d: %s",
172 FN_NAME, template, errno, strerror(errno));
173 if ( (TESTDIR = strdup(template)) == NULL ) { //Error Handling for strdup()
174 tst_brkm(TBROK, tmpdir_cleanup,
175 "%s: strdup(%s) failed; errno = %d: %s",
176 FN_NAME, template, errno, strerror(errno));
178 #else
180 * Make the template name, then the directory
182 if ((tfd = mkstemp(template)) == -1)
183 tst_brkm(TBROK, tmpdir_cleanup,
184 "%s: mkstemp(%s) failed; errno = %d: %s",
185 FN_NAME, template, errno, strerror(errno));
186 if ( close(tfd) == -1 ) {
187 tst_brkm(TBROK, tmpdir_cleanup,
188 "%s: close() failed; errno = %d: %s",
189 FN_NAME, errno, strerror(errno));
191 if ( unlink(template) == -1) {
192 tst_brkm(TBROK, tmpdir_cleanup,
193 "%s: unlink(%s) failed; errno = %d: %s",
194 FN_NAME, template, errno, strerror(errno));
196 if ( (TESTDIR = strdup(template)) == NULL ) {
197 tst_brkm(TBROK, tmpdir_cleanup,
198 "%s: strdup(%s) failed; errno = %d: %s",
199 FN_NAME, template, errno, strerror(errno));
201 if (mkdir(TESTDIR, DIR_MODE)) {
202 /* If we start failing with EEXIST, wrap this section in
203 * a loop so we can try again.
205 tst_brkm(TBROK, tmpdir_cleanup,
206 "%s: mkdir(%s, %#o) failed; errno = %d: %s",
207 FN_NAME, TESTDIR, DIR_MODE, errno,
208 strerror(errno));
210 #endif
213 * Change the group on this temporary directory to be that of the
214 * gid of the person running the tests and permissions to 777.
216 if ( chown(TESTDIR, -1, getgid()) == -1 )
217 tst_brkm(TBROK, tmpdir_cleanup,
218 "chown(%s, -1, %d) failed; errno = %d: %s",
219 TESTDIR, getgid(), errno, strerror(errno));
220 if ( chmod(TESTDIR,S_IRWXU | S_IRWXG | S_IRWXO) == -1 )
221 tst_brkm(TBROK, tmpdir_cleanup,
222 "chmod(%s,777) failed; errno %d: %s",
223 TESTDIR, errno, strerror(errno));
226 #if UNIT_TEST
227 printf("TESTDIR = %s\n", TESTDIR);
228 #endif
231 * Change to the temporary directory. If the chdir() fails, issue
232 * TBROK messages for all test cases, attempt to remove the
233 * directory (if it was created), and exit. If the removal also
234 * fails, also issue a TWARN message.
236 if ( chdir(TESTDIR) == -1 ) {
237 tst_brkm(TBROK, NULL, "%s: chdir(%s) failed; errno = %d: %s",
238 FN_NAME, TESTDIR, errno, strerror(errno) );
240 /* Try to remove the directory */
241 if ( !no_cleanup && rmdir(TESTDIR) == -1 )
242 tst_resm(TWARN, "%s: rmdir(%s) failed; errno = %d: %s",
243 FN_NAME, TESTDIR, errno, strerror(errno) );
245 tmpdir_cleanup();
248 #if UNIT_TEST
249 printf("CWD is %s\n", getcwd((char *)NULL, PATH_MAX));
250 #endif
253 * If we made through all this stuff, return.
255 return;
256 } /* tst_tmpdir() */
261 * tst_rmdir() - Recursively remove the temporary directory created by
262 * tst_tmpdir(). This function is intended ONLY as a
263 * companion to tst_tmpdir(). If the TDIRECTORY
264 * environment variable is set, no cleanup will be
265 * attempted.
267 #undef FN_NAME
268 #define FN_NAME "tst_rmdir()"
270 void tst_rmdir(void)
272 char *errmsg;
273 char *tdirectory;
274 char current_dir[PATH_MAX]; /* current working directory */
275 char parent_dir[PATH_MAX]; /* directory above TESTDIR */
276 char *basename; /* basename of the TESTDIR */
279 * If the TDIRECTORY env variable is set, this indicates that no
280 * temp dir was created by tst_tmpdir(). Thus no cleanup will be
281 * necessary.
283 if ( (tdirectory = getenv(TDIRECTORY)) != NULL ) {
284 #if UNIT_TEST
285 printf("\"TDIRECORY\" env variable is set; no cleanup was performed\n");
286 #endif
287 return;
291 * Check that TESTDIR is not NULL.
293 if ( TESTDIR == NULL ) {
294 tst_resm(TWARN, "%s: TESTDIR was NULL; no removal attempted",
295 FN_NAME);
296 return;
300 * Check that the value of TESTDIR is not "*" or "/". These could
301 * have disastrous effects in a test run by root.
303 if ( strcmp(TESTDIR, "/") == 0 ) {
304 tst_resm(TWARN,
305 "%s: Recursive remove of root directory not attempted",
306 FN_NAME);
307 return;
310 if ( strchr(TESTDIR, '*') != NULL ) {
311 tst_resm(TWARN, "%s: Recursive remove of '*' not attempted",
312 FN_NAME);
313 return;
317 * Get the directory name of TESTDIR. If TESTDIR is a relative path,
318 * get full path.
320 if ( TESTDIR[0] != '/' ) {
321 if ( getcwd(current_dir,PATH_MAX) == NULL )
322 strcpy(parent_dir, TESTDIR);
323 else
324 sprintf(parent_dir, "%s/%s", current_dir, TESTDIR);
325 } else {
326 strcpy(parent_dir, TESTDIR);
328 if ( (basename = strrchr(parent_dir, '/')) != NULL ) {
329 *basename='\0'; /* terminate at end of parent_dir */
333 * Change directory to parent_dir (The dir above TESTDIR).
335 if ( chdir(parent_dir) != 0 )
336 tst_resm(TWARN,
337 "%s: chdir(%s) failed; errno = %d: %s\nAttempting to remove temp dir anyway",
338 FN_NAME, parent_dir, errno, strerror(errno));
341 * Attempt to remove the "TESTDIR" directory, using rmobj().
343 if ( rmobj(TESTDIR, &errmsg) == -1 )
344 tst_resm(TWARN, "%s: rmobj(%s) failed: %s",
345 FN_NAME, TESTDIR, errmsg);
347 return;
348 } /* tst_rmdir() */
352 * tmpdir_cleanup() - This function is used when tst_tmpdir()
353 * encounters an error, and must cleanup and exit.
354 * It prints a warning message via tst_resm(), and
355 * then calls tst_exit().
357 #undef FN_NAME
358 #define FN_NAME "tst_tmpdir()"
360 static void
361 tmpdir_cleanup()
364 * Print a warning message and call tst_exit() to exit the test.
366 tst_resm(TWARN, "%s: No user cleanup function called before exiting",
367 FN_NAME);
368 tst_exit();
369 } /* tmpdir_cleanup() */
372 #ifdef UNIT_TEST
373 /****************************************************************************
374 * Unit test code: Takes input from stdin and can make the following
375 * calls: tst_tmpdir(), tst_rmdir().
376 ****************************************************************************/
377 int TST_TOTAL = 10;
378 char *TCID = "TESTTCID";
380 main()
382 int option;
383 char *chrptr;
385 printf("UNIT TEST of tst_tmpdir.c. Options to try:\n\
386 -1 : call tst_exit()\n\
387 0 : call tst_tmpdir()\n\
388 1 : call tst_rmdir()\n\n");
390 while ( 1 ) {
391 printf("Enter options (-1, 0, 1): ");
392 (void) scanf("%d%c", &option, &chrptr);
394 switch ( option ) {
395 case -1:
396 tst_exit();
397 break;
399 case 0:
400 tst_tmpdir();
401 break;
403 case 1:
404 tst_rmdir();
405 break;
406 } /* switch() */
407 } /* while() */
409 #endif /* UNIT_TEST */