Home | History | Annotate | Download | only in lib
      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