]>
Commit | Line | Data |
---|---|---|
b0d623f7 A |
1 | /* |
2 | * 32bit_inode_tests.c | |
3 | * xnu_quick_test | |
4 | * | |
5 | * Created by Ryan Branche on 2/17/08. | |
6 | * Copyright 2008 Apple Inc. All rights reserved. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* | |
11 | * Explicitely turn off 64-bit inodes because we are testing the 32-bit inode | |
12 | * versions of statfs functions and getdirentries doesn't support 64-bit inodes. | |
13 | */ | |
14 | #define _DARWIN_NO_64_BIT_INODE 1 | |
15 | ||
16 | #include "tests.h" | |
17 | #include <mach/mach.h> | |
18 | #include <dirent.h> | |
19 | ||
20 | extern char g_target_path[ PATH_MAX ]; | |
21 | extern int g_skip_setuid_tests; | |
22 | extern int g_is_under_rosetta; | |
23 | extern int g_is_single_user; | |
24 | ||
25 | /* ************************************************************************************************************** | |
26 | * Test getdirentries system call. | |
27 | * ************************************************************************************************************** | |
28 | */ | |
29 | struct test_attr_buf { | |
30 | uint32_t length; | |
31 | fsobj_type_t obj_type; | |
32 | fsobj_id_t obj_id; | |
33 | struct timespec backup_time; | |
34 | }; | |
35 | ||
36 | typedef struct test_attr_buf test_attr_buf; | |
37 | ||
38 | int getdirentries_test( void * the_argp ) | |
39 | { | |
40 | int my_err, done, found_it, i; | |
41 | int my_fd = -1; | |
42 | int is_ufs = 0; | |
43 | char * my_pathp = NULL; | |
44 | char * my_bufp = NULL; | |
45 | char * my_file_namep; | |
46 | unsigned long my_base; | |
47 | unsigned long my_count; | |
48 | unsigned long my_new_state; | |
49 | fsobj_id_t my_obj_id; | |
50 | struct timespec my_new_backup_time; | |
51 | struct attrlist my_attrlist; | |
52 | test_attr_buf my_attr_buf[4]; | |
53 | struct statfs my_statfs_buf; | |
54 | kern_return_t my_kr; | |
55 | ||
56 | /* need to know type of file system */ | |
57 | my_err = statfs( &g_target_path[0], &my_statfs_buf ); | |
58 | if ( my_err == -1 ) { | |
59 | printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
60 | goto test_failed_exit; | |
61 | } | |
62 | if ( memcmp( &my_statfs_buf.f_fstypename[0], "ufs", 3 ) == 0 ) { | |
63 | is_ufs = 1; | |
64 | } | |
65 | ||
66 | my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufp, (1024 * 5), VM_FLAGS_ANYWHERE); | |
67 | if(my_kr != KERN_SUCCESS){ | |
68 | printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
69 | goto test_failed_exit; | |
70 | } | |
71 | ||
72 | my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE); | |
73 | if(my_kr != KERN_SUCCESS){ | |
74 | printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
75 | goto test_failed_exit; | |
76 | } | |
77 | ||
78 | *my_pathp = 0x00; | |
79 | strcat( my_pathp, &g_target_path[0] ); | |
80 | strcat( my_pathp, "/" ); | |
81 | ||
82 | /* create a test file */ | |
83 | my_err = create_random_name( my_pathp, 1 ); | |
84 | if ( my_err != 0 ) { | |
85 | goto test_failed_exit; | |
86 | } | |
87 | ||
88 | /* get pointer to just the file name */ | |
89 | my_file_namep = strrchr( my_pathp, '/' ); | |
90 | my_file_namep++; | |
91 | ||
92 | /* check out the test directory */ | |
93 | my_fd = open( &g_target_path[0], (O_RDONLY), 0 ); | |
94 | if ( my_fd == -1 ) { | |
95 | printf( "open failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
96 | goto test_failed_exit; | |
97 | } | |
98 | ||
99 | done = found_it = 0; | |
100 | while ( done == 0 ) { | |
101 | int my_result, i; | |
102 | struct dirent * my_dirent_p; | |
103 | ||
104 | /* This call requires that 64-bit inodes are disabled */ | |
105 | my_result = getdirentries( my_fd, my_bufp, (1024 * 5), &my_base ); | |
106 | if ( my_result <= 0 ) | |
107 | break; | |
108 | for ( i = 0; i < my_result; ) { | |
109 | my_dirent_p = (struct dirent *) (my_bufp + i); | |
110 | #if DEBUG | |
111 | printf( "d_ino %d d_reclen %d d_type %d d_namlen %d \"%s\" \n", | |
112 | my_dirent_p->d_ino, my_dirent_p->d_reclen, my_dirent_p->d_type, | |
113 | my_dirent_p->d_namlen, &my_dirent_p->d_name[0] ); | |
114 | #endif | |
115 | ||
116 | i += my_dirent_p->d_reclen; | |
117 | /* validate results by looking for our test file */ | |
118 | if ( my_dirent_p->d_type == DT_REG && my_dirent_p->d_ino != 0 && | |
119 | strlen( my_file_namep ) == my_dirent_p->d_namlen && | |
120 | memcmp( &my_dirent_p->d_name[0], my_file_namep, my_dirent_p->d_namlen ) == 0 ) { | |
121 | done = found_it = 1; | |
122 | break; | |
123 | } | |
124 | } | |
125 | } | |
126 | if ( found_it == 0 ) { | |
127 | printf( "getdirentries failed to find test file. \n" ); | |
128 | goto test_failed_exit; | |
129 | } | |
130 | ||
131 | test_failed_exit: | |
132 | if(my_err != 0) | |
133 | my_err = -1; | |
134 | ||
135 | test_passed_exit: | |
136 | if ( my_fd != -1 ) | |
137 | close( my_fd ); | |
138 | if ( my_pathp != NULL ) { | |
139 | remove( my_pathp ); | |
140 | vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX); | |
141 | } | |
142 | if ( my_bufp != NULL ) { | |
143 | vm_deallocate(mach_task_self(), (vm_address_t)my_bufp, (1024 * 5)); | |
144 | } | |
145 | ||
146 | return( my_err ); | |
147 | } | |
148 | ||
149 | ||
150 | /* ************************************************************************************************************** | |
151 | * Test 32-bit inode versions of statfs, fstatfs, and getfsstat system calls. | |
152 | * ************************************************************************************************************** | |
153 | */ | |
154 | ||
155 | #pragma pack(4) | |
156 | struct vol_attr_buf { | |
157 | u_int32_t length; | |
158 | off_t volume_size; | |
159 | u_int32_t io_blksize; | |
160 | }; | |
161 | #pragma pack() | |
162 | typedef struct vol_attr_buf vol_attr_buf; | |
163 | ||
164 | int statfs_32bit_inode_tests( void * the_argp ) | |
165 | { | |
166 | int my_err, my_count, i; | |
167 | int my_buffer_size; | |
168 | int my_fd = -1; | |
169 | int is_ufs = 0; | |
170 | void * my_bufferp = NULL; | |
171 | struct statfs * my_statfsp; | |
172 | long my_io_size; | |
173 | fsid_t my_fsid; | |
174 | struct attrlist my_attrlist; | |
175 | vol_attr_buf my_attr_buf; | |
176 | kern_return_t my_kr; | |
177 | ||
178 | my_buffer_size = (sizeof(struct statfs) * 10); | |
179 | my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufferp, my_buffer_size, VM_FLAGS_ANYWHERE); | |
180 | if(my_kr != KERN_SUCCESS){ | |
181 | printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
182 | goto test_failed_exit; | |
183 | } | |
184 | ||
185 | my_statfsp = (struct statfs *) my_bufferp; | |
186 | my_err = statfs( "/", my_statfsp ); | |
187 | if ( my_err == -1 ) { | |
188 | printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
189 | goto test_failed_exit; | |
190 | } | |
191 | if ( memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 ) { | |
192 | is_ufs = 1; | |
193 | } | |
194 | ||
195 | my_count = getfsstat( (struct statfs *)my_bufferp, my_buffer_size, MNT_NOWAIT ); | |
196 | if ( my_count == -1 ) { | |
197 | printf( "getfsstat call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
198 | goto test_failed_exit; | |
199 | } | |
200 | ||
201 | /* validate results */ | |
202 | my_statfsp = (struct statfs *) my_bufferp; | |
203 | for ( i = 0; i < my_count; i++, my_statfsp++ ) { | |
204 | if ( memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 || | |
205 | memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 || | |
206 | memcmp( &my_statfsp->f_fstypename[0], "devfs", 5 ) == 0 || | |
207 | memcmp( &my_statfsp->f_fstypename[0], "volfs", 5 ) == 0 ) { | |
208 | /* found a valid entry */ | |
209 | break; | |
210 | } | |
211 | } | |
212 | if ( i >= my_count ) { | |
213 | printf( "getfsstat call failed. could not find valid f_fstypename! \n" ); | |
214 | goto test_failed_exit; | |
215 | } | |
216 | ||
217 | /* set up to validate results via multiple sources. we use getattrlist to get volume | |
218 | * related attributes to verify against results from fstatfs and statfs - but only if | |
219 | * we are not targeting ufs volume since it doesn't support getattr calls | |
220 | */ | |
221 | if ( is_ufs == 0 ) { | |
222 | memset( &my_attrlist, 0, sizeof(my_attrlist) ); | |
223 | my_attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; | |
224 | my_attrlist.volattr = (ATTR_VOL_SIZE | ATTR_VOL_IOBLOCKSIZE); | |
225 | my_err = getattrlist( "/", &my_attrlist, &my_attr_buf, sizeof(my_attr_buf), 0 ); | |
226 | if ( my_err != 0 ) { | |
227 | printf( "getattrlist call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
228 | goto test_failed_exit; | |
229 | } | |
230 | } | |
231 | ||
232 | /* open kernel to use as test file for fstatfs */ | |
233 | my_fd = open( "/mach_kernel", O_RDONLY, 0 ); | |
234 | if ( my_fd == -1 ) { | |
235 | printf( "open call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
236 | goto test_failed_exit; | |
237 | } | |
238 | ||
239 | /* testing fstatfs */ | |
240 | my_statfsp = (struct statfs *) my_bufferp; | |
241 | my_err = fstatfs( my_fd, my_statfsp ); | |
242 | if ( my_err == -1 ) { | |
243 | printf( "fstatfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
244 | goto test_failed_exit; | |
245 | } | |
246 | ||
247 | /* validate results */ | |
248 | if ( !(memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 || | |
249 | memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0) ) { | |
250 | printf( "fstatfs call failed. could not find valid f_fstypename! \n" ); | |
251 | goto test_failed_exit; | |
252 | } | |
253 | my_io_size = my_statfsp->f_iosize; | |
254 | my_fsid = my_statfsp->f_fsid; | |
255 | if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) { | |
256 | printf( "fstatfs and getattrlist results do not match for volume block size \n" ); | |
257 | goto test_failed_exit; | |
258 | } | |
259 | ||
260 | /* try again with statfs */ | |
261 | my_err = statfs( "/mach_kernel", my_statfsp ); | |
262 | if ( my_err == -1 ) { | |
263 | printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
264 | goto test_failed_exit; | |
265 | } | |
266 | ||
267 | /* validate resutls */ | |
268 | if ( my_io_size != my_statfsp->f_iosize || my_fsid.val[0] != my_statfsp->f_fsid.val[0] || | |
269 | my_fsid.val[1] != my_statfsp->f_fsid.val[1] ) { | |
270 | printf( "statfs call failed. wrong f_iosize or f_fsid! \n" ); | |
271 | goto test_failed_exit; | |
272 | } | |
273 | if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) { | |
274 | printf( "statfs and getattrlist results do not match for volume block size \n" ); | |
275 | goto test_failed_exit; | |
276 | } | |
277 | ||
278 | /* We passed the test */ | |
279 | my_err = 0; | |
280 | ||
281 | test_failed_exit: | |
282 | if(my_err != 0) | |
283 | my_err = -1; | |
284 | ||
285 | test_passed_exit: | |
286 | if ( my_fd != -1 ) | |
287 | close( my_fd ); | |
288 | if ( my_bufferp != NULL ) { | |
289 | vm_deallocate(mach_task_self(), (vm_address_t)my_bufferp, my_buffer_size); | |
290 | } | |
291 | ||
292 | return( my_err ); | |
293 | } | |
294 |