]> git.saurik.com Git - apple/xnu.git/blame - tools/tests/xnu_quick_test/misc.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / misc.c
CommitLineData
2d21ac55
A
1
2#include "tests.h"
3
4/*
5 * create_random_name - creates a file with a random / unique name in the given directory.
6 * when do_open is true we create a file else we generaate a name that does not exist in the
7 * given directory (we do not create anything when do_open is 0).
8 * WARNING - caller provides enough space in path buffer for longest possible name.
9 * WARNING - assumes caller has appended a trailing '/' on the path passed to us.
10 * RAND_MAX is currently 2147483647 (ten characters plus one for a slash)
11 */
12int create_random_name( char *the_pathp, int do_open ) {
13 int i, my_err;
14 int my_fd = -1;
15
16 for ( i = 0; i < 1; i++ ) {
17 int my_rand;
18 char *myp;
19 char my_name[32];
20
21 my_rand = rand( );
22 sprintf( &my_name[0], "%d", my_rand );
23 if ( (strlen( &my_name[0] ) + strlen( the_pathp ) + 2) > PATH_MAX ) {
24 printf( "%s - path to test file greater than PATH_MAX \n", __FUNCTION__ );
25 return( -1 );
26 }
27
28 // append generated file name onto our path
29 myp = strrchr( the_pathp, '/' );
30 *(myp + 1) = 0x00;
31 strcat( the_pathp, &my_name[0] );
32 if ( do_open ) {
33 /* create a file with this name */
34 my_fd = open( the_pathp, (O_RDWR | O_CREAT | O_EXCL),
35 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
36 if ( my_fd == -1 ) {
37 if ( errno != EEXIST ) {
38 printf( "%s - open failed with errno %d - %s \n",
39 __FUNCTION__, errno, strerror( errno ) );
40 return( -1 );
41 }
42 // name already exists, try another
43 i--;
44 continue;
45 }
46 }
47 else {
48 /* make sure the name is unique */
49 struct stat my_sb;
50 my_err = stat( the_pathp, &my_sb );
51 if ( my_err != 0 ) {
52 if ( errno == ENOENT ) {
53 break;
54 }
55 else {
56 printf( "%s - open failed with errno %d - %s \n",
57 __FUNCTION__, errno, strerror( errno ) );
58 return( -1 );
59 }
60 }
61 /* name already exists, try another */
62 i--;
63 continue;
64 }
65 }
66
67 if ( my_fd != -1 )
68 close( my_fd );
69
70 return( 0 );
71
72} /* create_random_name */
73
74/*
75 * create_file_with_name - create a file in the given target directory using the given name.
76 * If an existing file or directory is present use the value of remove_existing to determine if the
77 * object is to be deleted.
78 * returns 0 if file could be created, 1 if file exists, 2 if directory exists, else -1
79 * NOTE - will fail if a directory is present with the given name and it is not empty.
80 */
81int create_file_with_name( char *the_target_dirp, char *the_namep, int remove_existing ) {
82 int create_test_file, my_err, my_result;
83 int my_fd = -1;
84 char * my_pathp = NULL;
85 struct stat my_sb;
86
87 create_test_file = 0;
88 my_pathp = (char *) malloc( PATH_MAX );
89 if ( my_pathp == NULL ) {
90 printf( "malloc failed with error %d - \"%s\" \n", errno, strerror( errno) );
91 goto failure_exit;
92 }
93 strcpy( my_pathp, the_target_dirp );
94 strcat( my_pathp, the_namep );
95
96 /* make sure the name is unique */
97 my_result = 0;
98 my_err = stat( my_pathp, &my_sb );
99 if ( my_err != 0 ) {
100 create_test_file = 1;
101 if ( errno != ENOENT ) {
102 goto failure_exit;
103 }
104 }
105 else {
106 /* name already exists */
107 if ( S_ISDIR( my_sb.st_mode ) ) {
108 my_result = 2; /* tell caller directory exists with target name */
109 if ( remove_existing ) {
110 my_err = rmdir( my_pathp );
111 if ( my_err == -1 ) {
112 printf( "rmdir failed with error %d - \"%s\" \n", errno, strerror( errno) );
113 goto failure_exit;
114 }
115 create_test_file = 1;
116 }
117 }
118 else {
119 my_result = 1; /* tell caller file exists with target name */
120 if ( remove_existing ) {
121 my_err = unlink( my_pathp );
122 if ( my_err == -1 ) {
123 printf( "unlink failed with error %d - \"%s\" \n", errno, strerror( errno) );
124 goto failure_exit;
125 }
126 create_test_file = 1;
127 }
128 }
129 }
130
131 if ( create_test_file ) {
132 /* create a file with this name */
133 my_fd = open( my_pathp, (O_RDWR | O_CREAT | O_EXCL),
134 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
135 if ( my_fd == -1 ) {
136 printf( "open failed with error %d - \"%s\" \n", errno, strerror( errno) );
137 goto failure_exit;
138 }
139 close( my_fd );
140 }
141 goto routine_exit;
142
143failure_exit:
144 my_result = -1;
145routine_exit:
146 if ( my_pathp != NULL ) {
147 if ( my_result == -1 && create_test_file ) {
148 remove( my_pathp );
149 }
150 free( my_pathp );
151 }
152
153 return( my_result );
154
155} /* create_file_with_name */
156
157
158
159
160/*
161 * This function is needed by both xnu_quick_test proper and the execve() helper
162 * program. It forks a child process and then exec()s an image on that child.
163 * Path, argv, and envp are fed directly to the execve() call.
164 * Parameter killwait decides how long to wait before killing the child.
165 */
166int do_execve_test(char * path, char * argv[], void * envp, int killwait)
167{
168 int my_err = 0, my_status;
169 pid_t my_pid, my_wait_pid;
170
171#if DEBUG
172 printf("do_execve_test(path = %s)\n", path);
173 printf("CWD= %s\n", getwd(NULL));
174 fflush(stdout);
175#endif
176 /* vfork then execve sleep system command (which we will kill from the parent process) */
177 my_pid = vfork();
178 if (my_pid == -1) {
179 printf( "vfork failed with errno %d - %s \n", errno, strerror( errno ) );
180 goto test_failed_exit;
181 }
182 if ( my_pid == 0 ) {
183 /*
184 * child process - use execve to start one of the customized helper
185 * binaries, which just sleep for 120 seconds. Let our parent kill us.
186 */
187
188 my_err = execve(path, argv, envp);
189 if ( my_err != 0 ) { /* TODO: execve() on x86_64 inca returns weird error codes, see rdar://4655612 */
190 printf( "execve call failed with return value: %d, errno: %d - \"%s\"; path: %s \n",
191 my_err, errno, strerror( errno), path );
192 fflush(stdout);
193 exit(-2);
194 }
195
196 /* should never get here */
197 printf("Execve failed and it was not caught by our test\n");
198 return(-1);
199 }
200 /*
201 * parent process - let's kill our sleeping child
202 */
203 sleep(killwait);
204 my_err = kill( my_pid, SIGKILL );
205 if ( my_err == -1 ) {
206 printf( "kill call failed with error %d - \"%s\" \n", errno, strerror( errno) );
207 goto test_failed_exit;
208 }
209
210 /* wait for child to exit */
211 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
212 if ( my_wait_pid == -1 ) {
213 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
214 goto test_failed_exit;
215 }
216
217 /* wait4 should return our child's pid when it exits */
218 if ( my_wait_pid != my_pid ) {
219 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
220 goto test_failed_exit;
221 }
222
223 if ( WIFSIGNALED( my_status ) && WTERMSIG( my_status ) != SIGKILL ) {
224 printf( "wait4 returned wrong signal status - 0x%02X \n", my_status );
225 goto test_failed_exit;
226 }
227
228 my_err = 0;
229 goto test_passed_exit;
230
231test_failed_exit:
232 my_err = 1;
233
234test_passed_exit:
235 return( my_err );
236} /* do_execve_test */
237
238/*
239 * Helper function for posix_spawn test
240 * arch: target architecture to spawn for
241 */
242int do_spawn_test(int arch, int shouldfail)
243{
244 int my_err, my_pid, my_status;
245 size_t my_size;
246 posix_spawnattr_t attr;
247
248 char * args[] = {"helpers/arch", NULL};
cf7d32b8 249
2d21ac55
A
250 my_err = posix_spawnattr_init(&attr);
251 if (my_err != 0) {
252 printf("posix_spawnattr_init failed\n");
253 goto done;
254 }
255
256 /* set spawn to only succeed for arch 'arch' */
257 my_err = posix_spawnattr_setbinpref_np(&attr, 1, &arch, &my_size);
258 if (my_err != 0 || my_size != 1) {
259 printf("posix_spawnattr_setbinpref_np failed\n");
260 goto done;
261 }
262
263 /* spawn off child process */
264 my_err = posix_spawn(&my_pid, args[0], NULL, &attr, args, NULL);
265 if (shouldfail) {
266 if( my_err == 0) {
267 printf("posix_spawn should have failed on arch %d\n", arch);
268 goto done;
269 }
270 my_err = 0;
271 } else {
272 /* child should exit with return code == arch */
273 if (my_err != 0) {
274 printf("posix_spawn failed with errno %d - %s\n", errno, strerror(errno));
275 goto done;
276 }
277
278 my_err = wait4(my_pid, &my_status, 0, NULL);
279 if (my_err == -1) {
280 printf("wait4 failed with errno %d - %s\n", errno, strerror(errno));
281 goto done;
282 }
283 my_err = 0;
284
285 if (WEXITSTATUS(my_status) != (arch & 0xff)) {
286 printf("child exited with status %d (expected %d)\n",
287 (WEXITSTATUS(my_status)),
288 (arch & 0xff));
289 my_err = -1;
290 goto done;
291 }
292 }
293
294done:
295 return my_err;
296}
297
298/*
299 * Uses sysctlbyname to determine the cpu type. Currently, XNU classifies G5 as a
300 * 32-bit CPU, so this shouldn't be used to determine whether or not a CPU
301 * is 64-bit.
302 */
303int get_architecture()
304{
305 int rval = -1;
306 size_t length = 0;
307 int my_err, buf;
308 char *errmsg = NULL;
309
310 errmsg = "sysctlbyname() failed when getting hw.cputype";
311 if (my_err = sysctlbyname("hw.cputype", NULL, &length, NULL, 0)) goto finished; /* get length of data */
312 if (length != sizeof(buf)) goto finished;
313 if (my_err = sysctlbyname("hw.cputype", &buf, &length, NULL, 0)) goto finished; /* copy data */
314 switch (buf) {
315 case CPU_TYPE_X86:
316 case CPU_TYPE_X86_64:
317 rval = INTEL;
318 break;
319 case CPU_TYPE_POWERPC:
320 case CPU_TYPE_POWERPC64:
321 rval = POWERPC;
322 break;
cf7d32b8
A
323 case CPU_TYPE_ARM:
324 rval = ARM;
325 break;
2d21ac55
A
326 }
327
328finished:
329 if (rval == -1 && errmsg)
330 printf("%s", errmsg);
331
332 return rval;
333}
334
335
336/*
337 * Gets the bit'ed-ness of the current host. Returns either 32 or 64.
338 * This get the hardware capability, but does not tell us whether this
339 * binary is executing in 64 bit or 32 bit mode. Check sizeof long
340 * or pointer to determine that.
341 */
342int get_bits()
343{
344 int my_err, buf;
345 size_t len = 0;
346 int rval = 32; /*
347 * On 32-bit systems the sysctls 64bitops and x86_64 don't
348 * even exists, so if we don't find them then we assume
349 * a 32-bit system.
350 */
351
352 /* Check for PPC 64 */
353 if ((my_err = sysctlbyname("hw.optional.64bitops", NULL, &len, NULL, 0))) goto x86_64check; /* Request size */
354 if (len > sizeof(buf)) goto x86_64check;
355 if ((my_err = sysctlbyname("hw.optional.64bitops", &buf, &len, NULL, 0))) goto x86_64check; /* Copy value out from kernel */
356 if (buf == 1) rval = 64;
357 goto finished;
358
359x86_64check:
360 /* Check for x86_64 */
361 if ((my_err = sysctlbyname("hw.optional.x86_64", NULL, &len, NULL, 0))) goto finished; /* Request size */
362 if (len > sizeof(buf)) goto finished;
363 if ((my_err = sysctlbyname("hw.optional.x86_64", &buf, &len, NULL, 0))) goto finished; /* Copy value out from kernel */
364 if (buf == 1) rval = 64;
365
366finished:
367 return rval;
368}
369