blob: 9c9809efd5522ca9ea8470f108aaac24458ffb97 [file] [log] [blame]
alaffincc2e5552000-07-27 17:13:18 +00001/*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
vapier45a8ba02009-07-20 10:59:32 +00003 *
alaffincc2e5552000-07-27 17:13:18 +00004 * 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.
vapier45a8ba02009-07-20 10:59:32 +00007 *
alaffincc2e5552000-07-27 17:13:18 +00008 * 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.
vapier45a8ba02009-07-20 10:59:32 +000011 *
alaffincc2e5552000-07-27 17:13:18 +000012 * 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.
vapier45a8ba02009-07-20 10:59:32 +000018 *
alaffincc2e5552000-07-27 17:13:18 +000019 * 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.
vapier45a8ba02009-07-20 10:59:32 +000022 *
alaffincc2e5552000-07-27 17:13:18 +000023 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
vapier45a8ba02009-07-20 10:59:32 +000025 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
alaffincc2e5552000-07-27 17:13:18 +000030 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 */
32
vapier45a8ba02009-07-20 10:59:32 +000033/* $Id: tst_tmpdir.c,v 1.14 2009/07/20 10:59:32 vapier Exp $ */
alaffincc2e5552000-07-27 17:13:18 +000034
35/**********************************************************
36 *
37 * OS Testing - Silicon Graphics, Inc.
38 *
39 * FUNCTION NAME : tst_tmpdir, tst_rmdir
40 *
41 * FUNCTION TITLE : Create/remove a testing temp dir
42 *
43 * SYNOPSIS:
44 * void tst_tmpdir();
45 * void tst_rmdir();
46 *
47 * AUTHOR : Dave Fenner
48 *
49 * INITIAL RELEASE : UNICOS 8.0
50 *
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().
56 *
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().
61 *
62 * RETURN VALUE
63 * Neither tst_tmpdir() or tst_rmdir() has a return value.
64 *
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"
75
76/*
77 * Define some useful macros.
78 */
79#define PREFIX_SIZE 4
80#define STRING_SIZE 256
81#define DIR_MODE 0777 /* mode of tmp dir that will be created */
82
83#ifndef PATH_MAX
84#ifdef MAXPATHLEN
85#define PATH_MAX MAXPATHLEN
86#else
87#define PATH_MAX 1024
88#endif
89#endif
90
91/*
92 * Define function prototypes.
93 */
94static void tmpdir_cleanup();
95
96/*
97 * Define global variables.
98 */
99extern char *TCID; /* defined/initialized in main() */
100extern int TST_TOTAL; /* defined/initialized in main() */
101extern char *TESTDIR; /* the directory created; defined in */
102 /* tst_res.c */
103
104/*
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.
110 *
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).
115 */
116#undef FN_NAME
117#define FN_NAME "tst_tmpdir()"
118
subrata_modak88c166c2009-06-09 16:01:20 +0000119void tst_tmpdir(void)
alaffincc2e5552000-07-27 17:13:18 +0000120{
plarsb00626b2002-09-04 14:01:28 +0000121 char template[PATH_MAX]; /* template for mkstemp, mkdtemp */
nstrazffe35e22001-03-13 16:33:54 +0000122 int no_cleanup = 0; /* !0 means TDIRECTORY env var was set */
123 char *env_tmpdir; /* temporary storage for TMPDIR env var */
robbiew5d94fdf2003-04-01 20:20:54 +0000124/* 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
plarsca41c6b2002-09-04 18:45:17 +0000130 int tfd;
robbiew5d94fdf2003-04-01 20:20:54 +0000131# endif
vapier45a8ba02009-07-20 10:59:32 +0000132#else
robbiew5d94fdf2003-04-01 20:20:54 +0000133# define HAVE_MKDTEMP 0
134 int tfd;
135#endif
nstrazffe35e22001-03-13 16:33:54 +0000136 /*
137 * If the TDIRECTORY env variable is not set, a temp dir will be
138 * created.
139 */
140 if ((TESTDIR = getenv(TDIRECTORY))) {
141 /*
142 * The TDIRECTORY env. variable is set, so no temp dir is created.
143 * Also, no clean up will be done via tst_rmdir().
144 */
vapier45a8ba02009-07-20 10:59:32 +0000145 mkdir(TESTDIR,DIR_MODE); /*Try to create the directory if it does not exist already,
subrata_modak0885aa02007-03-23 12:33:39 +0000146 user might forget to create one before exporting TDIRECTORY,
147 Will fail if it already exists, no issues in that*/
nstrazffe35e22001-03-13 16:33:54 +0000148 no_cleanup++;
alaffincc2e5552000-07-27 17:13:18 +0000149#if UNIT_TEST
nstrazffe35e22001-03-13 16:33:54 +0000150 printf("TDIRECTORY env var is set\n");
alaffincc2e5552000-07-27 17:13:18 +0000151#endif
nstrazffe35e22001-03-13 16:33:54 +0000152 } else {
153 /*
vapier45a8ba02009-07-20 10:59:32 +0000154 * Create a template for the temporary directory. Use the
nstrazffe35e22001-03-13 16:33:54 +0000155 * environment variable TMPDIR if it is available, otherwise
156 * use our default TEMPDIR.
157 */
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);
162 }
vapier45a8ba02009-07-20 10:59:32 +0000163
nstraz7891a262001-03-13 21:54:05 +0000164
165#if HAVE_MKDTEMP
nstrazffe35e22001-03-13 16:33:54 +0000166 /*
167 * Make the temporary directory in one shot using mkdtemp()
168 */
nstraz643643a2001-03-15 21:21:46 +0000169 if (mkdtemp(template) == NULL)
vapier45a8ba02009-07-20 10:59:32 +0000170 tst_brkm(TBROK, tmpdir_cleanup,
171 "%s: mkdtemp(%s) failed; errno = %d: %s",
plars8f4232f2002-09-04 18:40:11 +0000172 FN_NAME, template, errno, strerror(errno));
subrata_modak38fea912007-04-27 10:12:01 +0000173 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));
177 }
vapier45a8ba02009-07-20 10:59:32 +0000178#else
nstraz7891a262001-03-13 21:54:05 +0000179 /*
180 * Make the template name, then the directory
181 */
mridgee6508f82005-01-04 21:00:17 +0000182 if ((tfd = mkstemp(template)) == -1)
vapier45a8ba02009-07-20 10:59:32 +0000183 tst_brkm(TBROK, tmpdir_cleanup,
184 "%s: mkstemp(%s) failed; errno = %d: %s",
plars8f4232f2002-09-04 18:40:11 +0000185 FN_NAME, template, errno, strerror(errno));
subrata_modak38fea912007-04-27 10:12:01 +0000186 if ( close(tfd) == -1 ) {
187 tst_brkm(TBROK, tmpdir_cleanup,
188 "%s: close() failed; errno = %d: %s",
189 FN_NAME, errno, strerror(errno));
190 }
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));
195 }
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));
200 }
nstraz7891a262001-03-13 21:54:05 +0000201 if (mkdir(TESTDIR, DIR_MODE)) {
vapier45a8ba02009-07-20 10:59:32 +0000202 /* If we start failing with EEXIST, wrap this section in
nstraz7891a262001-03-13 21:54:05 +0000203 * a loop so we can try again.
204 */
vapier45a8ba02009-07-20 10:59:32 +0000205 tst_brkm(TBROK, tmpdir_cleanup,
206 "%s: mkdir(%s, %#o) failed; errno = %d: %s",
207 FN_NAME, TESTDIR, DIR_MODE, errno,
plars8f4232f2002-09-04 18:40:11 +0000208 strerror(errno));
nstraz7891a262001-03-13 21:54:05 +0000209 }
210#endif
nstrazffe35e22001-03-13 16:33:54 +0000211
212 /*
213 * Change the group on this temporary directory to be that of the
robbiewca11e712004-08-25 05:07:02 +0000214 * gid of the person running the tests and permissions to 777.
nstrazffe35e22001-03-13 16:33:54 +0000215 */
216 if ( chown(TESTDIR, -1, getgid()) == -1 )
vapier45a8ba02009-07-20 10:59:32 +0000217 tst_brkm(TBROK, tmpdir_cleanup,
218 "chown(%s, -1, %d) failed; errno = %d: %s",
plars8f4232f2002-09-04 18:40:11 +0000219 TESTDIR, getgid(), errno, strerror(errno));
robbiewca11e712004-08-25 05:07:02 +0000220 if ( chmod(TESTDIR,S_IRWXU | S_IRWXG | S_IRWXO) == -1 )
221 tst_brkm(TBROK, tmpdir_cleanup,
222 "chmod(%s,777) failed; errno %d: %s",
vapier45a8ba02009-07-20 10:59:32 +0000223 TESTDIR, errno, strerror(errno));
nstrazffe35e22001-03-13 16:33:54 +0000224 }
alaffincc2e5552000-07-27 17:13:18 +0000225
226#if UNIT_TEST
nstrazffe35e22001-03-13 16:33:54 +0000227 printf("TESTDIR = %s\n", TESTDIR);
alaffincc2e5552000-07-27 17:13:18 +0000228#endif
229
nstrazffe35e22001-03-13 16:33:54 +0000230 /*
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
vapier45a8ba02009-07-20 10:59:32 +0000234 * fails, also issue a TWARN message.
nstrazffe35e22001-03-13 16:33:54 +0000235 */
236 if ( chdir(TESTDIR) == -1 ) {
237 tst_brkm(TBROK, NULL, "%s: chdir(%s) failed; errno = %d: %s",
plars8f4232f2002-09-04 18:40:11 +0000238 FN_NAME, TESTDIR, errno, strerror(errno) );
alaffincc2e5552000-07-27 17:13:18 +0000239
nstrazffe35e22001-03-13 16:33:54 +0000240 /* Try to remove the directory */
241 if ( !no_cleanup && rmdir(TESTDIR) == -1 )
242 tst_resm(TWARN, "%s: rmdir(%s) failed; errno = %d: %s",
plars8f4232f2002-09-04 18:40:11 +0000243 FN_NAME, TESTDIR, errno, strerror(errno) );
alaffincc2e5552000-07-27 17:13:18 +0000244
nstrazffe35e22001-03-13 16:33:54 +0000245 tmpdir_cleanup();
246 }
vapier45a8ba02009-07-20 10:59:32 +0000247
alaffincc2e5552000-07-27 17:13:18 +0000248#if UNIT_TEST
nstrazffe35e22001-03-13 16:33:54 +0000249 printf("CWD is %s\n", getcwd((char *)NULL, PATH_MAX));
alaffincc2e5552000-07-27 17:13:18 +0000250#endif
251
nstrazffe35e22001-03-13 16:33:54 +0000252 /*
253 * If we made through all this stuff, return.
254 */
255 return;
alaffincc2e5552000-07-27 17:13:18 +0000256} /* tst_tmpdir() */
257
258
259/*
260 *
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.
vapier45a8ba02009-07-20 10:59:32 +0000266 */
alaffincc2e5552000-07-27 17:13:18 +0000267#undef FN_NAME
268#define FN_NAME "tst_rmdir()"
269
subrata_modak88c166c2009-06-09 16:01:20 +0000270void tst_rmdir(void)
alaffincc2e5552000-07-27 17:13:18 +0000271{
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 */
277
278 /*
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.
282 */
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;
288 }
vapier45a8ba02009-07-20 10:59:32 +0000289
alaffincc2e5552000-07-27 17:13:18 +0000290 /*
291 * Check that TESTDIR is not NULL.
292 */
293 if ( TESTDIR == NULL ) {
294 tst_resm(TWARN, "%s: TESTDIR was NULL; no removal attempted",
295 FN_NAME);
296 return;
297 }
298
299 /*
300 * Check that the value of TESTDIR is not "*" or "/". These could
301 * have disastrous effects in a test run by root.
302 */
303 if ( strcmp(TESTDIR, "/") == 0 ) {
304 tst_resm(TWARN,
305 "%s: Recursive remove of root directory not attempted",
306 FN_NAME);
307 return;
308 }
309
310 if ( strchr(TESTDIR, '*') != NULL ) {
311 tst_resm(TWARN, "%s: Recursive remove of '*' not attempted",
312 FN_NAME);
313 return;
314 }
315
316 /*
317 * Get the directory name of TESTDIR. If TESTDIR is a relative path,
318 * get full path.
319 */
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);
327 }
328 if ( (basename = strrchr(parent_dir, '/')) != NULL ) {
329 *basename='\0'; /* terminate at end of parent_dir */
330 }
331
332 /*
333 * Change directory to parent_dir (The dir above TESTDIR).
334 */
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));
vapier45a8ba02009-07-20 10:59:32 +0000339
alaffincc2e5552000-07-27 17:13:18 +0000340 /*
341 * Attempt to remove the "TESTDIR" directory, using rmobj().
342 */
343 if ( rmobj(TESTDIR, &errmsg) == -1 )
344 tst_resm(TWARN, "%s: rmobj(%s) failed: %s",
345 FN_NAME, TESTDIR, errmsg);
346
347 return;
348} /* tst_rmdir() */
349
350
351/*
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().
356 */
357#undef FN_NAME
358#define FN_NAME "tst_tmpdir()"
359
360static void
361tmpdir_cleanup()
362{
363 /*
364 * Print a warning message and call tst_exit() to exit the test.
365 */
366 tst_resm(TWARN, "%s: No user cleanup function called before exiting",
367 FN_NAME);
368 tst_exit();
369} /* tmpdir_cleanup() */
370
371
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 ****************************************************************************/
377int TST_TOTAL = 10;
378char *TCID = "TESTTCID";
379
380main()
381{
382 int option;
383 char *chrptr;
384
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");
389
390 while ( 1 ) {
391 printf("Enter options (-1, 0, 1): ");
392 (void) scanf("%d%c", &option, &chrptr);
393
394 switch ( option ) {
395 case -1:
396 tst_exit();
397 break;
398
399 case 0:
400 tst_tmpdir();
401 break;
402
403 case 1:
404 tst_rmdir();
405 break;
406 } /* switch() */
407 } /* while() */
408}
409#endif /* UNIT_TEST */