• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Crackerjack Project
3  *
4  * Copyright (C) 2007-2008, Hitachi, Ltd.
5  * Author(s): Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
6  *            Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *
22  * $Id: common_j_h.c,v 1.5 2009/11/20 06:48:31 yaberauneya Exp $
23  *
24  */
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <sys/stat.h>
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #include <fcntl.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <mqueue.h>
39 #include "include_j_h.h"
40 #include "test.h"
41 
42 #define barrier() __asm__ __volatile__("": : :"memory")
43 #define WITH_SIGNALS_BLOCKED(code) {					\
44 		sigset_t held_sigs_;					\
45 		sigfillset(&held_sigs_);				\
46 		sigprocmask(SIG_SETMASK, &held_sigs_, &held_sigs_);	\
47 		barrier();						\
48 		code;							\
49 		barrier();						\
50 		sigprocmask(SIG_SETMASK, &held_sigs_, NULL);		\
51 	}
52 
53 /*
54  * Change user ID
55  *
56  *   We assume 'test' executable is executed with 'root' permission.
57  *   So, if you use this function, you can not return 'root' uid.
58  */
setup_uid(char * uname)59 int setup_uid(char *uname)
60 {
61 	struct passwd *pw;
62 	int rc;
63 
64 	pw = getpwnam(uname);
65 	if (!pw) {
66 		EPRINTF("getpwnam failed.\n");
67 		return -1;
68 	}
69 	rc = setuid(pw->pw_uid);
70 	if (rc < 0) {
71 		EPRINTF("setuid failed.\n");
72 		return -1;
73 	}
74 	return 0;
75 }
76 
77 /*
78  * Change effective user ID
79  */
setup_euid(char * uname,uid_t * old_uid)80 int setup_euid(char *uname, uid_t * old_uid)
81 {
82 	struct passwd *pw;
83 	int rc;
84 
85 	*old_uid = geteuid();
86 	pw = getpwnam(uname);
87 	if (!pw) {
88 		EPRINTF("getpwnam failed.\n");
89 		return -1;
90 	}
91 	rc = seteuid(pw->pw_uid);
92 	if (rc < 0) {
93 		EPRINTF("seteuid failed.\n");
94 		return -1;
95 	}
96 	return 0;
97 }
98 
cleanup_euid(uid_t old_uid)99 int cleanup_euid(uid_t old_uid)
100 {
101 	int rc;
102 
103 	rc = seteuid(old_uid);
104 	if (rc < 0) {
105 		EPRINTF("seteuid failed.\n");
106 		return -1;
107 	}
108 	return 0;
109 }
110 
sigterm_handler(int sig)111 static void sigterm_handler(int sig)
112 {
113 	_exit(0);
114 }
115 
116 /*
117  * Generate a child process which will send a signal
118  */
create_sig_proc(unsigned long usec,int sig,unsigned count)119 pid_t create_sig_proc(unsigned long usec, int sig, unsigned count)
120 {
121 	pid_t pid, cpid;
122 
123 	pid = getpid();
124 	WITH_SIGNALS_BLOCKED(if ((cpid = fork()) == 0) {
125 			     tst_sig(NOFORK, SIG_DFL, NULL);
126 			     signal(SIGTERM, sigterm_handler);}
127 	) ;
128 	switch (cpid) {
129 	case 0:
130 		while (count-- > 0) {
131 			usleep(usec);
132 			if (kill(pid, sig) == -1)
133 				break;
134 		}
135 		_exit(0);
136 		break;
137 	case -1:
138 		EPRINTF("fork failed.\n");
139 		return cpid;
140 	default:
141 		return cpid;
142 	}
143 }
144 
145 /*
146  * Create and delete test file
147  */
setup_file(char * testdir,char * fname,char * path)148 int setup_file(char *testdir, char *fname, char *path)
149 {
150 	return _setup_file(testdir, fname, path,
151 			   O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
152 }
153 
_setup_file(char * testdir,char * fname,char * path,int flags,mode_t mode)154 int _setup_file(char *testdir, char *fname, char *path, int flags, mode_t mode)
155 {
156 	int rc;
157 
158 	sprintf(path, "%s/%s", testdir, fname);
159 	rc = open(path, flags, mode);
160 	if (rc < 0) {
161 		EPRINTF("open failed.\n");
162 		return -1;
163 	}
164 	return rc;
165 }
166 
cleanup_file(char * path)167 int cleanup_file(char *path)
168 {
169 	unlink(path);
170 	return 0;
171 }
172 
173 /*
174  * Create and delete swap file
175  */
176 /* swap file needs to be more than 40KB */
177 #define MIN_SWAPFILE_SIZE	(64 * 1024)
setup_swapfile(char * testdir,char * fname,char * path,size_t size)178 int setup_swapfile(char *testdir, char *fname, char *path, size_t size)
179 {
180 	int fd = -1, rc;
181 	size_t r_sz;
182 	int cmdlen = 256;
183 	char cmd[cmdlen];
184 	char *p = NULL;
185 
186 	sprintf(path, "%s/%s", testdir, fname);
187 	fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
188 	if (fd < 0) {
189 		EPRINTF("open failed.\n");
190 		goto ERR_EXIT;
191 	}
192 	if (size < MIN_SWAPFILE_SIZE) {
193 		EPRINTF("size too short.\n");
194 		goto ERR_EXIT;
195 	}
196 	p = malloc(size);
197 	if (!p) {
198 		EPRINTF("malloc failed.\n");
199 		goto ERR_EXIT;
200 	}
201 	/* Swap file must not have hole area */
202 	memset(p, 0x5a, size);
203 	r_sz = (size_t) write(fd, p, size);
204 	if (r_sz != size) {
205 		EPRINTF("write failed.\n");
206 		goto ERR_EXIT;
207 	}
208 	snprintf(cmd, cmdlen, "/sbin/mkswap %s > /dev/null 2>&1", path);
209 	rc = system(cmd);
210 	if (rc != 0) {
211 		EPRINTF("system(%s) failed.\n", cmd);
212 		goto ERR_EXIT;
213 	}
214 	return fd;
215 
216 ERR_EXIT:
217 	if (fd >= 0)
218 		close(fd);
219 	if (p)
220 		free(p);
221 	return -1;
222 }
223 
cleanup_swapfile(char * path)224 int cleanup_swapfile(char *path)
225 {
226 	unlink(path);
227 	return 0;
228 }
229 
230 /*
231  * Change user limit that the calling process can open
232  */
setup_ulimit_fnum(rlim_t newlim,rlim_t * oldlim)233 int setup_ulimit_fnum(rlim_t newlim, rlim_t * oldlim)
234 {
235 	int rc;
236 	struct rlimit rlim;
237 
238 	rc = getrlimit(RLIMIT_NOFILE, &rlim);
239 	if (rc < 0) {
240 		EPRINTF("getrlimit failed.\n");
241 		return -1;
242 	}
243 	*oldlim = rlim.rlim_cur;
244 	if (newlim > rlim.rlim_max) {
245 		EPRINTF("can't set ulimit value: %ld.\n", newlim);
246 		return -1;
247 	}
248 	rlim.rlim_cur = newlim;
249 	rc = setrlimit(RLIMIT_NOFILE, &rlim);
250 	if (rc < 0) {
251 		EPRINTF("setrlimit failed.\n");
252 		return -1;
253 	}
254 	return 0;
255 }
256 
cleanup_ulimit_fnum(rlim_t oldlim)257 int cleanup_ulimit_fnum(rlim_t oldlim)
258 {
259 	int rc;
260 	struct rlimit rlim;
261 
262 	rc = getrlimit(RLIMIT_NOFILE, &rlim);
263 	if (rc < 0) {
264 		EPRINTF("getrlimit failed.\n");
265 		return -1;
266 	}
267 	if (oldlim > rlim.rlim_max) {
268 		EPRINTF("can't set ulimit value: %ld.\n", oldlim);
269 		return -1;
270 	}
271 	rlim.rlim_cur = oldlim;
272 	rc = setrlimit(RLIMIT_NOFILE, &rlim);
273 	if (rc < 0) {
274 		EPRINTF("setrlimit failed.\n");
275 		return -1;
276 	}
277 	return 0;
278 }
279 
280 /*
281  * Change /proc or /sys setting
282  */
setup_proc_fs(char * path,int newval,int * oldval)283 int setup_proc_fs(char *path, int newval, int *oldval)
284 {
285 	int fd = -1, rc, len;
286 	char buf[32];
287 
288 	fd = open(path, O_RDWR);
289 	if (fd < 0) {
290 		EPRINTF("open %s failed.\n", path);
291 		return -1;
292 	}
293 
294 	do {
295 		rc = read(fd, buf, 32);
296 	} while (rc < 0 && errno == EAGAIN);
297 	if (rc < 0) {
298 		EPRINTF("read failed.\n");
299 		close(fd);
300 		return -1;
301 	}
302 
303 	*oldval = atoi(buf);
304 	sprintf(buf, "%d\n", newval);
305 	len = strlen(buf);
306 	rc = write(fd, buf, len);
307 	close(fd);
308 	if (rc != len) {
309 		EPRINTF("write failed.\n");
310 		return -1;
311 	}
312 	return 0;
313 }
314 
cleanup_proc_fs(char * path,int oldval)315 int cleanup_proc_fs(char *path, int oldval)
316 {
317 	int fd = -1, rc, len;
318 	char buf[32];
319 
320 	fd = open(path, O_RDWR);
321 	if (fd < 0) {
322 		EPRINTF("open %s failed.\n", path);
323 		return -1;
324 	}
325 
326 	sprintf(buf, "%d\n", oldval);
327 	len = strlen(buf);
328 	rc = write(fd, buf, len);
329 	close(fd);
330 	if (rc != len) {
331 		EPRINTF("write failed.\n");
332 		return -1;
333 	}
334 	return 0;
335 }
336 
337 #if 0
338 /*
339  * Check max nodes from /sys/devices/system/node/node* files (for NUMA)
340  */
341 int get_max_nodes(void)
342 {
343 	/* We assume that there is only one node */
344 	return 1;
345 }
346 #endif
347 
348 /*
349  * Get unexist pid
350  */
get_unexist_pid(void)351 pid_t get_unexist_pid(void)
352 {
353 	pid_t pid;
354 	int st;
355 
356 	pid = fork();
357 	switch (pid) {
358 	case -1:
359 		EPRINTF("fork failed.\n");
360 		return -1;
361 	case 0:
362 		_exit(0);
363 	default:
364 		wait(&st);
365 		return pid;
366 	}
367 }
368