1 /* 2 * Crackerjack Project 3 * 4 * Copyright (C) 2007-2008, Hitachi, Ltd. 5 * Author(s): Yumiko Sugita <yumiko.sugita.yf (at) hitachi.com>, 6 * Satoshi Fujiwara <sa-fuji (at) 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 */ 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 */ 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 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 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 */ 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 */ 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 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 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) 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 224 int cleanup_swapfile(char *path) 225 { 226 unlink(path); 227 return 0; 228 } 229 230 #if 0 231 /* 232 * Check max nodes from /sys/devices/system/node/node* files (for NUMA) 233 */ 234 int get_max_nodes(void) 235 { 236 /* We assume that there is only one node */ 237 return 1; 238 } 239 #endif 240 241 /* 242 * Get unexist pid 243 */ 244 pid_t get_unexist_pid(void) 245 { 246 pid_t pid; 247 int st; 248 249 pid = fork(); 250 switch (pid) { 251 case -1: 252 EPRINTF("fork failed.\n"); 253 return -1; 254 case 0: 255 _exit(0); 256 default: 257 wait(&st); 258 return pid; 259 } 260 } 261