#include "tests.h"
#include <mach/mach.h>
int create_random_name( char *the_pathp, int do_open ) {
int i, my_err;
int my_fd = -1;
for ( i = 0; i < 1; i++ ) {
int my_rand;
char *myp;
char my_name[32];
my_rand = rand( );
sprintf( &my_name[0], "%d", my_rand );
if ( (strlen( &my_name[0] ) + strlen( the_pathp ) + 2) > PATH_MAX ) {
printf( "%s - path to test file greater than PATH_MAX \n", __FUNCTION__ );
return( -1 );
}
myp = strrchr( the_pathp, '/' );
*(myp + 1) = 0x00;
strcat( the_pathp, &my_name[0] );
if ( do_open ) {
my_fd = open( the_pathp, (O_RDWR | O_CREAT | O_EXCL),
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
if ( my_fd == -1 ) {
if ( errno != EEXIST ) {
printf( "%s - open failed with errno %d - %s \n",
__FUNCTION__, errno, strerror( errno ) );
return( -1 );
}
i--;
continue;
}
}
else {
struct stat my_sb;
my_err = stat( the_pathp, &my_sb );
if ( my_err != 0 ) {
if ( errno == ENOENT ) {
break;
}
else {
printf( "%s - open failed with errno %d - %s \n",
__FUNCTION__, errno, strerror( errno ) );
return( -1 );
}
}
i--;
continue;
}
}
if ( my_fd != -1 )
close( my_fd );
return( 0 );
}
int create_file_with_name( char *the_target_dirp, char *the_namep, int remove_existing ) {
int create_test_file, my_err, my_result;
int my_fd = -1;
char * my_pathp = NULL;
struct stat my_sb;
kern_return_t my_kr;
create_test_file = 0;
my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
if(my_kr != KERN_SUCCESS){
printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
goto failure_exit;
}
strcpy( my_pathp, the_target_dirp );
strcat( my_pathp, the_namep );
my_result = 0;
my_err = stat( my_pathp, &my_sb );
if ( my_err != 0 ) {
create_test_file = 1;
if ( errno != ENOENT ) {
goto failure_exit;
}
}
else {
if ( S_ISDIR( my_sb.st_mode ) ) {
my_result = 2;
if ( remove_existing ) {
my_err = rmdir( my_pathp );
if ( my_err == -1 ) {
printf( "rmdir failed with error %d - \"%s\" \n", errno, strerror( errno) );
goto failure_exit;
}
create_test_file = 1;
}
}
else {
my_result = 1;
if ( remove_existing ) {
my_err = unlink( my_pathp );
if ( my_err == -1 ) {
printf( "unlink failed with error %d - \"%s\" \n", errno, strerror( errno) );
goto failure_exit;
}
create_test_file = 1;
}
}
}
if ( create_test_file ) {
my_fd = open( my_pathp, (O_RDWR | O_CREAT | O_EXCL),
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
if ( my_fd == -1 ) {
printf( "open failed with error %d - \"%s\" \n", errno, strerror( errno) );
goto failure_exit;
}
close( my_fd );
}
goto routine_exit;
failure_exit:
my_result = -1;
routine_exit:
if ( my_pathp != NULL ) {
if ( my_result == -1 && create_test_file ) {
remove( my_pathp );
}
vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
}
return( my_result );
}
int do_execve_test(char * path, char * argv[], void * envp, int killwait)
{
int my_err = 0, my_status;
pid_t my_pid, my_wait_pid;
#if DEBUG
printf("do_execve_test(path = %s)\n", path);
printf("CWD= %s\n", getwd(NULL));
fflush(stdout);
#endif
my_pid = vfork();
if (my_pid == -1) {
printf( "vfork failed with errno %d - %s \n", errno, strerror( errno ) );
goto test_failed_exit;
}
if ( my_pid == 0 ) {
my_err = execve(path, argv, envp);
if ( my_err != 0 ) {
printf( "execve call failed with return value: %d, errno: %d - \"%s\"; path: %s \n",
my_err, errno, strerror( errno), path );
fflush(stdout);
exit(-2);
}
printf("Execve failed and it was not caught by our test\n");
return(-1);
}
sleep(killwait);
my_err = kill( my_pid, SIGKILL );
if ( my_err == -1 ) {
printf( "kill call failed with error %d - \"%s\" \n", errno, strerror( errno) );
goto test_failed_exit;
}
my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
if ( my_wait_pid == -1 ) {
printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
goto test_failed_exit;
}
if ( my_wait_pid != my_pid ) {
printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
goto test_failed_exit;
}
if (!(WIFSIGNALED( my_status ))) {
printf( "child process was not signaled and should have been\n", my_status );
goto test_failed_exit;
}
if (WTERMSIG( my_status ) != SIGKILL) {
printf( "wait4 returned wrong signal status - 0x%02X \n", my_status );
goto test_failed_exit;
}
my_err = 0;
goto test_passed_exit;
test_failed_exit:
my_err = 1;
test_passed_exit:
return( my_err );
}
int do_spawn_test(int arch, int shouldfail)
{
int my_err, my_pid, my_status;
size_t my_size;
posix_spawnattr_t attr;
char * args[] = {"helpers/arch", NULL};
my_err = posix_spawnattr_init(&attr);
if (my_err != 0) {
printf("posix_spawnattr_init failed\n");
goto done;
}
my_err = posix_spawnattr_setbinpref_np(&attr, 1, &arch, &my_size);
if (my_err != 0 || my_size != 1) {
printf("posix_spawnattr_setbinpref_np failed\n");
goto done;
}
my_err = posix_spawn(&my_pid, args[0], NULL, &attr, args, NULL);
if (shouldfail) {
if( my_err == 0) {
printf("posix_spawn should have failed on arch %d\n", arch);
goto done;
}
my_err = 0;
} else {
if (my_err != 0) {
printf("posix_spawn failed with errno %d - %s\n", my_err, strerror(my_err));
goto done;
}
my_err = wait4(my_pid, &my_status, 0, NULL);
if (my_err == -1) {
printf("wait4 failed with errno %d - %s\n", errno, strerror(errno));
goto done;
}
my_err = 0;
if (WEXITSTATUS(my_status) != (arch & 0xff)) {
printf("child exited with status %d (expected %d)\n",
(WEXITSTATUS(my_status)),
(arch & 0xff));
my_err = -1;
goto done;
}
}
done:
return my_err;
}
int get_architecture()
{
int rval = -1;
size_t length = 0;
int my_err, buf;
char *errmsg = NULL;
errmsg = "sysctlbyname() failed when getting hw.cputype";
if (my_err = sysctlbyname("hw.cputype", NULL, &length, NULL, 0)) goto finished;
if (length != sizeof(buf)) goto finished;
if (my_err = sysctlbyname("hw.cputype", &buf, &length, NULL, 0)) goto finished;
switch (buf) {
case CPU_TYPE_X86:
case CPU_TYPE_X86_64:
rval = INTEL;
break;
case CPU_TYPE_ARM:
rval = ARM;
break;
}
finished:
if (rval == -1 && errmsg)
printf("%s", errmsg);
return rval;
}
int get_bits()
{
int my_err, buf;
size_t len = 0;
int rval = 32;
if ((my_err = sysctlbyname("hw.optional.64bitops", NULL, &len, NULL, 0))) goto x86_64check;
if (len > sizeof(buf)) goto x86_64check;
if ((my_err = sysctlbyname("hw.optional.64bitops", &buf, &len, NULL, 0))) goto x86_64check;
if (buf == 1) rval = 64;
goto finished;
x86_64check:
if ((my_err = sysctlbyname("hw.optional.x86_64", NULL, &len, NULL, 0))) goto finished;
if (len > sizeof(buf)) goto finished;
if ((my_err = sysctlbyname("hw.optional.x86_64", &buf, &len, NULL, 0))) goto finished;
if (buf == 1) rval = 64;
finished:
return rval;
}
#define MY_PRINTF_DATE_FMT "%b %e %T"
#undef printf
int
my_printf(const char * __restrict fmt, ...)
{
char *bufp;
char datebuf[256];
struct tm *timeptr;
time_t result;
int rv;
va_list ap;
result = time(NULL);
timeptr = localtime(&result);
strftime(datebuf, sizeof(datebuf), MY_PRINTF_DATE_FMT, timeptr);
va_start(ap, fmt);
rv = vasprintf(&bufp, fmt, ap);
va_end(ap);
if (rv != -1) {
rv = printf("%s %s", datebuf, bufp);
free(bufp);
}
return(rv);
}