1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2001
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program;  if not, write to the Free Software
17 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/*
21 * NAME
22 *	rename03
23 *
24 * DESCRIPTION
25 *	This test will verify that rename(2) functions correctly
26 *	when the "new" file or directory exists
27 *
28 * ALGORITHM
29 *	Setup:
30 *		Setup signal handling.
31 *		Create temporary directory.
32 *		Pause for SIGUSR1 if option specified.
33 *
34 *	Test:
35 *		Loop if the proper options are given.
36 *              1.  both old and new file exist
37 *                  create the "old" file and the "new" file
38 *                  rename the "old" to the "new" file
39 *                  verify the "new" file points to the "old" file
40 *                  verify the "old" file does not exists
41 *              2.  both old file and new directory exist
42 *                  create the "old" and the "new" directory
43 *                  rename the "old" to the "new" directory
44 *                  verify the "new" points to the "old" directory
45 *                  verify the "old" does not exists
46 *	Cleanup:
47 *		Print errno log and/or timing stats if options given
48 *		Delete the temporary directory created.
49 *
50 * USAGE
51 *	rename03 [-c n] [-f] [-i n] [-I x] [-p x] [-t]
52 *	where,  -c n : Run n copies concurrently.
53 *		-f   : Turn off functionality Testing.
54 *		-i n : Execute test n times.
55 *		-I x : Execute test for x seconds.
56 *		-P x : Pause for x seconds between iterations.
57 *		-t   : Turn on syscall timing.
58 *
59 * HISTORY
60 *	07/2001 Ported by Wayne Boyer
61 *
62 * RESTRICTIONS
63 *	None.
64 */
65#include <sys/types.h>
66#include <sys/fcntl.h>
67#include <sys/stat.h>
68#include <unistd.h>
69#include <errno.h>
70
71#include "test.h"
72
73void setup();
74void setup2();
75void cleanup();
76
77char *TCID = "rename03";
78int TST_TOTAL = 2;
79
80char fname[255], mname[255];
81char fdir[255], mdir[255];
82struct stat buf1, buf2;
83dev_t f_olddev, d_olddev;
84ino_t f_oldino, d_oldino;
85
86struct test_case_t {
87	char *name1;
88	char *name2;
89	char *desc;
90	dev_t *olddev;
91	ino_t *oldino;
92} TC[] = {
93	{
94	fname, mname, "file", &f_olddev, &f_oldino}, {
95	fdir, mdir, "directory", &d_olddev, &d_oldino}
96};
97
98int main(int ac, char **av)
99{
100	int lc;
101	int i;
102
103	/*
104	 * parse standard options
105	 */
106	tst_parse_opts(ac, av, NULL, NULL);
107	/*
108	 * perform global setup for test
109	 */
110	setup();
111
112	/*
113	 * check looping state if -i option given
114	 */
115	for (lc = 0; TEST_LOOPING(lc); lc++) {
116
117		tst_count = 0;
118
119		/* set up the files and directories for the tests */
120		setup2();
121
122		/* loop through the test cases */
123		for (i = 0; i < TST_TOTAL; i++) {
124
125			TEST(rename(TC[i].name1, TC[i].name2));
126
127			if (TEST_RETURN == -1) {
128				tst_resm(TFAIL, "call failed unexpectedly");
129				continue;
130			}
131
132			if (stat(TC[i].name2, &buf2) == -1) {
133				tst_brkm(TBROK, cleanup, "stat of %s "
134					 "failed", TC[i].desc);
135
136			}
137
138			/*
139			 * verify the new file or directory is the
140			 * same as the old one
141			 */
142			if (buf2.st_dev != *TC[i].olddev ||
143			    buf2.st_ino != *TC[i].oldino) {
144				tst_resm(TFAIL, "rename() failed: the "
145					 "new %s points to a different "
146					 "inode/location", TC[i].desc);
147				continue;
148			}
149			/*
150			 * verify that the old file or directory
151			 * does not exist
152			 */
153			if (stat(fname, &buf2) != -1) {
154				tst_resm(TFAIL, "the old %s still "
155					 "exists", TC[i].desc);
156				continue;
157			}
158
159			tst_resm(TPASS, "functionality is correct "
160				 "for renaming a %s", TC[i].desc);
161		}
162
163		/* reset things in case we are looping */
164
165		/* unlink the new file */
166		if (unlink(mname) == -1) {
167			tst_brkm(TBROK, cleanup, "unlink() failed");
168		}
169
170		/* remove the new directory */
171		if (rmdir(mdir) == -1) {
172			tst_brkm(TBROK, cleanup, "Couldn't remove directory %s",
173				 mdir);
174		}
175	}
176
177	cleanup();
178	tst_exit();
179
180}
181
182/*
183 * setup() - performs all ONE TIME setup for this test.
184 */
185void setup(void)
186{
187
188	tst_sig(NOFORK, DEF_HANDLER, cleanup);
189
190	TEST_PAUSE;
191
192	/* Create a temporary directory and make it current. */
193	tst_tmpdir();
194
195	sprintf(fname, "./tfile_%d", getpid());
196	sprintf(mname, "./rnfile_%d", getpid());
197	sprintf(fdir, "./tdir_%d", getpid());
198	sprintf(mdir, "./rndir_%d", getpid());
199}
200
201/*
202 * setup2() - set up the files and directories for the tests
203 */
204void setup2(void)
205{
206	SAFE_TOUCH(cleanup, fname, 0700, NULL);
207
208	if (stat(fname, &buf1) == -1) {
209		tst_brkm(TBROK, cleanup, "failed to stat file %s"
210			 "in rename()", fname);
211
212	}
213
214	/* save original file's dev and ino */
215	f_olddev = buf1.st_dev;
216	f_oldino = buf1.st_ino;
217
218	SAFE_TOUCH(cleanup, mname, 0700, NULL);
219
220	/* create "old" directory */
221	if (mkdir(fdir, 00770) == -1) {
222		tst_brkm(TBROK, cleanup, "Could not create directory %s", fdir);
223	}
224	if (stat(fdir, &buf1) == -1) {
225		tst_brkm(TBROK, cleanup, "failed to stat directory %s"
226			 "in rename()", fdir);
227
228	}
229
230	d_olddev = buf1.st_dev;
231	d_oldino = buf1.st_ino;
232
233	/* create another directory */
234	if (mkdir(mdir, 00770) == -1) {
235		tst_brkm(TBROK, cleanup, "Could not create directory %s", mdir);
236	}
237}
238
239/*
240 * cleanup() - performs all ONE TIME cleanup for this test at
241 *             completion or premature exit.
242 */
243void cleanup(void)
244{
245
246	/*
247	 * Remove the temporary directory.
248	 */
249	tst_rmdir();
250}
251