X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/e2fac8b15b12a7979f72090454d850e612fc5b13..b0d623f7f2ae71ed96e60569f61f9a9a27016e80:/tools/tests/xnu_quick_test/32bit_inode_tests.c diff --git a/tools/tests/xnu_quick_test/32bit_inode_tests.c b/tools/tests/xnu_quick_test/32bit_inode_tests.c new file mode 100644 index 000000000..e5effea56 --- /dev/null +++ b/tools/tests/xnu_quick_test/32bit_inode_tests.c @@ -0,0 +1,294 @@ +/* + * 32bit_inode_tests.c + * xnu_quick_test + * + * Created by Ryan Branche on 2/17/08. + * Copyright 2008 Apple Inc. All rights reserved. + * + */ + +/* + * Explicitely turn off 64-bit inodes because we are testing the 32-bit inode + * versions of statfs functions and getdirentries doesn't support 64-bit inodes. + */ +#define _DARWIN_NO_64_BIT_INODE 1 + +#include "tests.h" +#include +#include + +extern char g_target_path[ PATH_MAX ]; +extern int g_skip_setuid_tests; +extern int g_is_under_rosetta; +extern int g_is_single_user; + +/* ************************************************************************************************************** + * Test getdirentries system call. + * ************************************************************************************************************** + */ +struct test_attr_buf { + uint32_t length; + fsobj_type_t obj_type; + fsobj_id_t obj_id; + struct timespec backup_time; +}; + +typedef struct test_attr_buf test_attr_buf; + +int getdirentries_test( void * the_argp ) +{ + int my_err, done, found_it, i; + int my_fd = -1; + int is_ufs = 0; + char * my_pathp = NULL; + char * my_bufp = NULL; + char * my_file_namep; + unsigned long my_base; + unsigned long my_count; + unsigned long my_new_state; + fsobj_id_t my_obj_id; + struct timespec my_new_backup_time; + struct attrlist my_attrlist; + test_attr_buf my_attr_buf[4]; + struct statfs my_statfs_buf; + kern_return_t my_kr; + + /* need to know type of file system */ + my_err = statfs( &g_target_path[0], &my_statfs_buf ); + if ( my_err == -1 ) { + printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + if ( memcmp( &my_statfs_buf.f_fstypename[0], "ufs", 3 ) == 0 ) { + is_ufs = 1; + } + + my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufp, (1024 * 5), VM_FLAGS_ANYWHERE); + if(my_kr != KERN_SUCCESS){ + printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) ); + goto test_failed_exit; + } + + 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 test_failed_exit; + } + + *my_pathp = 0x00; + strcat( my_pathp, &g_target_path[0] ); + strcat( my_pathp, "/" ); + + /* create a test file */ + my_err = create_random_name( my_pathp, 1 ); + if ( my_err != 0 ) { + goto test_failed_exit; + } + + /* get pointer to just the file name */ + my_file_namep = strrchr( my_pathp, '/' ); + my_file_namep++; + + /* check out the test directory */ + my_fd = open( &g_target_path[0], (O_RDONLY), 0 ); + if ( my_fd == -1 ) { + printf( "open failed with error %d - \"%s\" \n", errno, strerror( errno) ); + goto test_failed_exit; + } + + done = found_it = 0; + while ( done == 0 ) { + int my_result, i; + struct dirent * my_dirent_p; + + /* This call requires that 64-bit inodes are disabled */ + my_result = getdirentries( my_fd, my_bufp, (1024 * 5), &my_base ); + if ( my_result <= 0 ) + break; + for ( i = 0; i < my_result; ) { + my_dirent_p = (struct dirent *) (my_bufp + i); +#if DEBUG + printf( "d_ino %d d_reclen %d d_type %d d_namlen %d \"%s\" \n", + my_dirent_p->d_ino, my_dirent_p->d_reclen, my_dirent_p->d_type, + my_dirent_p->d_namlen, &my_dirent_p->d_name[0] ); +#endif + + i += my_dirent_p->d_reclen; + /* validate results by looking for our test file */ + if ( my_dirent_p->d_type == DT_REG && my_dirent_p->d_ino != 0 && + strlen( my_file_namep ) == my_dirent_p->d_namlen && + memcmp( &my_dirent_p->d_name[0], my_file_namep, my_dirent_p->d_namlen ) == 0 ) { + done = found_it = 1; + break; + } + } + } + if ( found_it == 0 ) { + printf( "getdirentries failed to find test file. \n" ); + goto test_failed_exit; + } + +test_failed_exit: + if(my_err != 0) + my_err = -1; + +test_passed_exit: + if ( my_fd != -1 ) + close( my_fd ); + if ( my_pathp != NULL ) { + remove( my_pathp ); + vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX); + } + if ( my_bufp != NULL ) { + vm_deallocate(mach_task_self(), (vm_address_t)my_bufp, (1024 * 5)); + } + + return( my_err ); +} + + +/* ************************************************************************************************************** + * Test 32-bit inode versions of statfs, fstatfs, and getfsstat system calls. + * ************************************************************************************************************** + */ + +#pragma pack(4) +struct vol_attr_buf { + u_int32_t length; + off_t volume_size; + u_int32_t io_blksize; +}; +#pragma pack() +typedef struct vol_attr_buf vol_attr_buf; + +int statfs_32bit_inode_tests( void * the_argp ) +{ + int my_err, my_count, i; + int my_buffer_size; + int my_fd = -1; + int is_ufs = 0; + void * my_bufferp = NULL; + struct statfs * my_statfsp; + long my_io_size; + fsid_t my_fsid; + struct attrlist my_attrlist; + vol_attr_buf my_attr_buf; + kern_return_t my_kr; + + my_buffer_size = (sizeof(struct statfs) * 10); + my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufferp, my_buffer_size, VM_FLAGS_ANYWHERE); + if(my_kr != KERN_SUCCESS){ + printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) ); + goto test_failed_exit; + } + + my_statfsp = (struct statfs *) my_bufferp; + my_err = statfs( "/", my_statfsp ); + if ( my_err == -1 ) { + printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + if ( memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 ) { + is_ufs = 1; + } + + my_count = getfsstat( (struct statfs *)my_bufferp, my_buffer_size, MNT_NOWAIT ); + if ( my_count == -1 ) { + printf( "getfsstat call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + + /* validate results */ + my_statfsp = (struct statfs *) my_bufferp; + for ( i = 0; i < my_count; i++, my_statfsp++ ) { + if ( memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 || + memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 || + memcmp( &my_statfsp->f_fstypename[0], "devfs", 5 ) == 0 || + memcmp( &my_statfsp->f_fstypename[0], "volfs", 5 ) == 0 ) { + /* found a valid entry */ + break; + } + } + if ( i >= my_count ) { + printf( "getfsstat call failed. could not find valid f_fstypename! \n" ); + goto test_failed_exit; + } + + /* set up to validate results via multiple sources. we use getattrlist to get volume + * related attributes to verify against results from fstatfs and statfs - but only if + * we are not targeting ufs volume since it doesn't support getattr calls + */ + if ( is_ufs == 0 ) { + memset( &my_attrlist, 0, sizeof(my_attrlist) ); + my_attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; + my_attrlist.volattr = (ATTR_VOL_SIZE | ATTR_VOL_IOBLOCKSIZE); + my_err = getattrlist( "/", &my_attrlist, &my_attr_buf, sizeof(my_attr_buf), 0 ); + if ( my_err != 0 ) { + printf( "getattrlist call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + } + + /* open kernel to use as test file for fstatfs */ + my_fd = open( "/mach_kernel", O_RDONLY, 0 ); + if ( my_fd == -1 ) { + printf( "open call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + + /* testing fstatfs */ + my_statfsp = (struct statfs *) my_bufferp; + my_err = fstatfs( my_fd, my_statfsp ); + if ( my_err == -1 ) { + printf( "fstatfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + + /* validate results */ + if ( !(memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 || + memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0) ) { + printf( "fstatfs call failed. could not find valid f_fstypename! \n" ); + goto test_failed_exit; + } + my_io_size = my_statfsp->f_iosize; + my_fsid = my_statfsp->f_fsid; + if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) { + printf( "fstatfs and getattrlist results do not match for volume block size \n" ); + goto test_failed_exit; + } + + /* try again with statfs */ + my_err = statfs( "/mach_kernel", my_statfsp ); + if ( my_err == -1 ) { + printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); + goto test_failed_exit; + } + + /* validate resutls */ + if ( my_io_size != my_statfsp->f_iosize || my_fsid.val[0] != my_statfsp->f_fsid.val[0] || + my_fsid.val[1] != my_statfsp->f_fsid.val[1] ) { + printf( "statfs call failed. wrong f_iosize or f_fsid! \n" ); + goto test_failed_exit; + } + if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) { + printf( "statfs and getattrlist results do not match for volume block size \n" ); + goto test_failed_exit; + } + + /* We passed the test */ + my_err = 0; + +test_failed_exit: + if(my_err != 0) + my_err = -1; + +test_passed_exit: + if ( my_fd != -1 ) + close( my_fd ); + if ( my_bufferp != NULL ) { + vm_deallocate(mach_task_self(), (vm_address_t)my_bufferp, my_buffer_size); + } + + return( my_err ); +} +