]>
git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/misc.c
5 extern int g_testbots_active
;
8 * create_random_name - creates a file with a random / unique name in the given directory.
9 * when do_open is true we create a file else we generaate a name that does not exist in the
10 * given directory (we do not create anything when do_open is 0).
11 * WARNING - caller provides enough space in path buffer for longest possible name.
12 * WARNING - assumes caller has appended a trailing '/' on the path passed to us.
13 * RAND_MAX is currently 2147483647 (ten characters plus one for a slash)
15 int create_random_name( char *the_pathp
, int do_open
) {
19 for ( i
= 0; i
< 1; i
++ ) {
25 sprintf( &my_name
[0], "%d", my_rand
);
26 if ( (strlen( &my_name
[0] ) + strlen( the_pathp
) + 2) > PATH_MAX
) {
27 printf( "%s - path to test file greater than PATH_MAX \n", __FUNCTION__
);
31 // append generated file name onto our path
32 myp
= strrchr( the_pathp
, '/' );
34 strcat( the_pathp
, &my_name
[0] );
36 /* create a file with this name */
37 my_fd
= open( the_pathp
, (O_RDWR
| O_CREAT
| O_EXCL
),
38 (S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) );
40 if ( errno
!= EEXIST
) {
41 printf( "%s - open failed with errno %d - %s \n",
42 __FUNCTION__
, errno
, strerror( errno
) );
45 // name already exists, try another
51 /* make sure the name is unique */
53 my_err
= stat( the_pathp
, &my_sb
);
55 if ( errno
== ENOENT
) {
59 printf( "%s - open failed with errno %d - %s \n",
60 __FUNCTION__
, errno
, strerror( errno
) );
64 /* name already exists, try another */
75 } /* create_random_name */
78 * create_file_with_name - create a file in the given target directory using the given name.
79 * If an existing file or directory is present use the value of remove_existing to determine if the
80 * object is to be deleted.
81 * returns 0 if file could be created, 1 if file exists, 2 if directory exists, else -1
82 * NOTE - will fail if a directory is present with the given name and it is not empty.
84 int create_file_with_name( char *the_target_dirp
, char *the_namep
, int remove_existing
) {
85 int create_test_file
, my_err
, my_result
;
87 char * my_pathp
= NULL
;
92 my_kr
= vm_allocate((vm_map_t
) mach_task_self(), (vm_address_t
*)&my_pathp
, PATH_MAX
, VM_FLAGS_ANYWHERE
);
93 if(my_kr
!= KERN_SUCCESS
){
94 printf( "vm_allocate failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
98 strcpy( my_pathp
, the_target_dirp
);
99 strcat( my_pathp
, the_namep
);
101 /* make sure the name is unique */
103 my_err
= stat( my_pathp
, &my_sb
);
105 create_test_file
= 1;
106 if ( errno
!= ENOENT
) {
111 /* name already exists */
112 if ( S_ISDIR( my_sb
.st_mode
) ) {
113 my_result
= 2; /* tell caller directory exists with target name */
114 if ( remove_existing
) {
115 my_err
= rmdir( my_pathp
);
116 if ( my_err
== -1 ) {
117 printf( "rmdir failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
120 create_test_file
= 1;
124 my_result
= 1; /* tell caller file exists with target name */
125 if ( remove_existing
) {
126 my_err
= unlink( my_pathp
);
127 if ( my_err
== -1 ) {
128 printf( "unlink failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
131 create_test_file
= 1;
136 if ( create_test_file
) {
137 /* create a file with this name */
138 my_fd
= open( my_pathp
, (O_RDWR
| O_CREAT
| O_EXCL
),
139 (S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) );
141 printf( "open failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
144 fcntl( my_fd
, F_FULLFSYNC
);
152 if ( my_pathp
!= NULL
) {
153 if ( my_result
== -1 && create_test_file
) {
156 vm_deallocate(mach_task_self(), (vm_address_t
)my_pathp
, PATH_MAX
);
161 } /* create_file_with_name */
167 * This function is needed by both xnu_quick_test proper and the execve() helper
168 * program. It forks a child process and then exec()s an image on that child.
169 * Path, argv, and envp are fed directly to the execve() call.
170 * Parameter killwait decides how long to wait before killing the child.
172 int do_execve_test(char * path
, char * argv
[], void * envp
, int killwait
)
174 int my_err
= 0, my_status
;
175 pid_t my_pid
, my_wait_pid
;
178 printf("do_execve_test(path = %s)\n", path
);
179 printf("CWD= %s\n", getwd(NULL
));
183 /* vfork then execve sleep system command (which we will kill from the parent process) */
186 printf( "vfork failed with errno %d - %s \n", errno
, strerror( errno
) );
187 goto test_failed_exit
;
191 * child process - use execve to start one of the customized helper
192 * binaries, which just sleep for 120 seconds. Let our parent kill us.
195 my_err
= execve(path
, argv
, envp
);
196 if ( my_err
!= 0 ) { /* TODO: execve() on x86_64 inca returns weird error codes, see rdar://4655612 */
197 printf( "execve call failed with return value: %d, errno: %d - \"%s\"; path: %s \n",
198 my_err
, errno
, strerror( errno
), path
);
203 /* should never get here */
204 printf("Execve failed and it was not caught by our test\n");
208 * parent process - let's kill our sleeping child
211 my_err
= kill( my_pid
, SIGKILL
);
212 if ( my_err
== -1 ) {
213 printf( "kill call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
214 goto test_failed_exit
;
217 /* wait for child to exit */
218 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
219 if ( my_wait_pid
== -1 ) {
220 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
221 goto test_failed_exit
;
224 /* wait4 should return our child's pid when it exits */
225 if ( my_wait_pid
!= my_pid
) {
226 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid
, my_pid
);
227 goto test_failed_exit
;
230 if (!(WIFSIGNALED( my_status
))) {
231 printf( "child process was not signaled and should have been\n", my_status
);
232 goto test_failed_exit
;
235 if (WTERMSIG( my_status
) != SIGKILL
) {
236 printf( "wait4 returned wrong signal status - 0x%02X \n", my_status
);
237 goto test_failed_exit
;
241 goto test_passed_exit
;
248 } /* do_execve_test */
251 * Helper function for posix_spawn test
252 * arch: target architecture to spawn for
254 int do_spawn_test(int arch
, int shouldfail
)
256 int my_err
, my_pid
, my_status
;
258 posix_spawnattr_t attr
;
260 char * args
[] = {"helpers/arch", NULL
};
262 my_err
= posix_spawnattr_init(&attr
);
264 printf("posix_spawnattr_init failed\n");
268 /* set spawn to only succeed for arch 'arch' */
269 my_err
= posix_spawnattr_setbinpref_np(&attr
, 1, &arch
, &my_size
);
270 if (my_err
!= 0 || my_size
!= 1) {
271 printf("posix_spawnattr_setbinpref_np failed\n");
275 /* spawn off child process */
276 my_err
= posix_spawn(&my_pid
, args
[0], NULL
, &attr
, args
, NULL
);
279 printf("posix_spawn should have failed on arch %d\n", arch
);
285 * child should exit with return code == arch; note that the
286 * posix_spawn error numers are *returned*, NOT set in errno!!!
289 printf("posix_spawn failed with errno %d - %s\n", my_err
, strerror(my_err
));
293 my_err
= wait4(my_pid
, &my_status
, 0, NULL
);
295 printf("wait4 failed with errno %d - %s\n", errno
, strerror(errno
));
300 if (WEXITSTATUS(my_status
) != (arch
& 0xff)) {
301 printf("child exited with status %d (expected %d)\n",
302 (WEXITSTATUS(my_status
)),
314 * Uses sysctlbyname to determine the cpu type. Currently, XNU classifies G5 as a
315 * 32-bit CPU, so this shouldn't be used to determine whether or not a CPU
318 int get_architecture()
325 errmsg
= "sysctlbyname() failed when getting hw.cputype";
326 if ((my_err
= sysctlbyname("hw.cputype", NULL
, &length
, NULL
, 0))) goto finished
; /* get length of data */
327 if (length
!= sizeof(buf
)) goto finished
;
328 if ((my_err
= sysctlbyname("hw.cputype", &buf
, &length
, NULL
, 0))) goto finished
; /* copy data */
331 case CPU_TYPE_X86_64
:
335 #ifdef CPU_TYPE_ARM64
343 if (rval
== -1 && errmsg
)
344 printf("%s", errmsg
);
351 * Gets the bit'ed-ness of the current host. Returns either 32 or 64.
352 * This get the hardware capability, but does not tell us whether this
353 * binary is executing in 64 bit or 32 bit mode. Check sizeof long
354 * or pointer to determine that.
361 * On 32-bit systems the sysctls 64bitops and x86_64 don't
362 * even exists, so if we don't find them then we assume
366 /* Check for PPC 64 */
367 if ((my_err
= sysctlbyname("hw.optional.64bitops", NULL
, &len
, NULL
, 0))) goto check64bit
; /* Request size */
368 if (len
> sizeof(buf
)) goto check64bit
;
369 if ((my_err
= sysctlbyname("hw.optional.64bitops", &buf
, &len
, NULL
, 0))) goto check64bit
; /* Copy value out from kernel */
370 if (buf
== 1) rval
= 64;
374 #if defined(__i386__) || defined(__x86_64__)
375 /* Check for x86_64 */
376 if ((my_err
= sysctlbyname("hw.optional.x86_64", NULL
, &len
, NULL
, 0))) goto finished
; /* Request size */
377 if (len
> sizeof(buf
)) goto finished
;
378 if ((my_err
= sysctlbyname("hw.optional.x86_64", &buf
, &len
, NULL
, 0))) goto finished
; /* Copy value out from kernel */
379 if (buf
== 1) rval
= 64;
382 #error Unknown architecture.
390 * printf with a date and time stamp so that we can correlate printf's
391 * with the log files of a system in case of test failure.
393 * NB: MY_PRINTF_DATE_FMT chosen to look like syslog to aid "grep".
395 #define MY_PRINTF_DATE_FMT "%b %e %T"
396 #undef printf /* was my_printf */
398 my_printf(const char * __restrict fmt
, ...)
407 /* if we are running under a TestBot, do a normal printf */
408 if (g_testbots_active
) {
410 rv
= vprintf(fmt
, ap
);
415 /* Get the timestamp for this printf */
417 timeptr
= localtime(&result
);
418 strftime(datebuf
, sizeof(datebuf
), MY_PRINTF_DATE_FMT
, timeptr
);
420 /* do the printf of the requested data to a local buffer */
422 rv
= vasprintf(&bufp
, fmt
, ap
);
426 * if we successfully got a local buffer, then we want to
427 * print a timestamp plus what we would have printed before,
428 * then free the allocated memory.
431 rv
= printf("%s %s", datebuf
, bufp
);