utime01.c revision d59a659cd639ca2780b00049d102acd2a783d585
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 * Test Name: utime01
22 *
23 * Test Description:
24 *  Verify that the system call utime() successfully sets the modification
25 *  and access times of a file to the current time, if the times argument
26 *  is null, and the user ID of the process is "root".
27 *
28 * Expected Result:
29 *  utime succeeds returning zero and sets the access and modification
30 *  times of the file to the current time.
31 *
32 * Algorithm:
33 *  Setup:
34 *   Setup signal handling.
35 *   Create temporary directory.
36 *   Pause for SIGUSR1 if option specified.
37 *
38 *  Test:
39 *   Loop if the proper options are given.
40 *   Execute system call
41 *   Check return code, if system call failed (return=-1)
42 *	Log the errno and Issue a FAIL message.
43 *   Otherwise,
44 *	Verify the Functionality of system call
45 *      if successful,
46 *		Issue Functionality-Pass message.
47 *      Otherwise,
48 *		Issue Functionality-Fail message.
49 *  Cleanup:
50 *   Print errno log and/or timing stats if options given
51 *   Delete the temporary directory created.
52 *
53 * Usage:  <for command-line>
54 *  utime01 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
55 *		where,  -c n : Run n copies concurrently.
56 *			-e   : Turn on errno logging.
57 *			-f   : Turn off functionality Testing.
58 *			-i n : Execute test n times.
59 *			-I x : Execute test for x seconds.
60 *			-P x : Pause for x seconds between iterations.
61 *			-t   : Turn on syscall timing.
62 *
63 * History
64 *	07/2001 John George
65 *		-Ported
66 *
67 * Restrictions:
68 *  This test should be run by 'super-user' (root) only.
69 *
70 */
71
72#include <stdio.h>
73#include <unistd.h>
74#include <sys/types.h>
75#include <errno.h>
76#include <fcntl.h>
77#include <utime.h>
78#include <string.h>
79#include <sys/stat.h>
80#include <signal.h>
81#include <time.h>
82
83#include "test.h"
84#include "usctest.h"
85
86#define TEMP_FILE	"tmp_file"
87#define FILE_MODE	S_IRUSR | S_IRGRP | S_IROTH
88
89char *TCID = "utime01";		/* Test program identifier.    */
90int TST_TOTAL = 1;		/* Total number of test cases. */
91time_t curr_time;		/* current time in seconds */
92time_t tloc;			/* argument var. for time() */
93int exp_enos[] = { 0 };
94
95void setup();			/* Main setup function of test */
96void cleanup();			/* cleanup function for the test */
97
98int main(int ac, char **av)
99{
100	struct stat stat_buf;	/* struct buffer to hold file info. */
101	int lc;
102	char *msg;
103	time_t modf_time, access_time;
104	time_t pres_time;	/* file modification/access/present time */
105
106	/* Parse standard options given to run the test. */
107	msg = parse_opts(ac, av, NULL, NULL);
108	if (msg != NULL) {
109		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
110
111	}
112
113	setup();
114
115	/*
116	 * check if the current filesystem is nfs
117	 */
118	if (tst_is_cwd_nfs()) {
119		tst_brkm(TCONF, cleanup,
120			 "Cannot do utime on a file located on an NFS filesystem");
121	}
122
123	if (tst_is_cwd_v9fs()) {
124		tst_brkm(TCONF, cleanup,
125			 "Cannot do utime on a file located on an 9P filesystem");
126	}
127
128	/* set the expected errnos... */
129	TEST_EXP_ENOS(exp_enos);
130
131	for (lc = 0; TEST_LOOPING(lc); lc++) {
132
133		tst_count = 0;
134
135		/*
136		 * Invoke utime(2) to set TEMP_FILE access and
137		 * modification times to the current time.
138		 */
139		TEST(utime(TEMP_FILE, NULL));
140
141		if (TEST_RETURN == -1) {
142			TEST_ERROR_LOG(TEST_ERRNO);
143			tst_resm(TFAIL, "utime(%s) Failed, errno=%d : %s",
144				 TEMP_FILE, TEST_ERRNO, strerror(TEST_ERRNO));
145		} else {
146			/*
147			 * Perform functional verification if test
148			 * executed without (-f) option.
149			 */
150			if (STD_FUNCTIONAL_TEST) {
151				/*
152				 * Sleep for a second so that mod time and
153				 * access times will be different from the
154				 * current time
155				 */
156				sleep(2);
157
158				/*
159				 * Get the current time now, after calling
160				 * utime(2)
161				 */
162				if ((pres_time = time(&tloc)) < 0) {
163					tst_brkm(TFAIL, cleanup, "time() "
164						 "failed to get present time "
165						 "after utime, error=%d",
166						 errno);
167				}
168
169				/*
170				 * Get the modification and access times of
171				 * temporary file using stat(2).
172				 */
173				if (stat(TEMP_FILE, &stat_buf) < 0) {
174					tst_brkm(TFAIL, cleanup, "stat(2) of "
175						 "%s failed, error:%d",
176						 TEMP_FILE, TEST_ERRNO);
177				}
178				modf_time = stat_buf.st_mtime;
179				access_time = stat_buf.st_atime;
180
181				/* Now do the actual verification */
182				if (modf_time <= curr_time ||
183				    modf_time >= pres_time ||
184				    access_time <= curr_time ||
185				    access_time >= pres_time) {
186					tst_resm(TFAIL, "%s access and "
187						 "modification times not set",
188						 TEMP_FILE);
189				} else {
190					tst_resm(TPASS, "Functionality of "
191						 "utime(%s, NULL) successful",
192						 TEMP_FILE);
193				}
194			} else {
195				tst_resm(TPASS, "%s call succeeded", TCID);
196			}
197		}
198		tst_count++;
199	}
200
201	cleanup();
202	tst_exit();
203
204}
205
206/*
207 * void
208 * setup() - performs all ONE TIME setup for this test.
209 *  Create a temporary directory and change directory to it.
210 *  Create a test file under temporary directory and close it
211 */
212void setup()
213{
214	int fildes;		/* file handle for temp file */
215
216	tst_sig(FORK, DEF_HANDLER, cleanup);
217
218	/* Check that the test process id is super/root  */
219	if (geteuid() != 0) {
220		tst_brkm(TBROK, NULL, "Must be super/root for this test!");
221		tst_exit();
222	}
223
224	TEST_PAUSE;
225
226	tst_tmpdir();
227
228	/* Creat a temporary file under above directory */
229	if ((fildes = creat(TEMP_FILE, FILE_MODE)) == -1) {
230		tst_brkm(TBROK, cleanup,
231			 "creat(%s, %#o) Failed, errno=%d :%s",
232			 TEMP_FILE, FILE_MODE, errno, strerror(errno));
233	}
234
235	/* Close the temporary file created */
236	if (close(fildes) < 0) {
237		tst_brkm(TBROK, cleanup,
238			 "close(%s) Failed, errno=%d : %s:",
239			 TEMP_FILE, errno, strerror(errno));
240	}
241
242	/* Get the current time */
243	if ((curr_time = time(&tloc)) < 0) {
244		tst_brkm(TBROK, cleanup,
245			 "time() failed to get current time, errno=%d", errno);
246	}
247
248	/*
249	 * Sleep for a second so that mod time and access times will be
250	 * different from the current time
251	 */
252	sleep(2);		/* sleep(1) on IA64 sometimes sleeps < 1 sec!! */
253
254}
255
256/*
257 * void
258 * cleanup() - performs all ONE TIME cleanup for this test at
259 *             completion or premature exit.
260 *  Remove the test directory and testfile created in the setup.
261 */
262void cleanup()
263{
264	/*
265	 * print timing stats if that option was specified.
266	 * print errno log if that option was specified.
267	 */
268	TEST_CLEANUP;
269
270	tst_rmdir();
271
272}
273