blob: 09b7b6e22e4fe9309a57273e4240874a979131c2 [file] [log] [blame]
Marios Makris60b1baa2012-08-09 20:36:46 +03001/**********************************************************
alaffincc2e5552000-07-27 17:13:18 +00002 * 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
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/
Marios Makris60b1baa2012-08-09 20:36:46 +030031 *********************************************************/
alaffincc2e5552000-07-27 17:13:18 +000032
33/**********************************************************
34 *
Garrett Cooper53740502010-12-16 00:04:01 -080035 * OS Testing - Silicon Graphics, Inc.
alaffincc2e5552000-07-27 17:13:18 +000036 *
Garrett Cooper53740502010-12-16 00:04:01 -080037 * FUNCTION NAME : tst_tmpdir, tst_rmdir
alaffincc2e5552000-07-27 17:13:18 +000038 *
Garrett Cooper53740502010-12-16 00:04:01 -080039 * FUNCTION TITLE : Create/remove a testing temp dir
alaffincc2e5552000-07-27 17:13:18 +000040 *
Garrett Cooper53740502010-12-16 00:04:01 -080041 * SYNOPSIS:
42 * void tst_tmpdir();
43 * void tst_rmdir();
alaffincc2e5552000-07-27 17:13:18 +000044 *
Garrett Cooper53740502010-12-16 00:04:01 -080045 * AUTHOR : Dave Fenner
alaffincc2e5552000-07-27 17:13:18 +000046 *
Garrett Cooper53740502010-12-16 00:04:01 -080047 * INITIAL RELEASE : UNICOS 8.0
alaffincc2e5552000-07-27 17:13:18 +000048 *
Garrett Cooper53740502010-12-16 00:04:01 -080049 * 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().
alaffincc2e5552000-07-27 17:13:18 +000054 *
Garrett Cooper53740502010-12-16 00:04:01 -080055 * RETURN VALUE
56 * Neither tst_tmpdir() or tst_rmdir() has a return value.
alaffincc2e5552000-07-27 17:13:18 +000057 *
Marios Makris60b1baa2012-08-09 20:36:46 +030058 *********************************************************/
Xiao Yang8f8ff102017-02-14 11:09:29 +080059#define _GNU_SOURCE
Stanislav Kholmanskikh57027652015-05-26 13:21:10 +030060#include <sys/mman.h>
Garrett Cooper53740502010-12-16 00:04:01 -080061#include <sys/types.h>
62#include <sys/stat.h>
Garrett Cooperb1c7c6b2010-12-20 07:09:47 -080063#include <assert.h>
alaffincc2e5552000-07-27 17:13:18 +000064#include <errno.h>
Garrett Cooper53740502010-12-16 00:04:01 -080065#include <libgen.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69#include <unistd.h>
Cyril Hrubisfc0c72a2017-02-13 15:35:09 +010070#include <dirent.h>
71#include <fcntl.h>
Marios Makris60b1baa2012-08-09 20:36:46 +030072
alaffincc2e5552000-07-27 17:13:18 +000073#include "test.h"
Cyril Hrubisb0832a72017-10-03 13:41:18 +020074#include "safe_macros.h"
Cyril Hrubised69cd52013-06-24 17:51:00 +020075#include "ltp_priv.h"
Stanislav Kholmanskikh57027652015-05-26 13:21:10 +030076#include "lapi/futex.h"
alaffincc2e5552000-07-27 17:13:18 +000077
78/*
79 * Define some useful macros.
80 */
Garrett Cooper1f3c2362010-12-16 22:05:45 -080081#define DIR_MODE (S_IRWXU|S_IRWXG|S_IRWXO)
alaffincc2e5552000-07-27 17:13:18 +000082
83#ifndef PATH_MAX
84#ifdef MAXPATHLEN
Garrett Cooper1f3c2362010-12-16 22:05:45 -080085#define PATH_MAX MAXPATHLEN
alaffincc2e5552000-07-27 17:13:18 +000086#else
Garrett Cooper1f3c2362010-12-16 22:05:45 -080087#define PATH_MAX 1024
alaffincc2e5552000-07-27 17:13:18 +000088#endif
89#endif
90
91/*
alaffincc2e5552000-07-27 17:13:18 +000092 * Define global variables.
93 */
Garrett Cooperdb976802010-12-16 15:56:25 -080094extern char *TCID; /* defined/initialized in main() */
95static char *TESTDIR = NULL; /* the directory created */
96
Cyril Hrubis69c2ab02012-12-12 17:22:29 +010097static char test_start_work_dir[PATH_MAX];
98
Stanislav Kholmanskikh57027652015-05-26 13:21:10 +030099/* lib/tst_checkpoint.c */
100extern futex_t *tst_futexes;
Cyril Hrubis69c2ab02012-12-12 17:22:29 +0100101
Cyril Hrubisab8388c2012-11-28 15:42:17 +0100102int tst_tmpdir_created(void)
103{
104 return TESTDIR != NULL;
105}
106
Cyril Hrubis9c31ad22014-05-14 17:15:39 +0200107char *tst_get_tmpdir(void)
Garrett Cooperdb976802010-12-16 15:56:25 -0800108{
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100109 if (TESTDIR == NULL) {
Garrett Cooperb1c7c6b2010-12-20 07:09:47 -0800110 tst_brkm(TBROK, NULL, "you must call tst_tmpdir() first");
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100111 return NULL;
112 }
113
Garrett Cooperdb976802010-12-16 15:56:25 -0800114 return strdup(TESTDIR);
115}
alaffincc2e5552000-07-27 17:13:18 +0000116
Cyril Hrubis69c2ab02012-12-12 17:22:29 +0100117const char *tst_get_startwd(void)
118{
119 return test_start_work_dir;
120}
121
Cyril Hrubisfc0c72a2017-02-13 15:35:09 +0100122static int rmobj(char *obj, char **errmsg)
123{
124 int ret_val = 0;
125 DIR *dir;
126 struct dirent *dir_ent;
127 char dirobj[PATH_MAX];
128 struct stat statbuf;
129 static char err_msg[1024];
130 int fd;
131
132 fd = open(obj, O_DIRECTORY | O_NOFOLLOW);
133 if (fd != -1) {
134 close(fd);
135
136 /* Do NOT perform the request if the directory is "/" */
137 if (!strcmp(obj, "/")) {
138 if (errmsg != NULL) {
139 sprintf(err_msg, "Cannot remove /");
140 *errmsg = err_msg;
141 }
142 return -1;
143 }
144
145 /* Open the directory to get access to what is in it */
146 if ((dir = opendir(obj)) == NULL) {
147 if (rmdir(obj) != 0) {
148 if (errmsg != NULL) {
149 sprintf(err_msg,
150 "rmdir(%s) failed; errno=%d: %s",
151 obj, errno, tst_strerrno(errno));
152 *errmsg = err_msg;
153 }
154 return -1;
155 } else {
156 return 0;
157 }
158 }
159
160 /* Loop through the entries in the directory, removing each one */
161 for (dir_ent = (struct dirent *)readdir(dir);
162 dir_ent != NULL; dir_ent = (struct dirent *)readdir(dir)) {
163
164 /* Don't remove "." or ".." */
165 if (!strcmp(dir_ent->d_name, ".")
166 || !strcmp(dir_ent->d_name, ".."))
167 continue;
168
169 /* Recursively call this routine to remove the current entry */
170 sprintf(dirobj, "%s/%s", obj, dir_ent->d_name);
171 if (rmobj(dirobj, errmsg) != 0)
172 ret_val = -1;
173 }
174
175 closedir(dir);
176
177 /* If there were problems removing an entry, don't attempt to
178 remove the directory itself */
179 if (ret_val == -1)
180 return -1;
181
182 /* Get the link count, now that all the entries have been removed */
183 if (lstat(obj, &statbuf) < 0) {
184 if (errmsg != NULL) {
185 sprintf(err_msg,
186 "lstat(%s) failed; errno=%d: %s", obj,
187 errno, tst_strerrno(errno));
188 *errmsg = err_msg;
189 }
190 return -1;
191 }
192
193 /* Remove the directory itself */
194 if (statbuf.st_nlink >= 3) {
195 /* The directory is linked; unlink() must be used */
196 if (unlink(obj) < 0) {
197 if (errmsg != NULL) {
198 sprintf(err_msg,
199 "unlink(%s) failed; errno=%d: %s",
200 obj, errno, tst_strerrno(errno));
201 *errmsg = err_msg;
202 }
203 return -1;
204 }
205 } else {
206 /* The directory is not linked; remove() can be used */
207 if (remove(obj) < 0) {
208 if (errmsg != NULL) {
209 sprintf(err_msg,
210 "remove(%s) failed; errno=%d: %s",
211 obj, errno, tst_strerrno(errno));
212 *errmsg = err_msg;
213 }
214 return -1;
215 }
216 }
217 } else {
218 if (unlink(obj) < 0) {
219 if (errmsg != NULL) {
220 sprintf(err_msg,
221 "unlink(%s) failed; errno=%d: %s", obj,
222 errno, tst_strerrno(errno));
223 *errmsg = err_msg;
224 }
225 return -1;
226 }
227 }
228
229 return 0;
230}
231
subrata_modak88c166c2009-06-09 16:01:20 +0000232void tst_tmpdir(void)
alaffincc2e5552000-07-27 17:13:18 +0000233{
Garrett Cooperdb976802010-12-16 15:56:25 -0800234 char template[PATH_MAX];
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800235 char *env_tmpdir;
236 char *errmsg, *c;
Garrett Cooper53740502010-12-16 00:04:01 -0800237
Garrett Cooperdb976802010-12-16 15:56:25 -0800238 /*
Marios Makrisc128c452012-08-09 20:36:50 +0300239 * Create a template for the temporary directory. Use the
240 * environment variable TMPDIR if it is available, otherwise
241 * use our default TEMPDIR.
nstrazffe35e22001-03-13 16:33:54 +0000242 */
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800243 env_tmpdir = getenv("TMPDIR");
244 if (env_tmpdir) {
245 c = strchr(env_tmpdir, '/');
246 /*
247 * Now we force environment variable TMPDIR to be an absolute
248 * pathname, which dose not make much sense, but it will
249 * greatly simplify code in tst_rmdir().
250 */
251 if (c != env_tmpdir) {
Alexey Kodanev15634ea2016-06-20 17:53:03 +0300252 tst_brkm(TBROK, NULL, "You must specify an absolute "
253 "pathname for environment variable TMPDIR");
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100254 return;
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800255 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800256 snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", env_tmpdir, TCID);
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800257 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800258 snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID);
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800259 }
vapier45a8ba02009-07-20 10:59:32 +0000260
Marios Makrisc128c452012-08-09 20:36:50 +0300261 /* Make the temporary directory in one shot using mkdtemp. */
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100262 if (mkdtemp(template) == NULL) {
Alexey Kodanev15634ea2016-06-20 17:53:03 +0300263 tst_brkm(TBROK | TERRNO, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800264 "%s: mkdtemp(%s) failed", __func__, template);
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100265 return;
266 }
267
268 if ((TESTDIR = strdup(template)) == NULL) {
Alexey Kodanev15634ea2016-06-20 17:53:03 +0300269 tst_brkm(TBROK | TERRNO, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800270 "%s: strdup(%s) failed", __func__, template);
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100271 return;
272 }
nstrazffe35e22001-03-13 16:33:54 +0000273
Cyril Hrubis3b117652017-10-03 13:42:10 +0200274 SAFE_CHOWN(NULL, TESTDIR, -1, getgid());
Cyril Hrubisd101cab2017-02-14 11:48:46 +0100275
Cyril Hrubisb0832a72017-10-03 13:41:18 +0200276 SAFE_CHMOD(NULL, TESTDIR, DIR_MODE);
alaffincc2e5552000-07-27 17:13:18 +0000277
Cyril Hrubis69c2ab02012-12-12 17:22:29 +0100278 if (getcwd(test_start_work_dir, sizeof(test_start_work_dir)) == NULL) {
279 tst_resm(TINFO, "Failed to record test working dir");
280 test_start_work_dir[0] = '\0';
281 }
282
Marios Makris60b1baa2012-08-09 20:36:46 +0300283 /*
284 * Change to the temporary directory. If the chdir() fails, issue
Garrett Cooper53740502010-12-16 00:04:01 -0800285 * TBROK messages for all test cases, attempt to remove the
nstrazffe35e22001-03-13 16:33:54 +0000286 * directory (if it was created), and exit. If the removal also
vapier45a8ba02009-07-20 10:59:32 +0000287 * fails, also issue a TWARN message.
nstrazffe35e22001-03-13 16:33:54 +0000288 */
Garrett Cooper903910d2010-11-23 09:27:44 -0800289 if (chdir(TESTDIR) == -1) {
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800290 tst_resm(TERRNO, "%s: chdir(%s) failed", __func__, TESTDIR);
alaffincc2e5552000-07-27 17:13:18 +0000291
nstrazffe35e22001-03-13 16:33:54 +0000292 /* Try to remove the directory */
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800293 if (rmobj(TESTDIR, &errmsg) == -1) {
Marios Makrisc128c452012-08-09 20:36:50 +0300294 tst_resm(TWARN, "%s: rmobj(%s) failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800295 __func__, TESTDIR, errmsg);
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800296 }
alaffincc2e5552000-07-27 17:13:18 +0000297
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800298 tst_exit();
nstrazffe35e22001-03-13 16:33:54 +0000299 }
Marios Makris60b1baa2012-08-09 20:36:46 +0300300}
alaffincc2e5552000-07-27 17:13:18 +0000301
subrata_modak88c166c2009-06-09 16:01:20 +0000302void tst_rmdir(void)
alaffincc2e5552000-07-27 17:13:18 +0000303{
Garrett Cooper53740502010-12-16 00:04:01 -0800304 char *errmsg;
vapier45a8ba02009-07-20 10:59:32 +0000305
Garrett Cooper53740502010-12-16 00:04:01 -0800306 /*
307 * Check that TESTDIR is not NULL.
308 */
309 if (TESTDIR == NULL) {
Garrett Cooperdb976802010-12-16 15:56:25 -0800310 tst_resm(TWARN,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800311 "%s: TESTDIR was NULL; no removal attempted",
312 __func__);
Garrett Cooper53740502010-12-16 00:04:01 -0800313 return;
314 }
alaffincc2e5552000-07-27 17:13:18 +0000315
Garrett Cooper53740502010-12-16 00:04:01 -0800316 /*
Stanislav Kholmanskikh57027652015-05-26 13:21:10 +0300317 * Unmap the backend file.
318 * This is needed to overcome the NFS "silly rename" feature.
319 */
Stanislav Kholmanskikh401d0cb2015-05-28 11:58:10 +0300320 if (tst_futexes) {
321 msync((void *)tst_futexes, getpagesize(), MS_SYNC);
Stanislav Kholmanskikh57027652015-05-26 13:21:10 +0300322 munmap((void *)tst_futexes, getpagesize());
Stanislav Kholmanskikh401d0cb2015-05-28 11:58:10 +0300323 }
Stanislav Kholmanskikh57027652015-05-26 13:21:10 +0300324
325 /*
Garrett Cooper53740502010-12-16 00:04:01 -0800326 * Attempt to remove the "TESTDIR" directory, using rmobj().
327 */
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800328 if (rmobj(TESTDIR, &errmsg) == -1) {
Garrett Cooper53740502010-12-16 00:04:01 -0800329 tst_resm(TWARN, "%s: rmobj(%s) failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800330 __func__, TESTDIR, errmsg);
Xiaoguang Wang33a4adf2014-07-30 12:09:40 +0800331 }
Marios Makris60b1baa2012-08-09 20:36:46 +0300332}