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: stime01
22  *
23  * Test Description:
24  *  Verify that the system call stime() successfully sets the system's idea
25  *  of date and time if invoked by "root" user.
26  *
27  * Expected Result:
28  *  stime() should succeed to set the system data/time to the specified time.
29  *
30  * Algorithm:
31  *  Setup:
32  *   Setup signal handling.
33  *   Pause for SIGUSR1 if option specified.
34  *
35  *  Test:
36  *   Loop if the proper options are given.
37  *   Execute system call
38  *   Check return code, if system call failed (return=-1)
39  *   	Log the errno and Issue a FAIL message.
40  *   Otherwise,
41  *   	Verify the Functionality of system call
42  *      if successful,
43  *      	Issue Functionality-Pass message.
44  *      Otherwise,
45  *		Issue Functionality-Fail message.
46  *  Cleanup:
47  *   Print errno log and/or timing stats if options given
48  *
49  * Usage:  <for command-line>
50  *  stime01 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
51  *	where,  -c n : Run n copies concurrently.
52  *		-e   : Turn on errno logging.
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 John George
61  *		-Ported
62  *
63  * Restrictions:
64  *  This test should be run by 'super-user' (root) only.
65  *
66  */
67 
68 #include <stdio.h>
69 #include <unistd.h>
70 #include <sys/types.h>
71 #include <errno.h>
72 #include <fcntl.h>
73 #include <time.h>
74 #include <string.h>
75 #include <sys/stat.h>
76 #include <signal.h>
77 #include <sys/time.h>
78 
79 #include "test.h"
80 
81 #define INCR_TIME	30	/* increment in the system's current time */
82 
83 #define BASH_CLOCK
84 
85 char *TCID = "stime01";
86 int TST_TOTAL = 1;
87 struct timeval real_time_tv, pres_time_tv;
88 time_t new_time;
89 
90 void setup();			/* Main setup function of test */
91 void cleanup();			/* cleanup function for the test */
92 
93 int main(int ac, char **av)
94 {
95 	int lc;
96 
97 	tst_parse_opts(ac, av, NULL, NULL);
98 
99 	setup();
100 
101 	for (lc = 0; TEST_LOOPING(lc); lc++) {
102 
103 		/*
104 		 * ``Break`` the clock.
105 		 *
106 		 * This is being done inline here so that the offset is
107 		 * automatically reset based on the elapsed time, and not a
108 		 * fixed time sampled once in setup.
109 		 *
110 		 * The big assumption here is the clock state isn't super
111 		 * fubared if so, the executing party needs to go fix their
112 		 * RTC's battery, or they have more pressing issues to attend
113 		 * to as far as clock skew is concerned :P.
114 		 */
115 		if (gettimeofday(&real_time_tv, NULL) < 0) {
116 			tst_brkm(TBROK | TERRNO, NULL,
117 				 "failed to get current time via gettimeofday(2)");
118 		}
119 
120 		/* Get the system's new time */
121 		new_time = real_time_tv.tv_sec + INCR_TIME;
122 
123 		tst_count = 0;
124 
125 		/*
126 		 * Invoke stime(2) to set the system's time to the specified
127 		 * new_time.
128 		 */
129 		if (stime(&new_time) < 0) {
130 			tst_resm(TFAIL | TERRNO, "stime(%ld) failed", new_time);
131 		} else {
132 
133 			/*
134 			 * Get the system's current time after call
135 			 * to stime().
136 			 */
137 			if (gettimeofday(&pres_time_tv, NULL) < 0) {
138 				tst_brkm(TFAIL | TERRNO, cleanup,
139 					 "time() failed to get "
140 					 "system's time after stime");
141 			}
142 
143 			/* Now do the actual verification */
144 			switch (pres_time_tv.tv_sec - new_time) {
145 			case 0:
146 			case 1:
147 				tst_resm(TINFO, "pt.tv_sec: %ld",
148 					 pres_time_tv.tv_sec);
149 				tst_resm(TPASS, "system time was set "
150 					 "to %ld", new_time);
151 				break;
152 			default:
153 				tst_resm(TFAIL, "system time was not "
154 					 "set to %ld (time is "
155 					 "actually: %ld)",
156 					 new_time, pres_time_tv.tv_sec);
157 			}
158 
159 			if (settimeofday(&real_time_tv, NULL) < 0) {
160 				tst_resm(TBROK | TERRNO,
161 					 "failed to restore time to original "
162 					 "value; system clock may need to be "
163 					 "fixed manually");
164 			}
165 
166 		}
167 
168 	}
169 
170 	cleanup();
171 	tst_exit();
172 
173 }
174 
175 /*
176  * void
177  * setup() - performs all ONE TIME setup for this test.
178  *  Get the current time and system's new time to be set in the test.
179  */
180 void setup(void)
181 {
182 	tst_require_root();
183 
184 	TEST_PAUSE;
185 
186 }
187 
188 /*
189  * void
190  * cleanup() - performs all ONE TIME cleanup for this test at
191  *             completion or premature exit.
192  */
193 void cleanup(void)
194 {
195 
196 	/* Restore the original system time. */
197 	if (settimeofday(&real_time_tv, NULL) != 0) {
198 		tst_resm(TBROK | TERRNO, "failed to restore time to original "
199 			 "value; system clock may need to be "
200 			 "fixed manually");
201 	}
202 
203 }
204