]>
Commit | Line | Data |
---|---|---|
de8ee011 A |
1 | /* Copyright © 2017-2018 Apple Inc. All rights reserved. |
2 | * | |
3 | * livefiles_hfs_tester.c | |
4 | * hfs | |
5 | * | |
6 | * Created by Yakov Ben Zaken on 31/12/2017. | |
7 | */ | |
8 | ||
9 | #include <stdint.h> | |
10 | #include <stdlib.h> | |
11 | #include <mach/mach_time.h> | |
12 | #include "livefiles_hfs_tester.h" | |
13 | #include "lf_hfs_fsops_handler.h" | |
14 | #include "lf_hfs_dirops_handler.h" | |
15 | #include <UserFS/UserVFS.h> | |
16 | #include <assert.h> | |
17 | #include <sys/queue.h> | |
18 | #include "lf_hfs_journal.h" | |
19 | #include "lf_hfs_generic_buf.h" | |
20 | #include "lf_hfs_vfsutils.h" | |
21 | #include "lf_hfs_raw_read_write.h" | |
22 | ||
23 | #define DEFAULT_SYNCER_PERIOD 100 // mS | |
24 | #define MAX_UTF8_NAME_LENGTH (NAME_MAX*3+1) | |
25 | #define MAX_MAC2SFM (0x80) | |
26 | #define TEST_CYCLE_COUNT (1) | |
27 | #define CMP_TIMES(timspec1, timspec2) \ | |
28 | ((timspec1.tv_sec == timspec2.tv_sec) \ | |
29 | && (timspec1.tv_nsec == timspec2.tv_nsec)) | |
30 | ||
31 | #define ARR_LEN(arr) ((sizeof(arr))/(sizeof(arr[0]))) | |
32 | ||
33 | uint32_t guSyncerPeriod = DEFAULT_SYNCER_PERIOD; | |
34 | ||
35 | typedef int (*test_hander_t)( UVFSFileNode RootNode ); | |
36 | ||
37 | #if HFS_CRASH_TEST | |
38 | typedef int (*TesterCrashAbortFunction_FP)(void *psTestData, CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, pthread_t bSyncerThread); | |
39 | #endif | |
40 | ||
41 | ||
42 | typedef struct { | |
43 | ||
44 | char* pcTestName; | |
45 | char* pcDMGPath; | |
46 | test_hander_t pfTestHandler; | |
47 | ||
48 | UVFSFileNode psRootNode; | |
49 | pthread_t sSyncerThread; | |
50 | bool bSyncerOn; | |
51 | uint32_t uSyncerCount; | |
52 | bool bSparseImage; | |
53 | ||
54 | #if HFS_CRASH_TEST | |
55 | uint32_t uCrashAbortCnt; | |
56 | CrashAbort_E eCrashID; | |
57 | TesterCrashAbortFunction_FP pAbortFunc; | |
58 | pthread_t sTestExeThread; | |
59 | #endif | |
60 | } TestData_S; | |
61 | ||
62 | typedef struct { | |
63 | int iErr; | |
64 | int iFD; | |
65 | UVFSFileNode psNode; | |
66 | pthread_t pSyncerThread; | |
67 | #if HFS_CRASH_TEST | |
68 | CrashAbort_E eCrashID; | |
69 | #endif | |
70 | } TesterThreadReturnStatus_S; | |
71 | ||
72 | #if HFS_CRASH_TEST | |
73 | typedef struct { | |
74 | uint32_t uCrashCount; | |
75 | CrashAbort_E eCrashID; | |
76 | int iFD; | |
77 | UVFSFileNode psNode; | |
78 | pthread_t pSyncerThread; | |
79 | } CrashReport_S; | |
80 | #endif | |
81 | ||
82 | #if HFS_CRASH_TEST | |
83 | char *ppcCrashAbortDesc[CRASH_ABORT_LAST] = { | |
84 | [CRASH_ABORT_NONE] = "None", | |
85 | [CRASH_ABORT_MAKE_DIR] = "Make Dir", | |
86 | [CRASH_ABORT_JOURNAL_BEFORE_FINISH] = "Journal, before transaction finish", | |
87 | [CRASH_ABORT_JOURNAL_AFTER_JOURNAL_DATA] = "Journal, after journal data has been written", | |
88 | [CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER] = "Journal, after journal header has been written", | |
89 | [CRASH_ABORT_JOURNAL_IN_BLOCK_DATA] = "Journal, while block data is being written", | |
90 | [CRASH_ABORT_JOURNAL_AFTER_BLOCK_DATA] = "Journal, after block data has been written", | |
91 | [CRASH_ABORT_ON_UNMOUNT] = "Unmount", | |
92 | }; | |
93 | uint32_t guCrashAbortCnt = 0; | |
94 | CrashReport_S gsCrashReport; | |
95 | #endif | |
96 | ||
97 | int giFD = 0; | |
98 | ||
99 | // Multi-thread read-write test | |
100 | #if 1 // Quick Regression | |
101 | #define MTRW_NUM_OF_THREADS 10 | |
102 | #define MTRW_FILE_SIZE 5*1000 | |
103 | #define MTRW_NUM_OF_FILES 10 | |
104 | #define MTRW_NUM_OF_SYMLINKS 10 | |
105 | #define MTRW_SYMLINK_SIZE PATH_MAX | |
106 | #define MTRW_NUM_OF_OPERATIONS 10 | |
107 | #else // Longer Regression | |
108 | #define MTRW_NUM_OF_THREADS 30 | |
109 | #define MTRW_FILE_SIZE 5*1000 | |
110 | #define MTRW_NUM_OF_FILES 30 | |
111 | #define MTRW_NUM_OF_SYMLINKS 30 | |
112 | #define MTRW_SYMLINK_SIZE PATH_MAX | |
113 | #define MTRW_NUM_OF_OPERATIONS 30 | |
114 | #endif | |
115 | ||
116 | typedef struct { | |
117 | uint32_t uThreadNum; | |
118 | UVFSFileNode psRootNode; | |
119 | uint32_t uNumOfFiles; | |
120 | uint32_t uNumOfSymLinks; | |
121 | uint32_t uSymLinkSize; | |
122 | uint64_t uFileSize; | |
123 | int32_t iRetVal; | |
124 | } RWThreadData_S; | |
125 | ||
126 | ||
127 | static int SetAttrChangeSize(UVFSFileNode FileNode,uint64_t uNewSize); | |
128 | static int SetAttrChangeMode(UVFSFileNode FileNode,uint32_t uNewMode); | |
129 | static int SetAttrChangeUidGid(UVFSFileNode FileNode, uint32_t uNewUid, uint32_t uNewGid); | |
130 | static int SetAttrChangeAtimeMtime(UVFSFileNode FileNode); | |
131 | static int GetAttrAndCompare(UVFSFileNode FileNode,UVFSFileAttributes* sInAttrs); | |
132 | static int HFSTest_RunTest(TestData_S *psTestData); | |
133 | static void *ReadWriteThread(void *pvArgs); | |
134 | ||
135 | ||
136 | struct unistr255 { | |
137 | uint16_t length; | |
138 | uint16_t chars[255]; | |
139 | }; | |
140 | ||
141 | u_char | |
142 | l2u[256] = { | |
143 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */ | |
144 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */ | |
145 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ | |
146 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */ | |
147 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ | |
148 | 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ | |
149 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ | |
150 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ | |
151 | 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40-47 */ | |
152 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 48-4f */ | |
153 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 50-57 */ | |
154 | 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 58-5f */ | |
155 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 60-67 */ | |
156 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 68-6f */ | |
157 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 70-77 */ | |
158 | 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 78-7f */ | |
159 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */ | |
160 | 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */ | |
161 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */ | |
162 | 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */ | |
163 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */ | |
164 | 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */ | |
165 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */ | |
166 | 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */ | |
167 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */ | |
168 | 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */ | |
169 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */ | |
170 | 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */ | |
171 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */ | |
172 | 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */ | |
173 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */ | |
174 | 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */ | |
175 | }; | |
176 | ||
177 | /* | |
178 | * Macintosh Unicode (LSB) to Microsoft Services for Macintosh (SFM) Unicode | |
179 | */ | |
180 | static const uint16_t | |
181 | mac2sfm[MAX_MAC2SFM] = { | |
182 | 0x0, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007, /* 00-07 */ | |
183 | 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f, /* 08-0f */ | |
184 | 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017, /* 10-17 */ | |
185 | 0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, /* 18-1f */ | |
186 | 0x20, 0x21, 0xf020, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ | |
187 | 0x28, 0x29, 0xf021, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ | |
188 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ | |
189 | 0x38, 0x39, 0xf022, 0x3b, 0xf023, 0x3d, 0xf024, 0xf025, /* 38-3f */ | |
190 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 40-47 */ | |
191 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 48-4f */ | |
192 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 50-57 */ | |
193 | 0x58, 0x59, 0x5a, 0x5b, 0xf026, 0x5d, 0x5e, 0x5f, /* 58-5f */ | |
194 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 60-67 */ | |
195 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 68-6f */ | |
196 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 70-77 */ | |
197 | 0x78, 0x79, 0x7a, 0x7b, 0xf027, 0x7d, 0x7e, 0x7f, /* 78-7f */ | |
198 | }; | |
199 | ||
200 | static void | |
201 | unistr255ToLowerCase( struct unistr255* psUnistr255 ) | |
202 | { | |
203 | for ( uint16_t uIdx=0; uIdx<psUnistr255->length; uIdx++ ) | |
204 | { | |
205 | if ( psUnistr255->chars[uIdx] < 0x100 ) | |
206 | { | |
207 | psUnistr255->chars[uIdx] = l2u[psUnistr255->chars[uIdx]]; | |
208 | } | |
209 | } | |
210 | } | |
211 | ||
212 | void HFSTest_PrintCacheStats(void) { | |
213 | printf("Cache Statistics: buf_cache_size %u, max_buf_cache_size %u, buf_cache_cleanup %u, buf_cache_remove %u, max_gen_buf_uncached %u, gen_buf_uncached %u.\n", | |
214 | gCacheStat.buf_cache_size, | |
215 | gCacheStat.max_buf_cache_size, | |
216 | gCacheStat.buf_cache_cleanup, | |
217 | gCacheStat.buf_cache_remove, | |
218 | gCacheStat.max_gen_buf_uncached, | |
219 | gCacheStat.gen_buf_uncached); | |
220 | } | |
221 | ||
222 | __unused static long long int timestamp() | |
223 | { | |
224 | /* Example of timestamp in second. */ | |
225 | time_t timestamp_sec; /* timestamp in second */ | |
226 | time(×tamp_sec); /* get current time; same as: timestamp_sec = time(NULL) */ | |
227 | ||
228 | /* Example of timestamp in microsecond. */ | |
229 | struct timeval timer_usec; | |
230 | long long int timestamp_usec; /* timestamp in microsecond */ | |
231 | if (!gettimeofday(&timer_usec, NULL)) { | |
232 | timestamp_usec = ((long long int) timer_usec.tv_sec) * 1000000ll + | |
233 | (long long int) timer_usec.tv_usec; | |
234 | } | |
235 | else { | |
236 | timestamp_usec = -1; | |
237 | } | |
238 | ||
239 | return timestamp_usec; | |
240 | } | |
241 | ||
242 | __unused static errno_t | |
243 | CONV_UTF8ToUnistr255(const uint8_t *utf8, size_t utf8Length, struct unistr255 *unicode) | |
244 | { | |
245 | size_t i; | |
246 | uint32_t ch; | |
247 | ||
248 | unicode->length = 0; | |
249 | for (i = 0; i < utf8Length; ++i) | |
250 | { | |
251 | ch = utf8[i]; | |
252 | if ((ch & 0x80) == 0) | |
253 | { | |
254 | /* Plain ASCII */ | |
255 | } | |
256 | else if ((ch & 0xE0) == 0xC0) | |
257 | { | |
258 | /* Two-byte sequence */ | |
259 | if (utf8Length - i >= 2 && (utf8[i+1] & 0xC0) == 0x80) | |
260 | { | |
261 | ch = ((ch << 6) + utf8[++i]) - 0x3080; | |
262 | } | |
263 | else | |
264 | { | |
265 | /* Ill-formed UTF-8 */ | |
266 | return EILSEQ; | |
267 | } | |
268 | } | |
269 | else if ((ch & 0xF0) == 0xE0) | |
270 | { | |
271 | /* Three-byte sequence */ | |
272 | if (utf8Length - i >= 3 && (utf8[i+1] & 0xC0) == 0x80 && (utf8[i+2] & 0xC0) == 0x80) | |
273 | { | |
274 | ch <<= 6; | |
275 | ch += utf8[++i]; | |
276 | ch <<= 6; | |
277 | ch += utf8[++i]; | |
278 | ch -= 0xE2080; | |
279 | } | |
280 | else | |
281 | { | |
282 | /* Ill-formed UTF-8 */ | |
283 | return EILSEQ; | |
284 | } | |
285 | } | |
286 | else if ((ch & 0xF8) == 0xF0) | |
287 | { | |
288 | /* Four-byte sequence; requires surrogate pair for UTF-16 */ | |
289 | if (utf8Length - i >= 4 && (utf8[i+1] & 0xC0) == 0x80 && (utf8[i+2] & 0xC0) == 0x80 && (utf8[i+3] & 0xC0) == 0x80) | |
290 | { | |
291 | ch <<= 6; | |
292 | ch += utf8[++i]; | |
293 | ch <<= 6; | |
294 | ch += utf8[++i]; | |
295 | ch <<= 6; | |
296 | ch += utf8[++i]; | |
297 | ch -= 0x3C82080; | |
298 | } | |
299 | else | |
300 | { | |
301 | /* Ill-formed UTF-8 */ | |
302 | return EILSEQ; | |
303 | } | |
304 | } | |
305 | ||
306 | if (ch > 0xFFFF) | |
307 | { | |
308 | /* Requires surrogate pairs for UTF-16 */ | |
309 | if (unicode->length < 254) | |
310 | { | |
311 | ch -= 0x00010000; | |
312 | unicode->chars[unicode->length++] = 0xD800 | (ch >> 10); | |
313 | unicode->chars[unicode->length++] = 0xDC00 | (ch & 0x003F); | |
314 | } | |
315 | else | |
316 | { | |
317 | return ENAMETOOLONG; | |
318 | } | |
319 | } | |
320 | else | |
321 | { | |
322 | if (unicode->length < 255) | |
323 | { | |
324 | unicode->chars[unicode->length++] = ch; | |
325 | } | |
326 | else | |
327 | { | |
328 | /* No room to store character */ | |
329 | return ENAMETOOLONG; | |
330 | } | |
331 | } | |
332 | } | |
333 | ||
334 | //Only in "." and ".." we don't need to change the last char to speciel char. | |
335 | bool bNeedToChangeLastChar = true; | |
336 | if ( ((unicode->length == 1) && (unicode->chars[0] == '.')) || | |
337 | ((unicode->length == 2) && (unicode->chars[0] == '.') && (unicode->chars[1] == '.')) ) | |
338 | { | |
339 | bNeedToChangeLastChar = false; | |
340 | } | |
341 | ||
342 | for ( uint16_t uIdx=0; uIdx<unicode->length; uIdx++ ) | |
343 | { | |
344 | //If the last char is "." or " " we need to change it. | |
345 | //We won't use the mac2sfm table, we will do it manually | |
346 | if ( bNeedToChangeLastChar && uIdx == unicode->length-1 ) | |
347 | { | |
348 | if ( unicode->chars[uIdx] == ' ' ) | |
349 | { | |
350 | unicode->chars[uIdx] = 0xf028; | |
351 | continue; | |
352 | } | |
353 | ||
354 | if ( unicode->chars[uIdx] == '.' ) | |
355 | { | |
356 | unicode->chars[uIdx] = 0xf029; | |
357 | continue; | |
358 | } | |
359 | } | |
360 | ||
361 | ||
362 | if ( unicode->chars[uIdx] < MAX_MAC2SFM ) | |
363 | { | |
364 | unicode->chars[uIdx] = mac2sfm[unicode->chars[uIdx]]; | |
365 | } | |
366 | } | |
367 | ||
368 | return 0; | |
369 | } | |
370 | ||
371 | __unused static void print_dir_entry_name( uint32_t uLen, char* pcName, char* pcSearchName, bool* pbFound ) | |
372 | { | |
373 | struct unistr255 sU255; | |
374 | struct unistr255 sU2552; | |
375 | memset( &sU255, 0, sizeof(struct unistr255)); | |
376 | memset( &sU2552, 0, sizeof(struct unistr255)); | |
377 | errno_t status = CONV_UTF8ToUnistr255( (uint8_t*)pcName, strlen(pcName), &sU255 ); | |
378 | status |= CONV_UTF8ToUnistr255( (uint8_t*)pcSearchName, strlen(pcSearchName), &sU2552 ); | |
379 | ||
380 | if ( status != 0 ) { assert(0); } | |
381 | ||
382 | uLen = sU255.length; | |
383 | ||
384 | char pcNameToPrint[uLen+1]; | |
385 | memset( pcNameToPrint, 0, sizeof(pcNameToPrint) ); | |
386 | ||
387 | uint16_t* puName = sU255.chars; | |
388 | for ( uint32_t uIdx=0; uIdx<uLen; uIdx++ ) | |
389 | { | |
390 | pcNameToPrint[uIdx] = *puName++ & 0xff; | |
391 | } | |
392 | ||
393 | // printf( "TESTER Entry Name = [%s]\n", pcNameToPrint ); | |
394 | ||
395 | if ( pcSearchName ) | |
396 | { | |
397 | unistr255ToLowerCase(&sU255); | |
398 | unistr255ToLowerCase(&sU2552); | |
399 | ||
400 | if ( (sU255.length == sU2552.length) && !memcmp(sU255.chars, sU2552.chars, sU255.length*2) ) | |
401 | { | |
402 | *pbFound = true; | |
403 | } | |
404 | } | |
405 | } | |
406 | ||
407 | static bool | |
408 | HFSTest_CompareReadDir( void* psReadEntry, UVFSDirEntryAttr* psExpectedAttr, bool bIsWAttr) | |
409 | { | |
410 | bool bIsEqual = true; | |
411 | if (bIsWAttr) | |
412 | { | |
413 | UVFSDirEntryAttr* psNewDirListEntry = (UVFSDirEntryAttr*) psReadEntry; | |
414 | if ( (strcmp(UVFS_DIRENTRYATTR_NAMEPTR(psExpectedAttr),UVFS_DIRENTRYATTR_NAMEPTR(psNewDirListEntry))) || // Comapre Name | |
415 | (psNewDirListEntry->dea_attrs.fa_type != psExpectedAttr->dea_attrs.fa_type) || // Comapre Type | |
416 | (psNewDirListEntry->dea_attrs.fa_size != psExpectedAttr->dea_attrs.fa_size) || // Comapre Size | |
417 | (psNewDirListEntry->dea_attrs.fa_nlink != psExpectedAttr->dea_attrs.fa_nlink) || // Compare Nlink | |
418 | (psNewDirListEntry->dea_attrs.fa_mtime.tv_sec != psExpectedAttr->dea_attrs.fa_mtime.tv_sec) || // Comapre MTime | |
419 | (psNewDirListEntry->dea_attrs.fa_ctime.tv_sec != psExpectedAttr->dea_attrs.fa_ctime.tv_sec) || // Comapre Ctime | |
420 | (psNewDirListEntry->dea_attrs.fa_atime.tv_sec != psExpectedAttr->dea_attrs.fa_atime.tv_sec) || // Comapre Atime | |
421 | (psNewDirListEntry->dea_attrs.fa_birthtime.tv_sec != psExpectedAttr->dea_attrs.fa_birthtime.tv_sec) || // Comapre birthtime | |
422 | (psNewDirListEntry->dea_attrs.fa_mtime.tv_nsec != psExpectedAttr->dea_attrs.fa_mtime.tv_nsec) || // Comapre MTime | |
423 | (psNewDirListEntry->dea_attrs.fa_ctime.tv_nsec != psExpectedAttr->dea_attrs.fa_ctime.tv_nsec) || // Comapre Ctime | |
424 | (psNewDirListEntry->dea_attrs.fa_atime.tv_nsec != psExpectedAttr->dea_attrs.fa_atime.tv_nsec) || // Comapre Atime | |
425 | (psNewDirListEntry->dea_attrs.fa_birthtime.tv_nsec != psExpectedAttr->dea_attrs.fa_birthtime.tv_nsec) || // Comapre birthtime | |
426 | (psNewDirListEntry->dea_attrs.fa_allocsize != psExpectedAttr->dea_attrs.fa_allocsize) ) | |
427 | { | |
428 | printf("HFSTest_CompareReadDir: failed.\n"); | |
429 | ||
430 | printf("HFSTest_CompareReadDir: expected- name [%s], type [%d], size [%llu], nlink [%u], allocsize [%llu].\n",UVFS_DIRENTRYATTR_NAMEPTR(psExpectedAttr), psExpectedAttr->dea_attrs.fa_type, psExpectedAttr->dea_attrs.fa_size, psExpectedAttr->dea_attrs.fa_nlink, psExpectedAttr->dea_attrs.fa_allocsize); | |
431 | printf("HFSTest_CompareReadDir: expected- mtime [%ld.%ld], ctime [%ld.%ld], atime [%ld.%ld], btime [%ld.%ld] .\n",psExpectedAttr->dea_attrs.fa_mtime.tv_sec,psExpectedAttr->dea_attrs.fa_mtime.tv_nsec,psExpectedAttr->dea_attrs.fa_ctime.tv_sec,psExpectedAttr->dea_attrs.fa_ctime.tv_nsec, psExpectedAttr->dea_attrs.fa_atime.tv_sec, psExpectedAttr->dea_attrs.fa_atime.tv_nsec, psExpectedAttr->dea_attrs.fa_birthtime.tv_sec, psExpectedAttr->dea_attrs.fa_birthtime.tv_nsec); | |
432 | ||
433 | printf("HFSTest_CompareReadDir: got - name [%s], type [%d], size [%llu], nlink [%u], allocsize [%llu].\n",UVFS_DIRENTRYATTR_NAMEPTR(psNewDirListEntry), psNewDirListEntry->dea_attrs.fa_type, psNewDirListEntry->dea_attrs.fa_size, psNewDirListEntry->dea_attrs.fa_nlink, psNewDirListEntry->dea_attrs.fa_allocsize); | |
434 | printf("HFSTest_CompareReadDir: got - mtime [%ld.%ld], ctime [%ld.%ld], atime [%ld.%ld], btime [%ld.%ld] .\n",psNewDirListEntry->dea_attrs.fa_mtime.tv_sec,psNewDirListEntry->dea_attrs.fa_mtime.tv_nsec,psNewDirListEntry->dea_attrs.fa_ctime.tv_sec,psNewDirListEntry->dea_attrs.fa_ctime.tv_nsec, psNewDirListEntry->dea_attrs.fa_atime.tv_sec,psNewDirListEntry->dea_attrs.fa_atime.tv_nsec, psNewDirListEntry->dea_attrs.fa_birthtime.tv_sec,psNewDirListEntry->dea_attrs.fa_birthtime.tv_nsec); | |
435 | ||
436 | bIsEqual = false; | |
437 | } | |
438 | } | |
439 | else | |
440 | { | |
441 | UVFSDirEntry* psNewDirListEntry = ( UVFSDirEntry*) psReadEntry; | |
442 | if ( (strcmp(UVFS_DIRENTRYATTR_NAMEPTR(psExpectedAttr),psNewDirListEntry->de_name)) || // Comapre Name | |
443 | (psNewDirListEntry->de_filetype != psExpectedAttr->dea_attrs.fa_type)) // Comapre Type | |
444 | { | |
445 | bIsEqual = false; | |
446 | } | |
447 | } | |
448 | ||
449 | ||
450 | ||
451 | return bIsEqual; | |
452 | } | |
453 | ||
454 | /* --------------------------------------------------------------------------------------------- */ | |
455 | static void SetExpectedAttr(char* pcName, uint32_t uType, UVFSDirEntryAttr* psAttr); | |
456 | static int ReadDirAttr(UVFSFileNode psNode, UVFSDirEntryAttr* psReadDirTestsData, uint32_t uDirEntries); | |
457 | static int RemoveFolder(UVFSFileNode ParentNode,char* DirNameToRemove); | |
458 | static int CreateNewFolder(UVFSFileNode ParentNode,UVFSFileNode* NewDirNode,char* NewDirName); | |
459 | static int CreateHardLink(UVFSFileNode FromNode, UVFSFileNode ToDirNode, char* NewHardLinkName); | |
460 | static int RemoveFile(UVFSFileNode ParentNode,char* FileNameToRemove); | |
461 | static int CreateNewFile(UVFSFileNode ParentNode,UVFSFileNode* NewFileNode,char* NewFileName,uint64_t size); | |
462 | static int read_directory_and_search_for_name( UVFSFileNode psNode, char* pcSearchName, bool* pbFound, UVFSDirEntryAttr* psReadDirTestsData, uint32_t uDirEntries ); | |
463 | static int RenameFile(UVFSFileNode FromParentNode,UVFSFileNode FromNode,char* FromName, UVFSFileNode ToParentNode,UVFSFileNode ToNode,char* ToName); | |
464 | /* --------------------------------------------------------------------------------------------- */ | |
465 | ||
466 | static int RemoveFolder(UVFSFileNode ParentNode,char* DirNameToRemove) | |
467 | { | |
468 | int error =0; | |
469 | ||
470 | error = HFS_fsOps.fsops_rmdir(ParentNode, DirNameToRemove);; | |
471 | ||
472 | return error; | |
473 | } | |
474 | ||
475 | static int RemoveFile(UVFSFileNode ParentNode,char* FileNameToRemove) | |
476 | { | |
477 | int error =0; | |
478 | ||
479 | error = HFS_fsOps.fsops_remove( ParentNode, FileNameToRemove, NULL); | |
480 | ||
481 | return error; | |
482 | } | |
483 | ||
484 | static int RenameFile(UVFSFileNode FromParentNode,UVFSFileNode FromNode,char* FromName, UVFSFileNode ToParentNode,UVFSFileNode ToNode,char* ToName) | |
485 | { | |
486 | int error =0; | |
487 | ||
488 | error = HFS_fsOps.fsops_rename( FromParentNode, FromNode, FromName, ToParentNode, ToNode, ToName, 0); | |
489 | ||
490 | return error; | |
491 | } | |
492 | ||
493 | static int CreateNewFile(UVFSFileNode ParentNode,UVFSFileNode* NewFileNode,char* NewFileName,uint64_t size) | |
494 | { | |
495 | int error =0; | |
496 | UVFSFileAttributes attrs = {0}; | |
497 | ||
498 | attrs.fa_validmask = UVFS_FA_VALID_MODE | UVFS_FA_VALID_SIZE; | |
499 | attrs.fa_type = UVFS_FA_TYPE_FILE; | |
500 | attrs.fa_mode = UVFS_FA_MODE_OTH(UVFS_FA_MODE_RWX)|UVFS_FA_MODE_GRP(UVFS_FA_MODE_RWX)|UVFS_FA_MODE_USR(UVFS_FA_MODE_RWX);; | |
501 | attrs.fa_size = size; | |
502 | ||
503 | error = HFS_fsOps.fsops_create(ParentNode, NewFileName, &attrs, NewFileNode); | |
504 | ||
505 | return error; | |
506 | } | |
507 | ||
508 | static int CreateNewFolder(UVFSFileNode ParentNode,UVFSFileNode* NewDirNode,char* NewDirName) | |
509 | { | |
510 | int error =0; | |
511 | ||
512 | UVFSFileAttributes attrs; | |
513 | memset(&attrs,0,sizeof(UVFSFileAttributes)); | |
514 | attrs.fa_validmask = UVFS_FA_VALID_MODE; | |
515 | attrs.fa_type = UVFS_FA_TYPE_DIR; | |
516 | attrs.fa_mode = UVFS_FA_MODE_OTH(UVFS_FA_MODE_RWX)|UVFS_FA_MODE_GRP(UVFS_FA_MODE_RWX)|UVFS_FA_MODE_USR(UVFS_FA_MODE_RWX); | |
517 | error = HFS_fsOps.fsops_mkdir(ParentNode, NewDirName, &attrs, NewDirNode); | |
518 | ||
519 | return error; | |
520 | } | |
521 | ||
522 | static int CreateHardLink(UVFSFileNode FromNode, UVFSFileNode ToDirNode, char* NewHardLinkName) | |
523 | { | |
524 | int error =0; | |
525 | ||
526 | UVFSFileAttributes sToDirAttrs; | |
527 | UVFSFileAttributes sFromNodeAttrs; | |
528 | memset(&sToDirAttrs,0,sizeof(UVFSFileAttributes)); | |
529 | memset(&sFromNodeAttrs,0,sizeof(UVFSFileAttributes)); | |
530 | ||
531 | error = HFS_fsOps.fsops_link(FromNode, ToDirNode, NewHardLinkName, &sFromNodeAttrs, &sToDirAttrs); | |
532 | ||
533 | return error; | |
534 | } | |
535 | ||
536 | static int read_directory_and_search_for_name( UVFSFileNode psNode, char* pcSearchName, bool* pbFound, UVFSDirEntryAttr* psReadDirTestsData, uint32_t uDirEntries ) | |
537 | { | |
538 | if (pbFound) *pbFound = false; | |
539 | ||
540 | uint32_t uBufferSize = 1000; | |
541 | uint8_t* puBuffer = malloc(uBufferSize*2); | |
542 | if ( puBuffer == NULL ) | |
543 | { | |
544 | return ENOMEM; | |
545 | } | |
546 | memset(puBuffer, 0xff, uBufferSize*2); | |
547 | ||
548 | uint64_t uCookie = 0; | |
549 | uint64_t uVerifier = UVFS_DIRCOOKIE_VERIFIER_INITIAL; | |
550 | bool bConRead = true; | |
551 | ||
552 | uint32_t uDirsCounter = 0; | |
553 | uint32_t uFilesCounter = 0; | |
554 | uint32_t uLinksCounter = 0; | |
555 | size_t outLen = 0; | |
556 | uint32_t uDirIndex = 0; | |
557 | int iReadDirERR = 0; | |
558 | UVFSDirEntryAttr* psDirData = psReadDirTestsData; | |
559 | ||
560 | do { | |
561 | uint32_t uBufCurOffset = 0; | |
562 | ||
563 | memset(puBuffer, 0, uBufferSize); | |
564 | ||
565 | iReadDirERR = HFS_fsOps.fsops_readdir (psNode, puBuffer, uBufferSize, uCookie, &outLen, &uVerifier); | |
566 | // assert(0xffffffffffffffff == *(uint64_t*)(&puBuffer[100])); | |
567 | if ( (iReadDirERR != 0 && iReadDirERR != UVFS_READDIR_EOF_REACHED) || outLen==0) | |
568 | { | |
569 | bConRead = false; | |
570 | } | |
571 | else | |
572 | { | |
573 | //Go over all entries in the list and check if we got to the end of the directory | |
574 | bool bEndOfDirectoryList = false; | |
575 | ||
576 | while ( !bEndOfDirectoryList && iReadDirERR != UVFS_READDIR_EOF_REACHED ) | |
577 | { | |
578 | UVFSDirEntry* psNewDirListEntry = (UVFSDirEntry*) &puBuffer[uBufCurOffset]; | |
579 | uCookie = psNewDirListEntry->de_nextcookie; | |
580 | ||
581 | //We found all the files in the root directory | |
582 | if ( ( psNewDirListEntry->de_nextcookie == UVFS_DIRCOOKIE_EOF ) || ( psNewDirListEntry->de_reclen == 0 ) ) | |
583 | { | |
584 | bEndOfDirectoryList = true; | |
585 | } | |
586 | ||
587 | print_dir_entry_name( psNewDirListEntry->de_namelen, psNewDirListEntry->de_name, pcSearchName, pbFound ); | |
588 | switch ( psNewDirListEntry->de_filetype ) | |
589 | { | |
590 | case UVFS_FA_TYPE_DIR: | |
591 | { | |
592 | //printf("found dir: ID: %llu, named [%s], in offset [%u]\n",psNewDirListEntry->de_fileid, psNewDirListEntry->de_name, uBufCurOffset); | |
593 | uDirsCounter++; | |
594 | } | |
595 | break; | |
596 | case UVFS_FA_TYPE_FILE: | |
597 | { | |
598 | //printf("found file: ID: %llu, named [%s], in offset [%u]\n",psNewDirListEntry->de_fileid, psNewDirListEntry->de_name, uBufCurOffset); | |
599 | uFilesCounter++; | |
600 | } | |
601 | break; | |
602 | case UVFS_FA_TYPE_SYMLINK: | |
603 | { | |
604 | //printf("found link: ID: %llu, named [%s], in offset [%u]\n",psNewDirListEntry->de_fileid, psNewDirListEntry->de_name, uBufCurOffset); | |
605 | uLinksCounter++; | |
606 | } | |
607 | break; | |
608 | ||
609 | default: | |
610 | printf("Found Unkown file type %d, named [%s], Exiting\n", psNewDirListEntry->de_filetype, psNewDirListEntry->de_name); | |
611 | bEndOfDirectoryList = true; | |
612 | bConRead = false; | |
613 | break; | |
614 | } | |
615 | ||
616 | if (psDirData != NULL) | |
617 | { | |
618 | printf("Expected FileName = [%s], FileType = [%d].\n", UVFS_DIRENTRYATTR_NAMEPTR(psDirData), psDirData->dea_attrs.fa_type); | |
619 | ||
620 | //TBD - When getAttr will work need to change the compare to getAttr vs ReadDirAttr | |
621 | if ( !HFSTest_CompareReadDir(psNewDirListEntry, psDirData, false) ) | |
622 | { | |
623 | iReadDirERR = EINVAL; | |
624 | bConRead = false; | |
625 | break; | |
626 | } | |
627 | assert(uDirIndex<uDirEntries); | |
628 | uDirIndex++; | |
629 | psDirData = (UVFSDirEntryAttr*) ((void*) psDirData + sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH); | |
630 | } | |
631 | ||
632 | uBufCurOffset += UVFS_DIRENTRY_RECLEN(strlen(psNewDirListEntry->de_name)); | |
633 | } | |
634 | } | |
635 | } while( bConRead && (iReadDirERR != UVFS_READDIR_EOF_REACHED) ); | |
636 | ||
637 | if ( puBuffer ) free( puBuffer ); | |
638 | ||
639 | if(iReadDirERR == UVFS_READDIR_EOF_REACHED) | |
640 | iReadDirERR = 0; | |
641 | ||
642 | if ( psDirData ) | |
643 | assert(uDirIndex==uDirEntries); | |
644 | ||
645 | return iReadDirERR; | |
646 | } | |
647 | ||
648 | static int | |
649 | ReadDirAttr( UVFSFileNode psNode, UVFSDirEntryAttr * psReadDirTestsData, uint32_t uDirEntries) | |
650 | { | |
651 | uint32_t uBufferSize = 1000; | |
652 | uint8_t* puBuffer = malloc(uBufferSize); | |
653 | if ( puBuffer == NULL ) | |
654 | { | |
655 | return ENOMEM; | |
656 | } | |
657 | ||
658 | uint64_t uCookie = 0; | |
659 | uint64_t uVerifier = UVFS_DIRCOOKIE_VERIFIER_INITIAL; | |
660 | bool bConRead = true; | |
661 | size_t outLen = 0; | |
662 | int iReadDirERR = 0; | |
663 | uint32_t uDirIndex = 0; | |
664 | UVFSDirEntryAttr* psReadDir = psReadDirTestsData; | |
665 | ||
666 | do { | |
667 | ||
668 | uint32_t uBufCurOffset = 0; | |
669 | ||
670 | memset(puBuffer, 0, uBufferSize); | |
671 | ||
672 | iReadDirERR = HFS_fsOps.fsops_readdirattr (psNode, puBuffer, uBufferSize, uCookie, &outLen, &uVerifier); | |
673 | if ( (iReadDirERR != 0 && iReadDirERR != UVFS_READDIR_EOF_REACHED) || (outLen == 0) ) | |
674 | { | |
675 | bConRead = false; | |
676 | } | |
677 | else | |
678 | { | |
679 | //Go over all entries in the list and check if we got to the end of the directory | |
680 | bool bEndOfDirectoryList = false; | |
681 | ||
682 | while ( !bEndOfDirectoryList && iReadDirERR != UVFS_READDIR_EOF_REACHED ) | |
683 | { | |
684 | UVFSDirEntryAttr* psNewDirListEntry = (UVFSDirEntryAttr*) &puBuffer[uBufCurOffset]; | |
685 | uCookie = psNewDirListEntry->dea_nextcookie; | |
686 | //We found all the files in the root directory | |
687 | if ( ( psNewDirListEntry->dea_nextcookie == UVFS_DIRCOOKIE_EOF ) || ( psNewDirListEntry->dea_nextrec == 0 ) ) | |
688 | { | |
689 | bEndOfDirectoryList = true; | |
690 | } | |
691 | ||
692 | printf("Found FileName = [%s], FileID = [%llu], FileSize = [%llu].\n", UVFS_DIRENTRYATTR_NAMEPTR(psNewDirListEntry), psNewDirListEntry->dea_attrs.fa_fileid, psNewDirListEntry->dea_attrs.fa_size); | |
693 | ||
694 | if (psReadDir != NULL) | |
695 | { | |
696 | printf("Expected FileName = [%s], FileType = [%d].\n", UVFS_DIRENTRYATTR_NAMEPTR(psReadDir), psReadDir->dea_attrs.fa_type); | |
697 | ||
698 | //TBD - When getAttr will work need to change the compare to getAttr vs ReadDirAttr | |
699 | if ( !HFSTest_CompareReadDir((void*)psNewDirListEntry, psReadDir, true) ) | |
700 | { | |
701 | iReadDirERR = EINVAL; | |
702 | bConRead = false; | |
703 | break; | |
704 | } | |
705 | assert( uDirIndex < uDirEntries ); | |
706 | uDirIndex++; | |
707 | psReadDir = (UVFSDirEntryAttr*) ((void*) psReadDir + sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH); | |
708 | } | |
709 | ||
710 | uBufCurOffset += UVFS_DIRENTRYATTR_RECLEN(psNewDirListEntry, strlen(UVFS_DIRENTRYATTR_NAMEPTR(psNewDirListEntry))); | |
711 | } | |
712 | } | |
713 | } while( bConRead && (iReadDirERR != UVFS_READDIR_EOF_REACHED) ); | |
714 | ||
715 | if ( puBuffer ) | |
716 | free( puBuffer ); | |
717 | ||
718 | if(iReadDirERR == UVFS_READDIR_EOF_REACHED) | |
719 | iReadDirERR = 0; | |
720 | ||
721 | if (psReadDir != NULL) | |
722 | assert( uDirIndex == uDirEntries ); | |
723 | ||
724 | return iReadDirERR; | |
725 | } | |
726 | ||
727 | static int | |
728 | GetAttrAndCompare(UVFSFileNode FileNode,UVFSFileAttributes* sInAttrs) | |
729 | { | |
730 | int error =0; | |
731 | UVFSFileAttributes sOutAttrs; | |
732 | error = HFS_fsOps.fsops_getattr(FileNode, &sOutAttrs); | |
733 | if (error) | |
734 | { | |
735 | printf("Failed in get attr with err [%d]\n",error); | |
736 | return error; | |
737 | } | |
738 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_SIZE) | |
739 | if (sOutAttrs.fa_size != sInAttrs->fa_size) | |
740 | goto fail; | |
741 | ||
742 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_MODE) | |
743 | if (sOutAttrs.fa_mode != sInAttrs->fa_mode) | |
744 | goto fail; | |
745 | ||
746 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_BSD_FLAGS) | |
747 | if (sOutAttrs.fa_bsd_flags != sInAttrs->fa_bsd_flags) | |
748 | goto fail; | |
749 | ||
750 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_ATIME) | |
751 | if (CMP_TIMES(sOutAttrs.fa_atime,sInAttrs->fa_atime)) | |
752 | goto fail; | |
753 | ||
754 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_MTIME) | |
755 | if (CMP_TIMES(sOutAttrs.fa_atime,sInAttrs->fa_atime)) | |
756 | goto fail; | |
757 | ||
758 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_CTIME) | |
759 | if (CMP_TIMES(sOutAttrs.fa_ctime, sInAttrs->fa_ctime)) | |
760 | goto fail; | |
761 | ||
762 | if (sInAttrs->fa_validmask & UVFS_FA_VALID_BIRTHTIME) | |
763 | if (CMP_TIMES(sOutAttrs.fa_birthtime, sInAttrs->fa_birthtime)) | |
764 | goto fail; | |
765 | ||
766 | goto out; | |
767 | ||
768 | fail: | |
769 | error = 1; | |
770 | out: | |
771 | if (error) printf("Failed in compare attr\n"); | |
772 | return error; | |
773 | } | |
774 | ||
775 | static int | |
776 | SetAttrChangeSize(UVFSFileNode FileNode,uint64_t uNewSize) | |
777 | { | |
778 | int error =0; | |
779 | UVFSFileAttributes sInAttrs; | |
780 | UVFSFileAttributes sOutAttrs; | |
781 | memset(&sInAttrs,0,sizeof(UVFSFileAttributes)); | |
782 | sInAttrs.fa_validmask |= UVFS_FA_VALID_SIZE; | |
783 | sInAttrs.fa_size = uNewSize; | |
784 | ||
785 | error = HFS_fsOps.fsops_setattr( FileNode, &sInAttrs , &sOutAttrs ); | |
786 | ||
787 | error = GetAttrAndCompare(FileNode,&sInAttrs); | |
788 | ||
789 | return error; | |
790 | } | |
791 | ||
792 | static int | |
793 | SetAttrChangeMode(UVFSFileNode FileNode,uint32_t uNewMode) | |
794 | { | |
795 | int error =0; | |
796 | UVFSFileAttributes sInAttrs; | |
797 | UVFSFileAttributes sOutAttrs; | |
798 | memset(&sInAttrs,0,sizeof(UVFSFileAttributes)); | |
799 | sInAttrs.fa_validmask |= UVFS_FA_VALID_MODE; | |
800 | sInAttrs.fa_mode = uNewMode; | |
801 | ||
802 | error = HFS_fsOps.fsops_setattr( FileNode, &sInAttrs , &sOutAttrs ); | |
803 | ||
804 | return error; | |
805 | } | |
806 | ||
807 | static int | |
808 | SetAttrChangeUidGid(UVFSFileNode FileNode, uint32_t uNewUid, uint32_t uNewGid) | |
809 | { | |
810 | int error =0; | |
811 | UVFSFileAttributes sInAttrs; | |
812 | UVFSFileAttributes sOutAttrs; | |
813 | memset(&sInAttrs,0,sizeof(UVFSFileAttributes)); | |
814 | sInAttrs.fa_validmask |= UVFS_FA_VALID_UID; | |
815 | sInAttrs.fa_validmask |= UVFS_FA_VALID_GID; | |
816 | sInAttrs.fa_uid = uNewUid; | |
817 | sInAttrs.fa_gid = uNewGid; | |
818 | ||
819 | error = HFS_fsOps.fsops_setattr( FileNode, &sInAttrs , &sOutAttrs ); | |
820 | ||
821 | return error; | |
822 | } | |
823 | ||
824 | static int | |
825 | SetAttrChangeAtimeMtime(UVFSFileNode FileNode) | |
826 | { | |
827 | int error =0; | |
828 | UVFSFileAttributes sInAttrs; | |
829 | UVFSFileAttributes sOutAttrs; | |
830 | ||
831 | error = HFS_fsOps.fsops_getattr(FileNode, &sOutAttrs); | |
832 | if (error) | |
833 | { | |
834 | printf("Failed in get attr (1) with err [%d]\n",error); | |
835 | return error; | |
836 | } | |
837 | ||
838 | memset(&sInAttrs,0,sizeof(UVFSFileAttributes)); | |
839 | sInAttrs.fa_validmask |= UVFS_FA_VALID_ATIME; | |
840 | sInAttrs.fa_validmask |= UVFS_FA_VALID_MTIME; | |
841 | sInAttrs.fa_atime.tv_sec = sOutAttrs.fa_atime.tv_sec + 90000000; | |
842 | sInAttrs.fa_mtime.tv_sec = sOutAttrs.fa_mtime.tv_sec + 90000000; | |
843 | ||
844 | error = HFS_fsOps.fsops_setattr( FileNode, &sInAttrs , &sOutAttrs ); | |
845 | ||
846 | if (error) | |
847 | { | |
848 | printf("Failed to set attr to change atime and mtime err [%d]", error); | |
849 | return error; | |
850 | } | |
851 | error = HFS_fsOps.fsops_getattr(FileNode, &sOutAttrs); | |
852 | if (error) | |
853 | { | |
854 | printf("Failed in get attr (2) with err [%d]\n",error); | |
855 | return error; | |
856 | } | |
857 | ||
858 | if ( (sOutAttrs.fa_atime.tv_sec != sInAttrs.fa_atime.tv_sec) || (sOutAttrs.fa_mtime.tv_sec != sInAttrs.fa_mtime.tv_sec) ) | |
859 | { | |
860 | printf("Failed to update time!\n"); | |
861 | error = 1; | |
862 | } | |
863 | return error; | |
864 | } | |
865 | ||
866 | /*******************************************/ | |
867 | /*******************************************/ | |
868 | /*******************************************/ | |
869 | // Predefined Tests START. | |
870 | /*******************************************/ | |
871 | /*******************************************/ | |
872 | /*******************************************/ | |
873 | ||
874 | #define HFS_TEST_PREFIX "RUN_HFS_TESTS" | |
875 | #define HFS_RUN_FSCK "RUN_FSCK" | |
876 | #define HFS_DMGS_FOLDER "/Volumes/SSD_Shared/FS_DMGs/" | |
877 | #define TEMP_DMG "/tmp/hfstester.dmg" | |
878 | #define TEMP_DMG_SPARSE "/tmp/hfstester.dmg.sparseimage" | |
879 | #define TEMP_DMG_BKUP "/tmp/hfstester_bkup.dmg" | |
880 | #define TEMP_DMG_BKUP_SPARSE "/tmp/hfstester_bkup.dmg.sparseimage" | |
881 | #define TEMP_DEV_PATH "/tmp/dev_path.txt" | |
882 | #define TEMP_DEV_PATH2 "/tmp/dev_path2.txt" | |
883 | #define TEMP_DEV_PATH3 "/tmp/dev_path3.txt" | |
884 | #define CREATE_SPARSE_VOLUME "CREATE_SPARSE_VOLUME" | |
885 | #define CREATE_HFS_DMG "CREATE_HFS_DMG" | |
886 | ||
887 | #define MAX_CMN_LEN (1024*2) | |
888 | ||
889 | typedef int (*test_hander_t)( UVFSFileNode RootNode ); | |
890 | ||
891 | char pcLastDevPathName[50] = {0}; | |
892 | char pcDevPath[50] = {0}; | |
893 | char pcDevNum[50] = {0}; | |
894 | char gpcResultsFolder[256] = {0}; | |
895 | ||
896 | static int | |
897 | HFSTest_PrepareEnv(TestData_S *psTestData ) | |
898 | { | |
899 | int iErr = 0; | |
900 | bool bMountedAlready = false; | |
901 | char* pcCmd = malloc(MAX_CMN_LEN); | |
902 | assert(pcCmd); | |
903 | ||
904 | // Remove old dmg if exist. | |
905 | strcpy(pcCmd, "rm -rf "); | |
906 | strcat(pcCmd, TEMP_DMG" "TEMP_DEV_PATH" "TEMP_DEV_PATH2" "TEMP_DMG_SPARSE); | |
907 | #if HFS_CRASH_TEST | |
908 | if (psTestData->eCrashID) { | |
909 | strcat(pcCmd, " "TEMP_DMG_BKUP" "TEMP_DMG_BKUP_SPARSE); | |
910 | } | |
911 | #endif | |
912 | printf("Execute %s:\n", pcCmd); | |
913 | system(pcCmd); | |
914 | ||
915 | if (!strcmp(CREATE_SPARSE_VOLUME, psTestData->pcDMGPath)) { | |
916 | // Create a spase volume | |
917 | psTestData->bSparseImage = true; | |
918 | strcpy(pcCmd, "hdiutil create -ov -size 20G -type SPARSE -layout NONE "); | |
919 | strcat(pcCmd, TEMP_DMG); | |
920 | printf("Execute %s:\n", pcCmd); | |
921 | iErr = system( pcCmd ); | |
922 | if ( iErr != 0 ) | |
923 | { | |
924 | exit(-1); | |
925 | } | |
926 | strcpy(pcCmd, "hdiutil attach -nomount "); | |
927 | strcat(pcCmd, TEMP_DMG_SPARSE" > "TEMP_DEV_PATH); | |
928 | printf("Execute %s:\n", pcCmd); | |
929 | iErr = system( pcCmd ); | |
930 | if ( iErr != 0 ) | |
931 | { | |
932 | exit(-1); | |
933 | } | |
934 | bMountedAlready = true; | |
935 | ||
936 | // Extract disk number (disk??) | |
937 | strcpy(pcCmd, "cat "TEMP_DEV_PATH" | sed 's/\\/dev\\/disk\\([0-9]*\\)/\\1/' | awk '{print $1}' > "TEMP_DEV_PATH2); | |
938 | printf("Execute %s:\n", pcCmd); | |
939 | iErr = system( pcCmd ); | |
940 | if ( iErr != 0 ) | |
941 | { | |
942 | exit(-1); | |
943 | } | |
944 | FILE *psCat = fopen(TEMP_DEV_PATH2, "r"); | |
945 | fgets(pcLastDevPathName, sizeof(pcLastDevPathName), psCat); | |
946 | pclose(psCat); | |
947 | pcLastDevPathName[strlen(pcLastDevPathName)-1] = '\0'; | |
948 | ||
949 | sprintf(pcCmd, "newfs_hfs -v SparsedVolume -J /dev/disk%s ", pcLastDevPathName); | |
950 | printf("Execute %s:\n", pcCmd); | |
951 | iErr = system( pcCmd ); | |
952 | if ( iErr != 0 ) | |
953 | { | |
954 | exit(-1); | |
955 | } | |
956 | strcpy(pcDevPath, "/dev/rdisk"); | |
957 | strcat(pcDevPath, pcLastDevPathName); | |
958 | printf("%s\n", pcDevPath); | |
959 | pcDevNum[0] = '\0'; | |
960 | ||
961 | } else if (!strcmp(CREATE_HFS_DMG, psTestData->pcDMGPath)) { | |
962 | // No dmg filename provided. Create one: | |
963 | strcpy(pcCmd, "hdiutil create -size 20G -fs HFS+ -volname TwentyGigDmg "); | |
964 | strcat(pcCmd, TEMP_DMG); | |
965 | printf("Execute %s:\n", pcCmd); | |
966 | iErr = system( pcCmd ); | |
967 | if ( iErr != 0 ) | |
968 | { | |
969 | exit(-1); | |
970 | } | |
971 | ||
972 | } else if (psTestData->pcDMGPath[0] == '\0') { | |
973 | // No dmg filename provided. Create one: | |
974 | strcpy(pcCmd, "hdiutil create -size 20G -fs HFS+J -volname TwentyGigJournalDmg "); | |
975 | strcat(pcCmd, TEMP_DMG); | |
976 | printf("Execute %s:\n", pcCmd); | |
977 | iErr = system( pcCmd ); | |
978 | if ( iErr != 0 ) | |
979 | { | |
980 | exit(-1); | |
981 | } | |
982 | } else { | |
983 | // use dmg from provided path | |
984 | psTestData->bSparseImage = (strstr(psTestData->pcDMGPath, ".sparseimage") != NULL); | |
985 | // Copy dmg to tmp folder | |
986 | strcpy(pcCmd, "cp "); | |
987 | strcat(pcCmd, psTestData->pcDMGPath); | |
988 | strcat(pcCmd, " "); | |
989 | if (psTestData->bSparseImage) { | |
990 | strcat(pcCmd, TEMP_DMG_SPARSE); | |
991 | } else { | |
992 | strcat(pcCmd, TEMP_DMG); | |
993 | } | |
994 | printf("Execute %s:\n", pcCmd); | |
995 | iErr = system( pcCmd ); | |
996 | if ( iErr != 0 ) | |
997 | { | |
998 | exit(-1); | |
999 | } | |
1000 | } | |
1001 | ||
1002 | if (!bMountedAlready) { | |
1003 | // Attach DMG. | |
1004 | strcpy(pcCmd, "hdiutil attach -nomount "); | |
1005 | if (psTestData->bSparseImage) { | |
1006 | strcat(pcCmd, TEMP_DMG_SPARSE); | |
1007 | } else { | |
1008 | strcat(pcCmd, TEMP_DMG); | |
1009 | } | |
1010 | strcat(pcCmd," > "); | |
1011 | strcat(pcCmd, TEMP_DEV_PATH); | |
1012 | printf("Execute %s:\n", pcCmd); | |
1013 | iErr = system( pcCmd ); | |
1014 | if ( iErr != 0 ) | |
1015 | { | |
1016 | exit(-1); | |
1017 | } | |
1018 | ||
1019 | // Do we have multiple partitions? | |
1020 | strcpy(pcCmd, "cat "TEMP_DEV_PATH" | grep Apple_HFS > "TEMP_DEV_PATH2); | |
1021 | printf("Execute %s:\n", pcCmd); | |
1022 | int iSinglePartition = system( pcCmd ); | |
1023 | ||
1024 | if (iSinglePartition) { | |
1025 | // Extract disk number (disk??) | |
1026 | strcpy(pcCmd, "cat "TEMP_DEV_PATH" | sed 's/\\/dev\\/disk\\([0-9]*\\)/\\1/' | awk '{print $1}' > "TEMP_DEV_PATH2); | |
1027 | printf("Execute %s:\n", pcCmd); | |
1028 | iErr = system( pcCmd ); | |
1029 | if ( iErr != 0 ) | |
1030 | { | |
1031 | exit(-1); | |
1032 | } | |
1033 | FILE *psCat = fopen(TEMP_DEV_PATH2, "r"); | |
1034 | fgets(pcLastDevPathName, sizeof(pcLastDevPathName), psCat); | |
1035 | pclose(psCat); | |
1036 | pcLastDevPathName[strlen(pcLastDevPathName)-1] = '\0'; | |
1037 | ||
1038 | // Generate the full path | |
1039 | pcDevNum[0] = '\0'; | |
1040 | strcpy(pcDevPath, "/dev/rdisk"); | |
1041 | strcat(pcDevPath, pcLastDevPathName); | |
1042 | printf("%s\n", pcDevPath); | |
1043 | ||
1044 | } else { // Multilpe partitions | |
1045 | // Extract disk number (disk??) | |
1046 | strcpy(pcCmd, "cat "TEMP_DEV_PATH" | grep Apple_HFS | sed 's/\\/dev\\/disk\\([0-9]*\\)s[0-9]*/\\1/' | awk '{print $1}' > "TEMP_DEV_PATH2); | |
1047 | printf("Execute %s:\n", pcCmd); | |
1048 | iErr = system( pcCmd ); | |
1049 | if ( iErr != 0 ) | |
1050 | { | |
1051 | exit(-1); | |
1052 | } | |
1053 | FILE *psCat = fopen(TEMP_DEV_PATH2, "r"); | |
1054 | fgets(pcLastDevPathName, sizeof(pcLastDevPathName), psCat); | |
1055 | pclose(psCat); | |
1056 | pcLastDevPathName[strlen(pcLastDevPathName)-1] = '\0'; | |
1057 | ||
1058 | // Extract s number (s??) | |
1059 | strcpy(pcCmd, "cat "TEMP_DEV_PATH" | grep Apple_HFS | sed 's/\\/dev\\/disk[0-9]*s\\([0-9]*\\)/\\1/' | awk '{print $1}' > "TEMP_DEV_PATH3); | |
1060 | printf("Execute %s:\n", pcCmd); | |
1061 | iErr = system( pcCmd ); | |
1062 | if ( iErr != 0 ) | |
1063 | { | |
1064 | exit(-1); | |
1065 | } | |
1066 | psCat = fopen(TEMP_DEV_PATH3, "r"); | |
1067 | fgets(pcDevNum, sizeof(pcDevNum), psCat); | |
1068 | pclose(psCat); | |
1069 | pcDevNum[strlen(pcDevNum)-1] = '\0'; | |
1070 | ||
1071 | // Generate the full path | |
1072 | strcpy(pcDevPath, "/dev/rdisk"); | |
1073 | strcat(pcDevPath, pcLastDevPathName); | |
1074 | strcat(pcDevPath, "s"); | |
1075 | strcat(pcDevPath, pcDevNum); | |
1076 | printf("%s\n", pcDevPath); | |
1077 | } | |
1078 | ||
1079 | } | |
1080 | ||
1081 | // Open file. | |
1082 | printf("pcDevPath is %s\n", pcDevPath); | |
1083 | int iFD = open( pcDevPath, O_RDWR ); | |
1084 | if ( iFD < 0 ) | |
1085 | { | |
1086 | printf("Failed to open %s\n", pcDevPath); | |
1087 | exit(EBADF); | |
1088 | } | |
1089 | ||
1090 | free(pcCmd); | |
1091 | ||
1092 | return iFD; | |
1093 | } | |
1094 | ||
1095 | static void | |
1096 | HFSTest_DestroyEnv(__unused int iFD ) | |
1097 | { | |
1098 | int iErr = 0; | |
1099 | char* pcCmd = malloc(MAX_CMN_LEN); | |
1100 | assert(pcCmd); | |
1101 | ||
1102 | // Detach DMG. | |
1103 | memset(pcCmd, 0, MAX_CMN_LEN); | |
1104 | strcat(pcCmd, "hdiutil detach /dev/disk"); | |
1105 | strcat(pcCmd, pcLastDevPathName); | |
1106 | printf("Execute %s:\n", pcCmd); | |
1107 | iErr = system(pcCmd); | |
1108 | if ( iErr != 0 ) | |
1109 | { | |
1110 | exit(-1); | |
1111 | } | |
1112 | ||
1113 | // Remove old dmg if exist. | |
1114 | memset(pcCmd, 0, MAX_CMN_LEN); | |
1115 | strcat(pcCmd, "rm -rf "); | |
1116 | strcat(pcCmd, TEMP_DEV_PATH); | |
1117 | strcat(pcCmd, " "); | |
1118 | strcat(pcCmd, TEMP_DEV_PATH2); | |
1119 | printf("Execute %s:\n", pcCmd); | |
1120 | system(pcCmd); | |
1121 | ||
1122 | free(pcCmd); | |
1123 | } | |
1124 | ||
1125 | #if HFS_CRASH_TEST | |
1126 | void HFSTest_ClearCrashAbortFunctionArray(void) { | |
1127 | for(unsigned u=0; u<CRASH_ABORT_LAST; u++) | |
1128 | gpsCrashAbortFunctionArray[u] = NULL; | |
1129 | } | |
1130 | ||
1131 | typedef struct { | |
1132 | char pcMountedDev[512]; | |
1133 | char pcMountedVol[512]; | |
1134 | } MountedDrive_S; | |
1135 | ||
1136 | int HFSTest_KextMount(char *pcDmgFilename, MountedDrive_S *psMntd, bool bMount) { | |
1137 | int iErr = 0; | |
1138 | ||
1139 | char pcMountCmd[512] = {0}; | |
1140 | strcat( pcMountCmd, "hdiutil attach "); | |
1141 | if (!bMount) { | |
1142 | strcat( pcMountCmd, "-nomount "); | |
1143 | } | |
1144 | strcat( pcMountCmd, "-plist "); | |
1145 | strcat( pcMountCmd, pcDmgFilename ); | |
1146 | strcat( pcMountCmd, " > /tmp/tmp.txt "); | |
1147 | printf("Execute %s:\n", pcMountCmd); | |
1148 | iErr = system(pcMountCmd); | |
1149 | printf("*** %s returned %d\n", pcMountCmd,iErr); | |
1150 | if (iErr) | |
1151 | return(iErr); | |
1152 | ||
1153 | char pcCatCmd[512] = {0}; | |
1154 | strcat( pcCatCmd, "cat /tmp/tmp.txt | grep '\\/dev\\/disk[0-9]*' | tr -d '\\t' | sed 's/<string>//' | sed 's/<\\/string>//' > /tmp/dev.txt"); | |
1155 | printf("Execute %s:\n", pcCatCmd); | |
1156 | iErr = system(pcCatCmd); | |
1157 | printf("returned %d\n", iErr); | |
1158 | if (iErr) | |
1159 | return(iErr); | |
1160 | ||
1161 | psMntd->pcMountedDev[0] = '\0'; | |
1162 | FILE *psCat = fopen("/tmp/dev.txt", "r"); | |
1163 | fscanf(psCat, "%s", psMntd->pcMountedDev); | |
1164 | fclose(psCat); | |
1165 | printf("pcMountedDev is %s\n", psMntd->pcMountedDev); | |
1166 | ||
1167 | strcpy( pcCatCmd, "cat /tmp/tmp.txt | grep '\\/Volumes' | tr -d '\\t' | sed 's/<string>//' | sed 's/<\\/string>//' > /tmp/vol.txt"); | |
1168 | printf("Execute %s:\n", pcCatCmd); | |
1169 | iErr = system(pcCatCmd); | |
1170 | printf("returned %d\n", iErr); | |
1171 | if (iErr) | |
1172 | return(iErr); | |
1173 | ||
1174 | psCat = fopen("/tmp/vol.txt", "r"); | |
1175 | strcpy(psMntd->pcMountedVol, "\""); | |
1176 | fscanf(psCat, "%[^\n]", &psMntd->pcMountedVol[1]); | |
1177 | strcat(psMntd->pcMountedVol, "\""); | |
1178 | fclose(psCat); | |
1179 | printf("pcMountedVol is %s\n", psMntd->pcMountedVol); | |
1180 | ||
1181 | return(iErr); | |
1182 | } | |
1183 | ||
1184 | int HFSTest_KextFindAll(MountedDrive_S *psMntd, char *pcSearchFile) { | |
1185 | int iErr = 0; | |
1186 | ||
1187 | char pcFindCmd[512] = {0}; | |
1188 | sprintf(pcFindCmd, "find %s | tee /tmp/file-list.txt", psMntd->pcMountedVol); | |
1189 | printf("Execute %s :\n", pcFindCmd); | |
1190 | iErr = system(pcFindCmd); | |
1191 | printf("returned %d\n", iErr); | |
1192 | if (iErr) | |
1193 | return(iErr); | |
1194 | ||
1195 | sprintf(pcFindCmd, "cat /tmp/file-list.txt | grep %s", pcSearchFile); | |
1196 | printf("Execute %s :\n", pcFindCmd); | |
1197 | iErr = system(pcFindCmd); | |
1198 | printf("returned %d\n", iErr); | |
1199 | if (iErr) | |
1200 | return(iErr); | |
1201 | ||
1202 | return(iErr); | |
1203 | } | |
1204 | ||
1205 | int HFSTest_KextCount(MountedDrive_S *psMntd, char *pcSearchFile, uint32_t *puCount) { | |
1206 | int iErr = 0; | |
1207 | ||
1208 | char pcFindCmd[512] = {0}; | |
1209 | sprintf(pcFindCmd, "find %s | tee /tmp/file-list.txt", psMntd->pcMountedVol); | |
1210 | printf("Execute %s :\n", pcFindCmd); | |
1211 | iErr = system(pcFindCmd); | |
1212 | printf("returned %d\n", iErr); | |
1213 | if (iErr) | |
1214 | return(iErr); | |
1215 | ||
1216 | sprintf(pcFindCmd, "cat /tmp/file-list.txt | grep %s | wc -l > /tmp/word-count.txt", pcSearchFile); | |
1217 | printf("Execute %s :\n", pcFindCmd); | |
1218 | iErr = system(pcFindCmd); | |
1219 | printf("returned %d\n", iErr); | |
1220 | ||
1221 | FILE *psCat = fopen("/tmp/word-count.txt", "r"); | |
1222 | fscanf(psCat, "%u", puCount); | |
1223 | fclose(psCat); | |
1224 | ||
1225 | return(iErr); | |
1226 | } | |
1227 | ||
1228 | int HFSTest_KextUnMount(MountedDrive_S *psMntd) { | |
1229 | int iErr = 0; | |
1230 | ||
1231 | char pcUnMountCmd[512] = {0}; | |
1232 | strcat( pcUnMountCmd, "hdiutil detach "); | |
1233 | strcat( pcUnMountCmd, psMntd->pcMountedDev ); | |
1234 | printf("Execute %s:\n", pcUnMountCmd); | |
1235 | iErr = system(pcUnMountCmd); | |
1236 | printf("returned %d\n", iErr); | |
1237 | ||
1238 | return(iErr); | |
1239 | } | |
1240 | ||
1241 | int HFSTest_RunFsck(void) { | |
1242 | int iErr = 0; | |
1243 | char pcFsckCmd[512] = {0}; | |
1244 | ||
1245 | strcat( pcFsckCmd, "/System/Library/Filesystems/hfs.fs/Contents/Resources/fsck_hfs -fd -D 0x22 /dev/disk"); | |
1246 | strcat( pcFsckCmd, pcLastDevPathName ); | |
1247 | ||
1248 | if (pcDevNum[0] != '\0') { | |
1249 | strcat( pcFsckCmd, "s" ); | |
1250 | strcat( pcFsckCmd, pcDevNum); | |
1251 | } | |
1252 | printf("Execute %s:\n", pcFsckCmd); | |
1253 | ||
1254 | iErr = system( pcFsckCmd ); | |
1255 | ||
1256 | if (iErr) { | |
1257 | printf( "*** Fsck CMD failed! (%d) \n", iErr); | |
1258 | } else { | |
1259 | printf( "*** Fsck CMD succeeded!\n"); | |
1260 | } | |
1261 | ||
1262 | return(iErr); | |
1263 | } | |
1264 | ||
1265 | int HFSTest_RestartEnv(__unused int iFD) { | |
1266 | // Restart FS for following tests | |
1267 | HFS_fsOps.fsops_fini(); | |
1268 | ||
1269 | int iErr = HFS_fsOps.fsops_init(); | |
1270 | printf("Init err [%d]\n", iErr); | |
1271 | if (iErr) { | |
1272 | printf("Can't re-init (%d).\n", iErr); | |
1273 | } | |
1274 | return(iErr); | |
1275 | } | |
1276 | ||
1277 | int HFSTest_FailTestOnCrashAbort(__unused void *psTestData, CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, __unused pthread_t bSyncerThread) { | |
1278 | ||
1279 | printf("**** HFSTest_FailTestOnCrashAbort: eAbort (%u) \"%s\", iFD %d, psNode %p ****\n", eAbort, ppcCrashAbortDesc[eAbort], iFD, psNode); | |
1280 | ||
1281 | if (eAbort != CRASH_ABORT_NONE) { | |
1282 | panic("We should never get here!\n"); | |
1283 | return(-1); | |
1284 | } | |
1285 | ||
1286 | close(iFD); | |
1287 | // Seek & destroy | |
1288 | HFSTest_DestroyEnv( iFD ); | |
1289 | ||
1290 | return(0); | |
1291 | } | |
1292 | ||
1293 | static int HFSTest_ConfirmTestFolderExists(UVFSFileNode RootNode ) { | |
1294 | bool bFound; | |
1295 | ||
1296 | printf("HFSTest_ConfirmTestFolderExists:\n"); | |
1297 | bFound = false; | |
1298 | char pcFolderName[256]; | |
1299 | for(unsigned u=0; u<5; u++) { | |
1300 | sprintf(pcFolderName, "TestFolder_%u", u); | |
1301 | read_directory_and_search_for_name( RootNode, pcFolderName, &bFound, NULL, 0 ); | |
1302 | if (!bFound) { | |
1303 | printf("Error: Can not find replayed dir! (%s)\n", pcFolderName); | |
1304 | return -1; | |
1305 | } else { | |
1306 | printf("dir %s found after journal replay.\n", pcFolderName); | |
1307 | } | |
1308 | } | |
1309 | ||
1310 | return 0; | |
1311 | } | |
1312 | ||
1313 | static int HFSTest_ConfirmTestFolderDoesntExists(UVFSFileNode RootNode ) { | |
1314 | bool bFound; | |
1315 | ||
1316 | printf("HFSTest_ConfirmTestFolderExists:\n"); | |
1317 | bFound = false; | |
1318 | read_directory_and_search_for_name( RootNode, "TestFolder", &bFound, NULL, 0 ); | |
1319 | if (bFound) { | |
1320 | printf("dir \"TestFolder\" found.\n"); | |
1321 | return -1; | |
1322 | } | |
1323 | ||
1324 | printf("As expected, \"TestFolder\" was not found.\n"); | |
1325 | ||
1326 | return 0; | |
1327 | } | |
1328 | ||
1329 | int HFSTest_ValidateImageOnMac(__unused TestData_S *psTestData, char *pcDmgFilename, char *pcSearchItem, bool bFindNotFind) { | |
1330 | int iErr = 0; | |
1331 | MountedDrive_S sMntd; | |
1332 | ||
1333 | // Validate image with fsck + Kext mount | |
1334 | // attach -nomount | |
1335 | iErr = HFSTest_KextMount(pcDmgFilename, &sMntd, false); | |
1336 | if (iErr) { | |
1337 | printf("Can't HFSTest_KextMount(false).\n"); | |
1338 | goto exit; | |
1339 | } | |
1340 | ||
1341 | // Run FSCK | |
1342 | iErr = HFSTest_RunFsck(); | |
1343 | if (iErr) { | |
1344 | printf("Can't HFSTest_RunFsck.\n"); | |
1345 | goto exit; | |
1346 | } | |
1347 | ||
1348 | // detach | |
1349 | iErr = HFSTest_KextUnMount(&sMntd); | |
1350 | if (iErr) { | |
1351 | printf("Can't HFSTest_KextUnMount.\n"); | |
1352 | goto exit; | |
1353 | } | |
1354 | ||
1355 | // Validate that we can mount | |
1356 | iErr = HFSTest_KextMount(pcDmgFilename, &sMntd, true); | |
1357 | if (iErr) { | |
1358 | printf("Can't HFSTest_KextMount(true).\n"); | |
1359 | goto exit; | |
1360 | } | |
1361 | ||
1362 | if (pcSearchItem) { | |
1363 | char pcSearchPath[512] = {0}; | |
1364 | strcpy(pcSearchPath, sMntd.pcMountedVol); | |
1365 | strcat(pcSearchPath, pcSearchItem); | |
1366 | printf("pcSearchPath is %s\n", pcSearchPath); | |
1367 | ||
1368 | iErr = HFSTest_KextFindAll(&sMntd, pcSearchPath); | |
1369 | printf("grep returned %d.\n", iErr); | |
1370 | if (bFindNotFind == false) { | |
1371 | // Make sure string was not found on drive | |
1372 | if (iErr == 256) { | |
1373 | iErr = 0; | |
1374 | } else { | |
1375 | iErr = 1; | |
1376 | } | |
1377 | } | |
1378 | if (iErr) { | |
1379 | goto exit; | |
1380 | } | |
1381 | ||
1382 | // Count SymLinks | |
1383 | uint32_t uNumOfSymLinks = 0; | |
1384 | strcpy(pcSearchPath, "TestSymLink_thread"); | |
1385 | iErr = HFSTest_KextCount(&sMntd, pcSearchPath, &uNumOfSymLinks); | |
1386 | printf("*** found %u SymLinks\n", uNumOfSymLinks); | |
1387 | ||
1388 | // Count Files | |
1389 | uint32_t uNumOfFiles = 0; | |
1390 | strcpy(pcSearchPath, "file_Thread_"); | |
1391 | iErr = HFSTest_KextCount(&sMntd, pcSearchPath, &uNumOfFiles); | |
1392 | printf("*** found %u files\n", uNumOfFiles); | |
1393 | ||
1394 | } | |
1395 | ||
1396 | iErr = HFSTest_KextUnMount(&sMntd); | |
1397 | if (iErr) { | |
1398 | goto exit; | |
1399 | } | |
1400 | ||
1401 | exit: | |
1402 | return(iErr); | |
1403 | } | |
1404 | ||
1405 | int HFSTest_SaveDMG(void *pvTestData, CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, __unused pthread_t pSyncerThread) { | |
1406 | int iErr = 0; | |
1407 | TestData_S *psTestData = pvTestData; | |
1408 | ||
1409 | printf("**** HFSTest_SaveDMG: eAbort (%u) \"%s\", psNode %p ****\n", eAbort, ppcCrashAbortDesc[eAbort], psNode); | |
1410 | ||
1411 | close(iFD); | |
1412 | // Seek & destroy | |
1413 | HFSTest_DestroyEnv( iFD ); | |
1414 | ||
1415 | // Create a snapshot of the dmg | |
1416 | char pcDmgFilename[256]; | |
1417 | strcpy(pcDmgFilename, psTestData->bSparseImage?TEMP_DMG_SPARSE:TEMP_DMG); | |
1418 | ||
1419 | char pcCpCmd[512] = {0}; | |
1420 | strcat( pcCpCmd, "cp "); | |
1421 | strcat( pcCpCmd, pcDmgFilename); | |
1422 | if (psTestData->bSparseImage) { | |
1423 | strcat( pcCpCmd, " "TEMP_DMG_BKUP_SPARSE); | |
1424 | } else { | |
1425 | strcat( pcCpCmd, " "TEMP_DMG_BKUP); | |
1426 | } | |
1427 | printf("Execute %s:\n", pcCpCmd); | |
1428 | iErr = system(pcCpCmd); | |
1429 | printf("returned %d\n", iErr); | |
1430 | if (iErr) { | |
1431 | goto exit; | |
1432 | } | |
1433 | exit: | |
1434 | return(iErr); | |
1435 | } | |
1436 | ||
1437 | int HFSTest_CrashAbortAtRandom(void *pvTestData, CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, __unused pthread_t pSyncerThread) { | |
1438 | int iErr = 0; | |
1439 | TestData_S *psTestData = pvTestData; | |
1440 | ||
1441 | printf("**** HFSTest_CrashAbortAtRandom: eAbort (%u) \"%s\", psNode %p ****\n", eAbort, ppcCrashAbortDesc[eAbort], psNode); | |
1442 | ||
1443 | close(iFD); | |
1444 | // Seek & destroy | |
1445 | HFSTest_DestroyEnv( iFD ); | |
1446 | ||
1447 | // Create a snapshot of the crashed dmg | |
1448 | char pcDmgFilename[256]; | |
1449 | strcpy(pcDmgFilename, psTestData->bSparseImage?TEMP_DMG_SPARSE:TEMP_DMG); | |
1450 | ||
1451 | char pcCpCmd[512] = {0}; | |
1452 | strcat( pcCpCmd, "cp "); | |
1453 | strcat( pcCpCmd, pcDmgFilename); | |
1454 | if (psTestData->bSparseImage) { | |
1455 | strcat( pcCpCmd, " "TEMP_DMG_BKUP_SPARSE); | |
1456 | } else { | |
1457 | strcat( pcCpCmd, " "TEMP_DMG_BKUP); | |
1458 | } | |
1459 | printf("Execute %s:\n", pcCpCmd); | |
1460 | iErr = system(pcCpCmd); | |
1461 | printf("returned %d\n", iErr); | |
1462 | if (iErr) { | |
1463 | goto exit; | |
1464 | } | |
1465 | ||
1466 | bool bFindNotFind = true; | |
1467 | if (eAbort == CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER) { | |
1468 | bFindNotFind = true; | |
1469 | } else { | |
1470 | bFindNotFind = false; | |
1471 | } | |
1472 | ||
1473 | iErr = HFSTest_ValidateImageOnMac(psTestData, pcDmgFilename, "/TestFolder", bFindNotFind); | |
1474 | if (iErr) { | |
1475 | goto exit; | |
1476 | } | |
1477 | ||
1478 | exit: | |
1479 | return(iErr); | |
1480 | } | |
1481 | ||
1482 | int HFSTest_CrashAbortOnMkDir(void *pvTestData, CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, __unused pthread_t pSyncerThread) { | |
1483 | int iErr = 0; | |
1484 | TestData_S *psTestData = pvTestData; | |
1485 | ||
1486 | printf("**** HFSTest_CrashAbortOnMkDir: eAbort (%u) \"%s\", psNode %p ****\n", eAbort, ppcCrashAbortDesc[eAbort], psNode); | |
1487 | ||
1488 | close(iFD); | |
1489 | // Seek & destroy | |
1490 | HFSTest_DestroyEnv( iFD ); | |
1491 | ||
1492 | // Create a snapshot of the crashed dmg | |
1493 | char pcDmgFilename[256]; | |
1494 | strcpy(pcDmgFilename, psTestData->bSparseImage?TEMP_DMG_SPARSE:TEMP_DMG); | |
1495 | ||
1496 | char pcCpCmd[512] = {0}; | |
1497 | strcat( pcCpCmd, "cp "); | |
1498 | strcat( pcCpCmd, pcDmgFilename); | |
1499 | if (psTestData->bSparseImage) { | |
1500 | strcat( pcCpCmd, " "TEMP_DMG_BKUP_SPARSE); | |
1501 | } else { | |
1502 | strcat( pcCpCmd, " "TEMP_DMG_BKUP); | |
1503 | } | |
1504 | printf("Execute %s:\n", pcCpCmd); | |
1505 | iErr = system(pcCpCmd); | |
1506 | printf("returned %d\n", iErr); | |
1507 | if (iErr) { | |
1508 | goto exit; | |
1509 | } | |
1510 | ||
1511 | bool bFindNotFind = true; | |
1512 | if (eAbort == CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER) { | |
1513 | printf("CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER, expecting to find!\n"); | |
1514 | bFindNotFind = true; | |
1515 | } else { | |
1516 | bFindNotFind = false; | |
1517 | } | |
1518 | ||
1519 | iErr = HFSTest_ValidateImageOnMac(psTestData, pcDmgFilename, "/TestFolder", bFindNotFind); | |
1520 | if (iErr) { | |
1521 | goto exit; | |
1522 | } | |
1523 | ||
1524 | exit: | |
1525 | printf("HFSTest_CrashAbortOnMkDir returns %d\n", iErr); | |
1526 | return(iErr); | |
1527 | } | |
1528 | ||
1529 | int HFSTest_CrashAbort(void *pvTestData, CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, __unused pthread_t pSyncerThread) { | |
1530 | int iErr = 0; | |
1531 | TestData_S *psTestData = pvTestData; | |
1532 | ||
1533 | printf("**** HFSTest_CrashAbort: eAbort (%u) \"%s\", psNode %p ****\n", eAbort, ppcCrashAbortDesc[eAbort], psNode); | |
1534 | ||
1535 | close(iFD); | |
1536 | // Seek & destroy | |
1537 | HFSTest_DestroyEnv( iFD ); | |
1538 | ||
1539 | // Create a snapshot of the crashed dmg | |
1540 | char pcDmgFilename[256]; | |
1541 | strcpy(pcDmgFilename, psTestData->bSparseImage?TEMP_DMG_SPARSE:TEMP_DMG); | |
1542 | ||
1543 | char pcCpCmd[512] = {0}; | |
1544 | strcat( pcCpCmd, "cp "); | |
1545 | strcat( pcCpCmd, pcDmgFilename); | |
1546 | if (psTestData->bSparseImage) { | |
1547 | strcat( pcCpCmd, " "TEMP_DMG_BKUP_SPARSE); | |
1548 | } else { | |
1549 | strcat( pcCpCmd, " "TEMP_DMG_BKUP); | |
1550 | } | |
1551 | printf("Execute %s:\n", pcCpCmd); | |
1552 | iErr = system(pcCpCmd); | |
1553 | printf("returned %d\n", iErr); | |
1554 | if (iErr) { | |
1555 | goto exit; | |
1556 | } | |
1557 | ||
1558 | iErr = HFSTest_ValidateImageOnMac(psTestData, pcDmgFilename, NULL, false); | |
1559 | if (iErr) { | |
1560 | goto exit; | |
1561 | } | |
1562 | ||
1563 | exit: | |
1564 | return(iErr); | |
1565 | } | |
1566 | #endif | |
1567 | ||
1568 | static int | |
1569 | HFSTest_ScanID( UVFSFileNode RootNode ) | |
1570 | { | |
1571 | int iErr = 0; | |
1572 | printf("HFSTest_ScanID\n"); | |
1573 | __block uint64_t uScanIDFileIDArray; | |
1574 | __block char* pcScanIDPath = malloc(sizeof(char)* MAX_UTF8_NAME_LENGTH); | |
1575 | __block char* pcTempPath; | |
1576 | __block int iFoundRoot = 0; | |
1577 | ||
1578 | //Creating the following path | |
1579 | // /TestFolder/TestFolder2/TestFolder3/TestFolder4/TestFolder5/file.txt | |
1580 | UVFSFileNode TestFolder = NULL; | |
1581 | UVFSFileNode TestFolder2 = NULL; | |
1582 | UVFSFileNode TestFolder3 = NULL; | |
1583 | UVFSFileNode TestFolder4 = NULL; | |
1584 | UVFSFileNode TestFolder5 = NULL; | |
1585 | UVFSFileNode TestFile1 = NULL; | |
1586 | ||
1587 | iErr = CreateNewFolder( RootNode, &TestFolder, "TestFolder"); | |
1588 | printf("CreateNewFolder TestFolder err [%d]\n", iErr); | |
1589 | if (iErr) goto exit; | |
1590 | ||
1591 | iErr = CreateNewFolder( TestFolder, &TestFolder2, "TestFolder2"); | |
1592 | printf("CreateNewFolder TestFolder2 err [%d]\n", iErr); | |
1593 | if (iErr) goto exit; | |
1594 | ||
1595 | iErr = CreateNewFolder( TestFolder2, &TestFolder3, "TestFolder3"); | |
1596 | printf("CreateNewFolder TestFolder3 err [%d]\n", iErr); | |
1597 | if (iErr) goto exit; | |
1598 | ||
1599 | iErr = CreateNewFolder( TestFolder3, &TestFolder4, "TestFolder4"); | |
1600 | printf("CreateNewFolder TestFolder4 err [%d]\n", iErr); | |
1601 | if (iErr) goto exit; | |
1602 | ||
1603 | iErr = CreateNewFolder( TestFolder4, &TestFolder5, "TestFolder5"); | |
1604 | printf("CreateNewFolder TestFolder5 err [%d]\n", iErr); | |
1605 | if (iErr) goto exit; | |
1606 | ||
1607 | //Create new file with size 0 | |
1608 | iErr = CreateNewFile(TestFolder5, &TestFile1, "file.txt",512); | |
1609 | printf("Create file.txt in TestFolder5 err [%d]\n", iErr); | |
1610 | if (iErr) goto exit; | |
1611 | ||
1612 | LIFileAttributes_t FileAttr; | |
1613 | iErr = HFS_fsOps.fsops_getattr( TestFile1, &FileAttr); | |
1614 | if (iErr) goto exit; | |
1615 | ||
1616 | HFS_fsOps.fsops_reclaim(TestFile1); | |
1617 | ||
1618 | memset(pcScanIDPath, 0, MAX_UTF8_NAME_LENGTH); | |
1619 | uScanIDFileIDArray = FileAttr.fa_fileid; | |
1620 | ||
1621 | do | |
1622 | { | |
1623 | iErr = HFS_fsOps.fsops_scanids(RootNode, 0, &uScanIDFileIDArray, 1, | |
1624 | ^(__unused unsigned int fileid_index, const UVFSFileAttributes *file_attrs, const char *file_name) { | |
1625 | iFoundRoot = (file_attrs->fa_parentid == file_attrs->fa_fileid); | |
1626 | uScanIDFileIDArray = file_attrs->fa_parentid; | |
1627 | size_t uTmpPathSize = strlen(pcScanIDPath) + 1; | |
1628 | pcTempPath = malloc(uTmpPathSize); | |
1629 | strlcpy(pcTempPath, pcScanIDPath, uTmpPathSize); | |
1630 | strlcpy(pcScanIDPath, file_name, MAX_UTF8_NAME_LENGTH); | |
1631 | ||
1632 | if (uTmpPathSize != 1) { //For the first time we don't want to set / | |
1633 | strcat(pcScanIDPath,"/"); | |
1634 | strcat(pcScanIDPath,pcTempPath); | |
1635 | } | |
1636 | ||
1637 | free(pcTempPath); | |
1638 | }); | |
1639 | printf("HFS_fsOps.fsops_scanids err [%d]\n", iErr); | |
1640 | if (iErr) goto exit; | |
1641 | } while (!iFoundRoot); | |
1642 | ||
1643 | if (strcmp(pcScanIDPath,"/TestFolder/TestFolder2/TestFolder3/TestFolder4/TestFolder5/file.txt")) | |
1644 | { | |
1645 | iErr = EFAULT; | |
1646 | printf("Found path to file [%s]\n", pcScanIDPath); | |
1647 | } | |
1648 | ||
1649 | // ********************* Add Hard Links: ************************ | |
1650 | uint32_t uOriginalFileSize = 500000; | |
1651 | UVFSFileNode psFile = NULL; | |
1652 | size_t iActuallyWrite = 0; | |
1653 | size_t iActuallyRead = 0; | |
1654 | void* pvOutBuf = malloc(uOriginalFileSize); | |
1655 | void* pvInBuf = malloc(uOriginalFileSize); | |
1656 | ||
1657 | if (pvOutBuf == NULL || pvInBuf == NULL) { | |
1658 | printf("ERROR: HFSTest_ScanID: can't malloc (%p, %p)\n", pvOutBuf, pvInBuf); | |
1659 | iErr = -1; | |
1660 | goto exit; | |
1661 | } | |
1662 | ||
1663 | uint64_t* puOutBuf = pvOutBuf; | |
1664 | uint64_t* puInBuf = pvInBuf; | |
1665 | ||
1666 | // Create the original file with size 500,000 Bytes | |
1667 | iErr = CreateNewFile( RootNode, &psFile, "original_file.txt", uOriginalFileSize); | |
1668 | if (iErr) { | |
1669 | printf("ERROR: CreateNewFile return %d\n", iErr); | |
1670 | iErr = -1; | |
1671 | goto exit; | |
1672 | } | |
1673 | ||
1674 | // lets write 10,000 Bytes with 0xCD | |
1675 | memset(pvOutBuf, 0, uOriginalFileSize); | |
1676 | memset(pvInBuf, 0, uOriginalFileSize); | |
1677 | ||
1678 | memset(pvOutBuf, 0xCD, uOriginalFileSize); | |
1679 | ||
1680 | iErr = HFS_fsOps.fsops_write( psFile, 0, uOriginalFileSize, pvOutBuf, &iActuallyWrite ); | |
1681 | if (iErr) { | |
1682 | printf("ERROR: fsops_write return %d\n", iErr); | |
1683 | goto exit; | |
1684 | } | |
1685 | ||
1686 | iErr = HFS_fsOps.fsops_read( psFile, 0, uOriginalFileSize, pvInBuf, &iActuallyRead ); | |
1687 | if (iErr) { | |
1688 | printf("ERROR: fsops_read return %d\n", iErr); | |
1689 | goto exit; | |
1690 | } | |
1691 | ||
1692 | // Lets test it... | |
1693 | for ( uint64_t uIdx=0; uIdx<(uOriginalFileSize/sizeof(uint64_t)); uIdx++ ) { | |
1694 | if (puInBuf[uIdx] != puOutBuf[uIdx] ) { | |
1695 | printf("ERROR: puInBuf[uIdx] != puOutBuf[uIdx]\n"); | |
1696 | iErr = -1; | |
1697 | goto exit; | |
1698 | } | |
1699 | } | |
1700 | ||
1701 | UVFSFileNode psDirectory = NULL; | |
1702 | iErr = CreateNewFolder(RootNode,&psDirectory,"dir"); | |
1703 | if (iErr) { | |
1704 | printf("ERROR: CreateNewFolder return %d\n", iErr); | |
1705 | goto exit; | |
1706 | } | |
1707 | iErr = CreateHardLink(psFile,RootNode,"first_link.txt"); | |
1708 | if (iErr) { | |
1709 | printf("ERROR: CreateHardLink return %d\n", iErr); | |
1710 | goto exit; | |
1711 | } | |
1712 | iErr = CreateHardLink(psFile,psDirectory,"second_link.txt"); | |
1713 | if (iErr) { | |
1714 | printf("ERROR: CreateHardLink return %d\n", iErr); | |
1715 | goto exit; | |
1716 | } | |
1717 | ||
1718 | UVFSFileNode psFirstLink = NULL; | |
1719 | iErr = HFS_fsOps.fsops_lookup( psDirectory, "second_link.txt", &psFirstLink ); | |
1720 | if (iErr) goto exit; | |
1721 | ||
1722 | iErr = HFS_fsOps.fsops_getattr( psFirstLink, &FileAttr); | |
1723 | if (iErr) goto exit; | |
1724 | ||
1725 | uScanIDFileIDArray = FileAttr.fa_fileid; | |
1726 | memset(pcScanIDPath, 0, MAX_UTF8_NAME_LENGTH); | |
1727 | ||
1728 | HFS_fsOps.fsops_reclaim( psFile ); | |
1729 | HFS_fsOps.fsops_reclaim( psFirstLink ); | |
1730 | HFS_fsOps.fsops_reclaim( psDirectory ); | |
1731 | ||
1732 | // Now run SanID on hardlinks: | |
1733 | do { | |
1734 | iErr = HFS_fsOps.fsops_scanids(RootNode, 0, &uScanIDFileIDArray, 1, | |
1735 | ^(__unused unsigned int fileid_index, const UVFSFileAttributes *file_attrs, const char *file_name) { | |
1736 | iFoundRoot = (file_attrs->fa_parentid == file_attrs->fa_fileid); | |
1737 | uScanIDFileIDArray = file_attrs->fa_parentid; | |
1738 | size_t uTmpPathSize = strlen(pcScanIDPath) + 1; | |
1739 | pcTempPath = malloc(uTmpPathSize); | |
1740 | strlcpy(pcTempPath, pcScanIDPath, uTmpPathSize); | |
1741 | strlcpy(pcScanIDPath, file_name, MAX_UTF8_NAME_LENGTH); | |
1742 | ||
1743 | if (uTmpPathSize != 1) { //For the first time we don't want to set / | |
1744 | strcat(pcScanIDPath,"/"); | |
1745 | strcat(pcScanIDPath,pcTempPath); | |
1746 | } | |
1747 | ||
1748 | free(pcTempPath); | |
1749 | }); | |
1750 | printf("HFS_fsOps.fsops_scanids err [%d]\n", iErr); | |
1751 | if (iErr) goto exit; | |
1752 | } while (!iFoundRoot); | |
1753 | ||
1754 | if (strcmp(pcScanIDPath,"/original_file.txt")) | |
1755 | { | |
1756 | iErr = EFAULT; | |
1757 | printf("Found path to file [%s]\n", pcScanIDPath); | |
1758 | } | |
1759 | ||
1760 | exit: | |
1761 | free(pcScanIDPath); | |
1762 | ||
1763 | if (TestFile1) { | |
1764 | RemoveFile(TestFolder5,"file.txt"); | |
1765 | } | |
1766 | if (TestFolder5) { | |
1767 | HFS_fsOps.fsops_reclaim(TestFolder5); | |
1768 | RemoveFolder(TestFolder4,"TestFolder5"); | |
1769 | } | |
1770 | if (TestFolder4) { | |
1771 | HFS_fsOps.fsops_reclaim(TestFolder4); | |
1772 | RemoveFolder(TestFolder3,"TestFolder4"); | |
1773 | } | |
1774 | if (TestFolder3) { | |
1775 | HFS_fsOps.fsops_reclaim(TestFolder3); | |
1776 | RemoveFolder(TestFolder2,"TestFolder3"); | |
1777 | } | |
1778 | if (TestFolder2) { | |
1779 | HFS_fsOps.fsops_reclaim(TestFolder2); | |
1780 | RemoveFolder(TestFolder,"TestFolder2"); | |
1781 | } | |
1782 | if (TestFolder) { | |
1783 | HFS_fsOps.fsops_reclaim(TestFolder); | |
1784 | RemoveFolder(RootNode,"TestFolder"); | |
1785 | } | |
1786 | ||
1787 | return iErr; | |
1788 | } | |
1789 | ||
1790 | static int | |
1791 | HFSTest_Create( UVFSFileNode RootNode ) | |
1792 | { | |
1793 | int iErr = 0; | |
1794 | printf("HFSTest_Create\n"); | |
1795 | ||
1796 | UVFSFileNode TestFolder = NULL; | |
1797 | iErr = CreateNewFolder( RootNode, &TestFolder, "TestFolder"); | |
1798 | printf("CreateNewFolder err [%d]\n", iErr); | |
1799 | if (iErr) | |
1800 | return iErr; | |
1801 | ||
1802 | //Create new file with size 0 | |
1803 | UVFSFileNode TestFile1 = NULL; | |
1804 | CreateNewFile(TestFolder, &TestFile1, "TestFile",0); | |
1805 | printf("Create TestFile in TestFolder err [%d]\n", iErr); | |
1806 | if (iErr) | |
1807 | return iErr; | |
1808 | ||
1809 | //Create new file with size 512 | |
1810 | UVFSFileNode TestFile2 = NULL; | |
1811 | CreateNewFile(TestFolder, &TestFile2, "TestFile2",512); | |
1812 | printf("Create TestFile2 in TestFolder err [%d]\n", iErr); | |
1813 | if (iErr) | |
1814 | return iErr; | |
1815 | ||
1816 | uint32_t uEntrySize = sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH; | |
1817 | UVFSDirEntryAttr *psReadDirTestsData = malloc(2*uEntrySize); | |
1818 | if (psReadDirTestsData == NULL) | |
1819 | return ENOMEM; | |
1820 | ||
1821 | UVFSDirEntryAttr *psCurrentReadDirTestsData = psReadDirTestsData; | |
1822 | SetExpectedAttr("TestFile", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
1823 | iErr = HFS_fsOps.fsops_getattr( TestFile1, &psCurrentReadDirTestsData->dea_attrs ); | |
1824 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
1825 | SetExpectedAttr("TestFile2", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
1826 | iErr = HFS_fsOps.fsops_getattr( TestFile2, &psCurrentReadDirTestsData->dea_attrs ); | |
1827 | ||
1828 | // { | |
1829 | // {.pcTestName = "TestFile", .uTyppe = UVFS_FA_TYPE_FILE, .uSize = 0, .uNlink = 1, .uAllocatedSize = 0}, | |
1830 | // {.pcTestName = "TestFile2", .uTyppe = UVFS_FA_TYPE_FILE, .uSize = 512, .uNlink = 1, .uAllocatedSize = 4096}, | |
1831 | // }; | |
1832 | ||
1833 | iErr = ReadDirAttr(TestFolder, psReadDirTestsData, 2); | |
1834 | free(psReadDirTestsData); | |
1835 | printf("ReadDirAttr err [%d]\n", iErr); | |
1836 | if (iErr) | |
1837 | goto exit; | |
1838 | ||
1839 | // Remove File1 | |
1840 | iErr = RemoveFile(TestFolder,"TestFile"); | |
1841 | printf("Remove File TestFile from TestFolder err [%d]\n", iErr); | |
1842 | if (iErr) | |
1843 | goto exit; | |
1844 | ||
1845 | // Remove File2 | |
1846 | iErr = RemoveFile(TestFolder,"TestFile2"); | |
1847 | printf("Remove File TestFile2 from TestFolder err [%d]\n", iErr); | |
1848 | if (iErr) | |
1849 | goto exit; | |
1850 | ||
1851 | // Remove TestFolder | |
1852 | iErr = RemoveFolder(RootNode,"TestFolder"); | |
1853 | printf("Remove Folder TestFolder from Root err [%d]\n", iErr); | |
1854 | if (iErr) | |
1855 | goto exit; | |
1856 | ||
1857 | exit: | |
1858 | HFS_fsOps.fsops_reclaim(TestFolder); | |
1859 | HFS_fsOps.fsops_reclaim(TestFile1); | |
1860 | HFS_fsOps.fsops_reclaim(TestFile2); | |
1861 | return iErr; | |
1862 | } | |
1863 | ||
1864 | // This function tests the system behavior when deleting a very large defragmented file, | |
1865 | // which will cause the creation of a very large journal transaction and lots of BT buffers | |
1866 | static int HFSTest_DeleteAHugeDefragmentedFile_wJournal(UVFSFileNode RootNode) { | |
1867 | #define DHF_NUM_OF_FILES_TO_CREATE 1000 | |
1868 | #define DHF_HUGE_FILE_SIZE (15000000000ULL) // 15GBytes | |
1869 | #define DHF_SMALL_FILENAME "SmallFile" | |
1870 | #define DHF_HUGE_FILENAME "HugeFile" | |
1871 | ||
1872 | int iErr = 0; | |
1873 | ||
1874 | // Create many small files | |
1875 | char pcName[100] = {0}; | |
1876 | UVFSFileNode psNode; | |
1877 | for ( int i=0; i<DHF_NUM_OF_FILES_TO_CREATE; i++ ) { | |
1878 | sprintf(pcName, "%s_%u.txt", DHF_SMALL_FILENAME, i); | |
1879 | printf("Creating file %s\n", pcName); | |
1880 | if ( (iErr = CreateNewFile(RootNode, &psNode, pcName, 100)) != 0 ) { | |
1881 | printf("Failed to create file [%s]\n", pcName); | |
1882 | goto exit; | |
1883 | } | |
1884 | HFS_fsOps.fsops_reclaim(psNode); | |
1885 | } | |
1886 | ||
1887 | // delete every other file | |
1888 | for ( int i=0; i<DHF_NUM_OF_FILES_TO_CREATE; i+=2 ) { | |
1889 | sprintf(pcName, "%s_%u.txt", DHF_SMALL_FILENAME, i); | |
1890 | printf("Removing file %s\n", pcName); | |
1891 | if ( (iErr = RemoveFile(RootNode, pcName)) != 0 ) { | |
1892 | printf("Failed to remove file [%s]", pcName); | |
1893 | goto exit; | |
1894 | } | |
1895 | } | |
1896 | ||
1897 | // Create a huge file | |
1898 | sprintf(pcName, "%s.txt", DHF_HUGE_FILENAME); | |
1899 | printf("Creating huge file %s\n", pcName); | |
1900 | if ( (iErr = CreateNewFile(RootNode, &psNode, pcName, DHF_HUGE_FILE_SIZE)) != 0 ) { | |
1901 | printf("Failed to create file [%s]\n", pcName); | |
1902 | goto exit; | |
1903 | } | |
1904 | HFS_fsOps.fsops_reclaim(psNode); | |
1905 | ||
1906 | // Delete the huge defragmented file | |
1907 | sprintf(pcName, "%s.txt", DHF_HUGE_FILENAME);; | |
1908 | printf("Removing file %s\n", pcName); | |
1909 | if ( (iErr = RemoveFile(RootNode, pcName)) != 0 ) { | |
1910 | printf("Failed to remove file [%s]", pcName); | |
1911 | goto exit; | |
1912 | } | |
1913 | ||
1914 | exit: | |
1915 | return iErr; | |
1916 | } | |
1917 | ||
1918 | ||
1919 | static void *ReadWriteThread(void *pvArgs) { | |
1920 | int iErr = 0; | |
1921 | ||
1922 | RWThreadData_S *psThrdData = pvArgs; | |
1923 | UVFSFileNode psRootNode = psThrdData->psRootNode; | |
1924 | char pcName[100] = {0}; | |
1925 | char *pcFilenameFormat = "file_Thread_%u_OpCnt_%u_FileNum_%u_Len_%u.txt"; | |
1926 | ||
1927 | for(uint32_t uOpCnt=0; uOpCnt<MTRW_NUM_OF_OPERATIONS; uOpCnt++) { | |
1928 | ||
1929 | // Create files | |
1930 | for(uint32_t uNumOfFiles=0; uNumOfFiles<psThrdData->uNumOfFiles; uNumOfFiles++) { | |
1931 | ||
1932 | UVFSFileNode psNode; | |
1933 | uint64_t uLen = psThrdData->uFileSize * uNumOfFiles; | |
1934 | sprintf(pcName, pcFilenameFormat, psThrdData->uThreadNum, uOpCnt, uNumOfFiles, uLen); | |
1935 | printf("Creating file %s\n", pcName); | |
1936 | iErr = CreateNewFile(psRootNode, &psNode, pcName, uLen); | |
1937 | if (iErr) { | |
1938 | printf("Failed creating file %s with iErr %d.\n", pcName,iErr); | |
1939 | goto exit; | |
1940 | } | |
1941 | HFS_fsOps.fsops_reclaim(psNode); | |
1942 | } | |
1943 | ||
1944 | // Create SymLinks | |
1945 | UVFSFileNode *pOutNode = malloc(sizeof(UVFSFileNode) * psThrdData->uNumOfSymLinks); | |
1946 | uint32_t uSymLinkMode = UVFS_FA_MODE_USR(UVFS_FA_MODE_RWX) | UVFS_FA_MODE_GRP(UVFS_FA_MODE_R) | UVFS_FA_MODE_OTH(UVFS_FA_MODE_R | UVFS_FA_MODE_X); | |
1947 | for(uint32_t uNumOfSymLinks=0; uNumOfSymLinks<psThrdData->uNumOfSymLinks; uNumOfSymLinks++) { | |
1948 | ||
1949 | // Create Symlink | |
1950 | char pcSymLinkName[256] = {0}; | |
1951 | sprintf(pcSymLinkName, "TestSymLink_thread_%u_op_%u_symlink_%u", psThrdData->uThreadNum, uOpCnt, uNumOfSymLinks); | |
1952 | uint32_t uSymLinkSize = psThrdData->uSymLinkSize; | |
1953 | char *pcSymLinkContent = malloc(uSymLinkSize); | |
1954 | memset(pcSymLinkContent, 0, uSymLinkSize); | |
1955 | uint32_t uStampLen = sprintf(pcSymLinkContent, "/just/to/check/that/symlink/works/properly/thread/%u/op/%u/symlink_%u",psThrdData->uThreadNum, uOpCnt, uNumOfSymLinks); | |
1956 | assert(uSymLinkSize >= uStampLen); | |
1957 | for(uint32_t uStampCount=1; uSymLinkSize>(uStampCount+1)*uStampLen+1; uStampCount++) { | |
1958 | memcpy(pcSymLinkContent + uStampCount*uStampLen, pcSymLinkContent, uStampLen); | |
1959 | } | |
1960 | assert(strlen(pcSymLinkContent) + 1 <= uSymLinkSize); | |
1961 | ||
1962 | UVFSFileAttributes sAttr = {0}; | |
1963 | sAttr.fa_validmask = UVFS_FA_VALID_MODE; | |
1964 | sAttr.fa_type = UVFS_FA_TYPE_SYMLINK; | |
1965 | sAttr.fa_mode = uSymLinkMode; | |
1966 | ||
1967 | pOutNode[uNumOfSymLinks] = NULL; | |
1968 | printf("Creating Symlink %s\n", pcSymLinkName); | |
1969 | iErr = HFS_fsOps.fsops_symlink(psRootNode, pcSymLinkName, pcSymLinkContent, &sAttr, &pOutNode[uNumOfSymLinks] ); | |
1970 | if ( iErr != 0 ) { | |
1971 | printf( "fsops_symlink failed with eror code : %d\n", iErr ); | |
1972 | goto exit; | |
1973 | } | |
1974 | free(pcSymLinkContent); | |
1975 | } | |
1976 | ||
1977 | // Verify Symlink content | |
1978 | for(uint32_t uNumOfSymLinks=0; uNumOfSymLinks<psThrdData->uNumOfSymLinks; uNumOfSymLinks++) { | |
1979 | ||
1980 | uint32_t uSymLinkSize = psThrdData->uSymLinkSize; | |
1981 | char pcSymLinkName[256] = {0}; | |
1982 | sprintf(pcSymLinkName, "TestSymLink_thread_%u_op_%u_symlink_%u", psThrdData->uThreadNum, uOpCnt, uNumOfSymLinks); | |
1983 | char *pcSymLinkReadContent = malloc(uSymLinkSize); | |
1984 | memset(pcSymLinkReadContent, 0, uSymLinkSize); | |
1985 | size_t iActuallyRead; | |
1986 | ||
1987 | UVFSFileAttributes sOutAttr = {0}; | |
1988 | ||
1989 | printf("Reading Symlink %s\n", pcSymLinkName); | |
1990 | iErr = HFS_fsOps.fsops_readlink( pOutNode[uNumOfSymLinks], pcSymLinkReadContent, uSymLinkSize, &iActuallyRead, &sOutAttr ); | |
1991 | ||
1992 | if ( iErr != 0 ) { | |
1993 | printf( "fsops_readlink failed with eror code : %d\n", iErr ); | |
1994 | goto exit; | |
1995 | } | |
1996 | ||
1997 | char *pcSymLinkContent = malloc(uSymLinkSize); | |
1998 | memset(pcSymLinkContent, 0, uSymLinkSize); | |
1999 | uint32_t uStampLen = sprintf(pcSymLinkContent, "/just/to/check/that/symlink/works/properly/thread/%u/op/%u/symlink_%u",psThrdData->uThreadNum, uOpCnt, uNumOfSymLinks); | |
2000 | assert(uSymLinkSize >= uStampLen); | |
2001 | for(uint32_t uStampCount=1; uSymLinkSize>(uStampCount+1)*uStampLen+1; uStampCount++) { | |
2002 | memcpy(pcSymLinkContent + uStampCount*uStampLen, pcSymLinkContent, uStampLen); | |
2003 | } | |
2004 | ||
2005 | if ( memcmp( pcSymLinkContent, pcSymLinkReadContent, uSymLinkSize) != 0 ) { | |
2006 | printf( "Read bad symlink content\n" ); | |
2007 | iErr = -1; | |
2008 | goto exit; | |
2009 | } | |
2010 | ||
2011 | if ( sOutAttr.fa_mode != uSymLinkMode) { | |
2012 | printf( "Mode mismatch [%d != %d]\n", sOutAttr.fa_mode, uSymLinkMode); | |
2013 | iErr = -1; | |
2014 | goto exit; | |
2015 | } | |
2016 | ||
2017 | if ( sOutAttr.fa_type != UVFS_FA_TYPE_SYMLINK ) { | |
2018 | printf( "Type mismatch\n" ); | |
2019 | iErr = -1; | |
2020 | goto exit; | |
2021 | } | |
2022 | ||
2023 | HFS_fsOps.fsops_reclaim( pOutNode[uNumOfSymLinks] ); | |
2024 | free(pcSymLinkContent); | |
2025 | free(pcSymLinkReadContent); | |
2026 | } | |
2027 | free(pOutNode); | |
2028 | ||
2029 | // Remove files | |
2030 | for(uint32_t uNumOfFiles=0; uNumOfFiles<psThrdData->uNumOfFiles; uNumOfFiles++) { | |
2031 | uint64_t uLen = psThrdData->uFileSize * uNumOfFiles; | |
2032 | sprintf(pcName, pcFilenameFormat, psThrdData->uThreadNum, uOpCnt, uNumOfFiles, uLen); | |
2033 | printf("Removing file %s\n", pcName); | |
2034 | iErr = RemoveFile(psRootNode, pcName); | |
2035 | if (iErr) { | |
2036 | printf("Failed deleting file %s with iErr %d.\n", pcName, iErr); | |
2037 | goto exit; | |
2038 | } | |
2039 | } | |
2040 | ||
2041 | // Remove SymLinks | |
2042 | for(uint32_t uNumOfSymLinks=0; uNumOfSymLinks<psThrdData->uNumOfSymLinks; uNumOfSymLinks++) { | |
2043 | ||
2044 | char pcSymLinkName[256] = {0}; | |
2045 | sprintf(pcSymLinkName, "TestSymLink_thread_%u_op_%u_symlink_%u", psThrdData->uThreadNum, uOpCnt, uNumOfSymLinks); | |
2046 | ||
2047 | printf("Deleting Symlink %s\n", pcSymLinkName); | |
2048 | iErr = HFS_fsOps.fsops_remove(psRootNode, pcSymLinkName, NULL); | |
2049 | if ( iErr != 0 ) { | |
2050 | printf( "Failed to remove symlink %d\n", iErr ); | |
2051 | goto exit; | |
2052 | } | |
2053 | } | |
2054 | } | |
2055 | exit: | |
2056 | psThrdData->iRetVal = iErr; | |
2057 | return psThrdData; | |
2058 | } | |
2059 | ||
2060 | #if HFS_CRASH_TEST | |
2061 | static int MultiThreadedRW_wJournal_RandomCrash(UVFSFileNode psRootNode) { | |
2062 | int iErr = 0; | |
2063 | ||
2064 | pthread_attr_t sAttr; | |
2065 | pthread_attr_setdetachstate(&sAttr, PTHREAD_CREATE_JOINABLE); | |
2066 | pthread_attr_init(&sAttr); | |
2067 | pthread_t psExecThread[MTRW_NUM_OF_THREADS]; | |
2068 | RWThreadData_S pcThreadData[MTRW_NUM_OF_THREADS] = {{0}}; | |
2069 | for(uint32_t u = 0; u < MTRW_NUM_OF_THREADS; u++) { | |
2070 | pcThreadData[u].uThreadNum = u; | |
2071 | pcThreadData[u].psRootNode = psRootNode; | |
2072 | pcThreadData[u].uNumOfFiles = MTRW_NUM_OF_FILES*(u+1); | |
2073 | pcThreadData[u].uFileSize = MTRW_FILE_SIZE; | |
2074 | pcThreadData[u].uNumOfSymLinks = MTRW_NUM_OF_SYMLINKS*(u+1); | |
2075 | pcThreadData[u].uSymLinkSize = MTRW_SYMLINK_SIZE; | |
2076 | ||
2077 | iErr = pthread_create(&psExecThread[u], &sAttr, ReadWriteThread, &pcThreadData[u]); | |
2078 | if (iErr) { | |
2079 | printf("can't pthread_create\n"); | |
2080 | goto exit; | |
2081 | } | |
2082 | } | |
2083 | pthread_attr_destroy(&sAttr); | |
2084 | ||
2085 | time_t sTime; | |
2086 | srand((unsigned) time(&sTime)); | |
2087 | uint32_t uRandTime = 0; | |
2088 | if (guSyncerPeriod) { | |
2089 | uRandTime = rand() % (guSyncerPeriod * 150); | |
2090 | } else { | |
2091 | uRandTime = rand() % (15000); | |
2092 | } | |
2093 | printf("******* uRandTime is %u mS ******\n", uRandTime); | |
2094 | ||
2095 | uint32_t uAbortTime = uRandTime; // mSec | |
2096 | usleep(uAbortTime * 1000); | |
2097 | close(giFD); | |
2098 | printf("******* now: close(giFD) **************\n"); | |
2099 | ||
2100 | for(uint32_t u = 0; u < MTRW_NUM_OF_THREADS; u++) { | |
2101 | iErr = pthread_join(psExecThread[u], NULL); | |
2102 | if (iErr) { | |
2103 | printf("can't pthread_join\n"); | |
2104 | goto exit; | |
2105 | } | |
2106 | iErr = pcThreadData[u].iRetVal; | |
2107 | if (iErr) { | |
2108 | printf("Thread %u return error %d\n", u, iErr); | |
2109 | } | |
2110 | } | |
2111 | ||
2112 | exit: | |
2113 | return iErr; | |
2114 | ||
2115 | } | |
2116 | #endif | |
2117 | ||
2118 | static int HFSTest_MultiThreadedRW_wJournal(UVFSFileNode psRootNode) { | |
2119 | ||
2120 | int iErr = 0; | |
2121 | ||
2122 | pthread_attr_t sAttr; | |
2123 | pthread_attr_setdetachstate(&sAttr, PTHREAD_CREATE_JOINABLE); | |
2124 | pthread_attr_init(&sAttr); | |
2125 | pthread_t psExecThread[MTRW_NUM_OF_THREADS]; | |
2126 | RWThreadData_S pcThreadData[MTRW_NUM_OF_THREADS] = {{0}}; | |
2127 | for(uint32_t u = 0; u < MTRW_NUM_OF_THREADS; u++) { | |
2128 | pcThreadData[u].uThreadNum = u; | |
2129 | pcThreadData[u].psRootNode = psRootNode; | |
2130 | pcThreadData[u].uNumOfFiles = MTRW_NUM_OF_FILES*(u+1); | |
2131 | pcThreadData[u].uFileSize = MTRW_FILE_SIZE; | |
2132 | pcThreadData[u].uNumOfSymLinks = MTRW_NUM_OF_SYMLINKS; | |
2133 | pcThreadData[u].uSymLinkSize = MTRW_SYMLINK_SIZE/3; | |
2134 | ||
2135 | iErr = pthread_create(&psExecThread[u], &sAttr, ReadWriteThread, &pcThreadData[u]); | |
2136 | if (iErr) { | |
2137 | printf("can't pthread_create\n"); | |
2138 | goto exit; | |
2139 | } | |
2140 | } | |
2141 | pthread_attr_destroy(&sAttr); | |
2142 | ||
2143 | for(uint32_t u = 0; u < MTRW_NUM_OF_THREADS; u++) { | |
2144 | iErr = pthread_join(psExecThread[u], NULL); | |
2145 | if (iErr) { | |
2146 | printf("can't pthread_join\n"); | |
2147 | goto exit; | |
2148 | } | |
2149 | iErr = pcThreadData[u].iRetVal; | |
2150 | if (iErr) { | |
2151 | printf("Thread %u return error %d\n", u, iErr); | |
2152 | } | |
2153 | } | |
2154 | ||
2155 | exit: | |
2156 | return iErr; | |
2157 | } | |
2158 | ||
2159 | static int | |
2160 | HFSTest_Create1000Files( UVFSFileNode RootNode ) | |
2161 | { | |
2162 | #define CREATE_NUM_OF_FILES (1000) | |
2163 | #define FILE_NAME "Iamjustasimplefile_%d" | |
2164 | ||
2165 | int iErr = 0; | |
2166 | ||
2167 | char pcName[100] = {0}; | |
2168 | UVFSFileNode psNode; | |
2169 | for ( int i=0; i<CREATE_NUM_OF_FILES; i++ ) | |
2170 | { | |
2171 | sprintf(pcName, FILE_NAME, i); | |
2172 | printf("Creating file %s\n", pcName); | |
2173 | if ( (iErr = CreateNewFile(RootNode, &psNode, pcName, 0)) != 0 ) | |
2174 | { | |
2175 | printf("Failed to create file [%s]\n", pcName); | |
2176 | goto exit; | |
2177 | } | |
2178 | HFS_fsOps.fsops_reclaim(psNode); | |
2179 | } | |
2180 | ||
2181 | for ( int i=0; i<CREATE_NUM_OF_FILES; i++ ) | |
2182 | { | |
2183 | sprintf(pcName, FILE_NAME, i); | |
2184 | printf("Removing file %s\n", pcName); | |
2185 | if ( (iErr = RemoveFile(RootNode, pcName)) != 0 ) | |
2186 | { | |
2187 | printf("Failed to remove file [%s]", pcName); | |
2188 | goto exit; | |
2189 | } | |
2190 | } | |
2191 | ||
2192 | exit: | |
2193 | return iErr; | |
2194 | } | |
2195 | ||
2196 | static int | |
2197 | HFSTest_Rename( UVFSFileNode RootNode ) | |
2198 | { | |
2199 | int iErr = 0; | |
2200 | ||
2201 | printf("HFSTest_Rename\n"); | |
2202 | ||
2203 | UVFSFileNode TestFolder = NULL; | |
2204 | iErr = CreateNewFolder( RootNode, &TestFolder, "TestFolder"); | |
2205 | printf("CreateNewFolder err [%d]\n", iErr); | |
2206 | if (iErr) | |
2207 | return iErr; | |
2208 | ||
2209 | //Create new file with size 0 | |
2210 | UVFSFileNode TestFile1 = NULL; | |
2211 | CreateNewFile(TestFolder, &TestFile1, "TestFile",0); | |
2212 | printf("Create TestFile in TestFolder err [%d]\n", iErr); | |
2213 | if (iErr) | |
2214 | return iErr; | |
2215 | ||
2216 | //Create new file with size 512 | |
2217 | UVFSFileNode TestFile2 = NULL; | |
2218 | CreateNewFile(TestFolder, &TestFile2, "TestFile2",512); | |
2219 | printf("Create TestFile2 in TestFolder err [%d]\n", iErr); | |
2220 | if (iErr) | |
2221 | return iErr; | |
2222 | ||
2223 | ||
2224 | uint32_t uEntrySize = sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH; | |
2225 | UVFSDirEntryAttr *psReadDirTestsData = malloc(2*uEntrySize); | |
2226 | if (psReadDirTestsData == NULL) | |
2227 | return ENOMEM; | |
2228 | ||
2229 | UVFSDirEntryAttr *psCurrentReadDirTestsData = psReadDirTestsData; | |
2230 | SetExpectedAttr("TestFile", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
2231 | iErr = HFS_fsOps.fsops_getattr( TestFile1, &psCurrentReadDirTestsData->dea_attrs ); | |
2232 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
2233 | SetExpectedAttr("TestFile2", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
2234 | iErr = HFS_fsOps.fsops_getattr( TestFile2, &psCurrentReadDirTestsData->dea_attrs ); | |
2235 | ||
2236 | iErr = ReadDirAttr(TestFolder, psReadDirTestsData, 2); | |
2237 | free(psReadDirTestsData); | |
2238 | printf("ReadDirAttr err [%d]\n", iErr); | |
2239 | if (iErr) | |
2240 | goto exit; | |
2241 | ||
2242 | ||
2243 | iErr = RenameFile(TestFolder, TestFile1, "TestFile", TestFolder, NULL, "TestFile3"); | |
2244 | printf("Rename TestFile to TestFile3 in same dir err [%d]\n", iErr); | |
2245 | if (iErr) | |
2246 | goto exit; | |
2247 | ||
2248 | iErr = RenameFile(TestFolder, TestFile2, "TestFile2", RootNode, NULL, "TestFile4"); | |
2249 | printf("Rename TestFile2 to TestFile4 in diff Dir err [%d]\n", iErr); | |
2250 | if (iErr) | |
2251 | goto exit; | |
2252 | ||
2253 | iErr = RenameFile(RootNode, TestFolder, "TestFolder", RootNode, NULL, "TestFolder5"); | |
2254 | printf("Rename Dir TestFolder to TestFolder5 err [%d]\n", iErr); | |
2255 | if (iErr) | |
2256 | goto exit; | |
2257 | ||
2258 | iErr = RenameFile(TestFolder, TestFile1, "TestFile3", RootNode, TestFile2, "TestFile4"); | |
2259 | printf("Rename TestFile3 to TestFile4 in diff Dir err [%d]\n", iErr); | |
2260 | if (iErr) | |
2261 | goto exit; | |
2262 | ||
2263 | ||
2264 | // Remove File2 | |
2265 | iErr = RemoveFile(RootNode,"TestFile4"); | |
2266 | printf("Remove File TestFile2 from TestFolder err [%d]\n", iErr); | |
2267 | if (iErr) | |
2268 | goto exit; | |
2269 | ||
2270 | // Remove TestFolder | |
2271 | iErr = RemoveFolder(RootNode,"TestFolder5"); | |
2272 | printf("Remove Folder TestFolder from Root err [%d]\n", iErr); | |
2273 | if (iErr) | |
2274 | goto exit; | |
2275 | ||
2276 | exit: | |
2277 | HFS_fsOps.fsops_reclaim(TestFolder); | |
2278 | HFS_fsOps.fsops_reclaim(TestFile1); | |
2279 | HFS_fsOps.fsops_reclaim(TestFile2); | |
2280 | return iErr; | |
2281 | } | |
2282 | ||
2283 | static int ScanDir(UVFSFileNode UVFSFolderNode, char** contain_str_array, char** end_with_str_array, struct timespec mTime) | |
2284 | { | |
2285 | int err = 0; | |
2286 | ||
2287 | scandir_matching_request_t sMatchingCriteria = {0}; | |
2288 | UVFSFileAttributes smr_attribute_filter = {0}; | |
2289 | scandir_matching_reply_t sMatchingResult = {0}; | |
2290 | void* pvAttrBuf = malloc(sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH*sizeof(char)); | |
2291 | sMatchingResult.smr_entry = pvAttrBuf; | |
2292 | ||
2293 | sMatchingCriteria.smr_filename_contains = contain_str_array; | |
2294 | sMatchingCriteria.smr_filename_ends_with = end_with_str_array; | |
2295 | sMatchingCriteria.smr_attribute_filter = &smr_attribute_filter; | |
2296 | ||
2297 | if (mTime.tv_nsec != 0 || mTime.tv_sec != 0 ) | |
2298 | { | |
2299 | sMatchingCriteria.smr_attribute_filter->fa_validmask |= UVFS_FA_VALID_MTIME; | |
2300 | sMatchingCriteria.smr_attribute_filter->fa_mtime = mTime; | |
2301 | } | |
2302 | ||
2303 | bool bConRead = true; | |
2304 | ||
2305 | do | |
2306 | { | |
2307 | err = HFS_fsOps.fsops_scandir (UVFSFolderNode, &sMatchingCriteria, &sMatchingResult); | |
2308 | if ( err != 0 || ( sMatchingResult.smr_entry->dea_nextcookie == UVFS_DIRCOOKIE_EOF && sMatchingResult.smr_result_type == 0 ) ) | |
2309 | { | |
2310 | bConRead = false; | |
2311 | } | |
2312 | else | |
2313 | { | |
2314 | if ( sMatchingResult.smr_entry->dea_nextcookie == UVFS_DIRCOOKIE_EOF ) | |
2315 | { | |
2316 | bConRead = false; | |
2317 | } | |
2318 | printf("SearchDir Returned with status %d, FileName = [%s], M-Time sec:[%ld] nsec:[%ld].\n", sMatchingResult.smr_result_type, UVFS_DIRENTRYATTR_NAMEPTR(sMatchingResult.smr_entry),sMatchingResult.smr_entry->dea_attrs.fa_mtime.tv_sec,sMatchingResult.smr_entry->dea_attrs.fa_mtime.tv_nsec); | |
2319 | ||
2320 | sMatchingCriteria.smr_start_cookie = sMatchingResult.smr_entry->dea_nextcookie; | |
2321 | sMatchingCriteria.smr_verifier = sMatchingResult.smr_verifier; | |
2322 | } | |
2323 | ||
2324 | }while (bConRead); | |
2325 | ||
2326 | free(pvAttrBuf); | |
2327 | ||
2328 | return err; | |
2329 | } | |
2330 | ||
2331 | static int HFSTest_Corrupted2ndDiskImage(__unused UVFSFileNode RootNode ) | |
2332 | { | |
2333 | int iErr = 0; | |
2334 | printf("HFSTest_Corrupted2ndDiskImage:\n"); | |
2335 | ||
2336 | UVFSFileNode TestFolder1 = NULL; | |
2337 | iErr = CreateNewFolder( RootNode, &TestFolder1, "StamFolder"); | |
2338 | printf("CreateNewFolder err [%d]\n", iErr); | |
2339 | if (iErr) goto exit; | |
2340 | ||
2341 | HFS_fsOps.fsops_reclaim(TestFolder1); | |
2342 | ||
2343 | exit: | |
2344 | return iErr; | |
2345 | } | |
2346 | ||
2347 | static int HFSTest_ScanDir(UVFSFileNode RootNode ) | |
2348 | { | |
2349 | int iErr = 0; | |
2350 | UVFSFileNode TestFolder1 = NULL; | |
2351 | UVFSFileNode TestFolder2 = NULL; | |
2352 | UVFSFileNode TestFile1 = NULL; | |
2353 | ||
2354 | iErr = CreateNewFolder( RootNode, &TestFolder1, "D2"); | |
2355 | printf("CreateNewFolder err [%d]\n", iErr); | |
2356 | if (iErr) goto exit; | |
2357 | ||
2358 | iErr = CreateNewFolder( RootNode, &TestFolder2, "ÖÖ"); | |
2359 | printf("CreateNewFolder err [%d]\n", iErr); | |
2360 | if (iErr) goto exit; | |
2361 | ||
2362 | //Create new file with size 0 | |
2363 | iErr = CreateNewFile(RootNode, &TestFile1, "F🤪2",0); | |
2364 | printf("Create TestFile in TestFolder err [%d]\n", iErr); | |
2365 | if (iErr) goto exit; | |
2366 | ||
2367 | UVFSFileAttributes sOutAttrs; | |
2368 | iErr = HFS_fsOps.fsops_getattr(TestFile1, &sOutAttrs); | |
2369 | printf("fsops_getattr F🤪2 err [%d]\n",iErr); | |
2370 | if (iErr) goto exit; | |
2371 | ||
2372 | struct timespec mTime = {0}; | |
2373 | mTime.tv_nsec = sOutAttrs.fa_mtime.tv_nsec; | |
2374 | mTime.tv_sec = sOutAttrs.fa_mtime.tv_sec; | |
2375 | ||
2376 | char* name_contains_array[5] = {0}; | |
2377 | char* name_end_with_array[5] = {0}; | |
2378 | char Smile[5] = "🤪"; | |
2379 | char ContainLetter[2] = "d"; | |
2380 | char EndsWithLetter[2] = "2"; | |
2381 | char SpecialChar[3] = "ö"; | |
2382 | ||
2383 | name_contains_array[0] = (char*) Smile; | |
2384 | name_contains_array[1] = (char*) ContainLetter; | |
2385 | name_contains_array[2] = (char*) SpecialChar; | |
2386 | name_contains_array[3] = NULL; | |
2387 | ||
2388 | name_end_with_array[0] = (char*) EndsWithLetter; | |
2389 | name_end_with_array[1] = (char*) SpecialChar; | |
2390 | name_end_with_array[2] = NULL; | |
2391 | ||
2392 | iErr = ScanDir(RootNode, (char**) &name_contains_array, (char**) &name_end_with_array, mTime); | |
2393 | printf("ScanDir err [%d]\n",iErr); | |
2394 | ||
2395 | ||
2396 | HFS_fsOps.fsops_reclaim(TestFolder1); | |
2397 | HFS_fsOps.fsops_reclaim(TestFolder2); | |
2398 | HFS_fsOps.fsops_reclaim(TestFile1); | |
2399 | ||
2400 | // Remove File | |
2401 | iErr = RemoveFile(RootNode,"F🤪2"); | |
2402 | printf("Remove File F🤪2 from TestFolder err [%d]\n", iErr); | |
2403 | if (iErr) goto exit; | |
2404 | // Remove Folders | |
2405 | iErr = RemoveFolder(RootNode,"D2"); | |
2406 | printf("Remove Folder D1 from Root err [%d]\n", iErr); | |
2407 | if (iErr) goto exit; | |
2408 | ||
2409 | iErr = RemoveFolder(RootNode,"ÖÖ"); | |
2410 | printf("Remove Folder ÖÖ from Root err [%d]\n", iErr); | |
2411 | if (iErr) goto exit; | |
2412 | exit: | |
2413 | return iErr; | |
2414 | } | |
2415 | ||
2416 | static int HFSTest_RootFillUp( UVFSFileNode RootNode ) { | |
2417 | #define ROOT_FILL_UP_NUM_OF_FOLDERS 512 | |
2418 | #define ROOT_FILL_UP_NUM_OF_SYMLINKS 512 | |
2419 | UVFSFileNode pTestFolder[ROOT_FILL_UP_NUM_OF_FOLDERS] = {NULL}; | |
2420 | ||
2421 | int iErr = 0; | |
2422 | unsigned u = 0; | |
2423 | bool bFound; | |
2424 | ||
2425 | printf("HFSTest_RootFillUp\n"); | |
2426 | ||
2427 | // Create folders | |
2428 | for(u=0; u<ROOT_FILL_UP_NUM_OF_FOLDERS; u++) { | |
2429 | ||
2430 | char pcFolderName[256] = {0}; | |
2431 | sprintf(pcFolderName, "TestFolder_%d", u); | |
2432 | ||
2433 | printf("Creating folder %s.\n", pcFolderName); | |
2434 | iErr = CreateNewFolder( RootNode, &pTestFolder[u], pcFolderName); | |
2435 | //printf("iErr [%d]\n", iErr); | |
2436 | if (iErr) { | |
2437 | printf("Error: Creating folder %s. iErr [%d]\n", pcFolderName, iErr); | |
2438 | return iErr; | |
2439 | } | |
2440 | } | |
2441 | ||
2442 | // Validate folders exist | |
2443 | for(u=0; u<ROOT_FILL_UP_NUM_OF_FOLDERS; u++) { | |
2444 | ||
2445 | char pcFolderName[256] = {0}; | |
2446 | sprintf(pcFolderName, "TestFolder_%d", u); | |
2447 | ||
2448 | bFound = false; | |
2449 | read_directory_and_search_for_name( RootNode, pcFolderName, &bFound, NULL, 0); | |
2450 | if (!bFound) { | |
2451 | printf("Error: %s wasn't found in Root.\n", pcFolderName); | |
2452 | return -1; | |
2453 | } else { | |
2454 | printf("%s was found in Root.\n", pcFolderName); | |
2455 | } | |
2456 | } | |
2457 | ||
2458 | // Remove folders | |
2459 | for(u=0; u<ROOT_FILL_UP_NUM_OF_FOLDERS; u++) { | |
2460 | ||
2461 | char pcFolderName[256] = {0}; | |
2462 | sprintf(pcFolderName, "TestFolder_%d", u); | |
2463 | ||
2464 | HFS_fsOps.fsops_reclaim(pTestFolder[u]); | |
2465 | iErr = RemoveFolder(RootNode, pcFolderName); | |
2466 | printf("Remove Folder %s from Root err [%d]\n", pcFolderName, iErr); | |
2467 | if (iErr) { | |
2468 | return iErr; | |
2469 | } | |
2470 | } | |
2471 | ||
2472 | // Validate folders have been removed | |
2473 | for(u=0; u<ROOT_FILL_UP_NUM_OF_FOLDERS; u++) { | |
2474 | ||
2475 | char pcFolderName[256] = {0}; | |
2476 | sprintf(pcFolderName, "TestFolder_%d", u); | |
2477 | ||
2478 | bFound = false; | |
2479 | read_directory_and_search_for_name( RootNode, pcFolderName, &bFound, NULL, 0 ); | |
2480 | if (bFound) { | |
2481 | printf("Found deleted dir! (%s)", pcFolderName); | |
2482 | return -1; | |
2483 | } else { | |
2484 | printf(" Folder %s has been removed successfully.\n", pcFolderName); | |
2485 | } | |
2486 | } | |
2487 | ||
2488 | ||
2489 | // Create Symlink | |
2490 | UVFSFileNode pOutNode[ROOT_FILL_UP_NUM_OF_SYMLINKS] = {NULL}; | |
2491 | uint32_t uSymLinkMode = UVFS_FA_MODE_USR(UVFS_FA_MODE_RWX) | UVFS_FA_MODE_GRP(UVFS_FA_MODE_R) | UVFS_FA_MODE_OTH(UVFS_FA_MODE_R | UVFS_FA_MODE_X); | |
2492 | for(u=0; u<ROOT_FILL_UP_NUM_OF_SYMLINKS; u++) { | |
2493 | ||
2494 | char pcSymLinkName[256] = {0}; | |
2495 | sprintf(pcSymLinkName, "TestSymLink_%d", u); | |
2496 | char pcSymLinkContent[256] = {0}; | |
2497 | sprintf(pcSymLinkContent, "/just/for/check/that/symlink/work/properly_%d", u); | |
2498 | UVFSFileAttributes sAttr = {0}; | |
2499 | sAttr.fa_validmask = UVFS_FA_VALID_MODE; | |
2500 | sAttr.fa_type = UVFS_FA_TYPE_SYMLINK; | |
2501 | sAttr.fa_mode = uSymLinkMode; | |
2502 | ||
2503 | iErr = HFS_fsOps.fsops_symlink( RootNode, pcSymLinkName, pcSymLinkContent, &sAttr, &pOutNode[u] ); | |
2504 | if ( iErr != 0 ) { | |
2505 | printf( "fsops_symlink failed with eror code : %d\n", iErr ); | |
2506 | return(iErr); | |
2507 | } | |
2508 | ||
2509 | //HFS_fsOps.fsops_reclaim( pOutNode[u] ); | |
2510 | } | |
2511 | ||
2512 | ||
2513 | // Verify Symlink content | |
2514 | for(u=0; u<ROOT_FILL_UP_NUM_OF_SYMLINKS; u++) { | |
2515 | ||
2516 | char pcSymLinkName[256] = {0}; | |
2517 | sprintf(pcSymLinkName, "TestSymLink_%d", u); | |
2518 | char pcSymLinkReadContent[256] = {0}; | |
2519 | size_t iActuallyRead; | |
2520 | ||
2521 | //UVFSFileNode SymLinkNode = NULL; | |
2522 | //iErr = HFS_fsOps.fsops_lookup( RootNode, pcSymLinkName, &SymLinkNode ); | |
2523 | //printf("Symlink (%s) Lookup err [%d]\n", pcSymLinkName, iErr); | |
2524 | //if ( iErr ) | |
2525 | // return iErr; | |
2526 | ||
2527 | UVFSFileAttributes sOutAttr = {0}; | |
2528 | ||
2529 | iErr = HFS_fsOps.fsops_readlink( pOutNode[u], pcSymLinkReadContent, sizeof(pcSymLinkReadContent), &iActuallyRead, &sOutAttr ); | |
2530 | //iErr = HFS_fsOps.fsops_readlink( SymLinkNode, pcSymLinkReadContent, sizeof(pcSymLinkReadContent), &iActuallyRead, &sOutAttr ); | |
2531 | if ( iErr != 0 ) { | |
2532 | printf( "fsops_readlink failed with eror code : %d\n", iErr ); | |
2533 | return(iErr); | |
2534 | } | |
2535 | ||
2536 | char pcSymLinkContent[256] = {0}; | |
2537 | sprintf(pcSymLinkContent, "/just/for/check/that/symlink/work/properly_%d", u); | |
2538 | ||
2539 | if ( strcmp( pcSymLinkContent, pcSymLinkReadContent) != 0 ) { | |
2540 | printf( "Read bad symlink content\n" ); | |
2541 | iErr = -1; | |
2542 | return(iErr); | |
2543 | } | |
2544 | ||
2545 | if ( sOutAttr.fa_mode != uSymLinkMode) { | |
2546 | printf( "Mode mismatch [%d != %d]\n", sOutAttr.fa_mode, uSymLinkMode); | |
2547 | iErr = -1; | |
2548 | return(iErr); | |
2549 | } | |
2550 | ||
2551 | if ( sOutAttr.fa_type != UVFS_FA_TYPE_SYMLINK ) { | |
2552 | printf( "Type mismatch\n" ); | |
2553 | iErr = -1; | |
2554 | return(iErr); | |
2555 | } | |
2556 | ||
2557 | HFS_fsOps.fsops_reclaim( pOutNode[u] ); | |
2558 | //HFS_fsOps.fsops_reclaim( SymLinkNode ); | |
2559 | } | |
2560 | ||
2561 | // Remove SymLinks. | |
2562 | for(u=0; u<ROOT_FILL_UP_NUM_OF_SYMLINKS; u++) { | |
2563 | ||
2564 | char pcSymLinkName[256] = {0}; | |
2565 | sprintf(pcSymLinkName, "TestSymLink_%d", u); | |
2566 | ||
2567 | iErr = HFS_fsOps.fsops_remove( RootNode, pcSymLinkName, NULL); | |
2568 | if ( iErr != 0 ) { | |
2569 | printf( "Failed to remove symlink %d\n", iErr ); | |
2570 | return(iErr); | |
2571 | } | |
2572 | ||
2573 | bFound = false; | |
2574 | read_directory_and_search_for_name( RootNode, pcSymLinkName, &bFound, NULL, 0 ); | |
2575 | if ( bFound ) { | |
2576 | printf( "Failed to remove symlink\n"); | |
2577 | iErr = -1; | |
2578 | return(iErr); | |
2579 | } | |
2580 | } | |
2581 | ||
2582 | return iErr; | |
2583 | } | |
2584 | ||
2585 | static int ReadUnMountBit(UVFSFileNode psRootNode, uint32_t *puUnMountBit) { | |
2586 | ||
2587 | int iErr = 0; | |
2588 | char pcVolumeHeader[512]; | |
2589 | uint64_t uActuallyRead = 0; | |
2590 | iErr = raw_readwrite_read_mount(psRootNode, 2, 512, pcVolumeHeader, 512, &uActuallyRead, NULL); | |
2591 | if (iErr) { | |
2592 | printf("Failed to read volume header\n"); | |
2593 | goto exit; | |
2594 | } | |
2595 | ||
2596 | uint32_t uVolHdrAttributesBigEndian = *(uint32_t*)(pcVolumeHeader+4); | |
2597 | uint32_t uVolHdrAttributes = OSSwapBigToHostInt32(uVolHdrAttributesBigEndian); | |
2598 | printf("uVolHdrAttributes 0x%x\n", uVolHdrAttributes); | |
2599 | ||
2600 | uint32_t uUnMountBit = (uVolHdrAttributes & 0x00000100)?1:0; | |
2601 | printf("uUnMountBit %u\n", uUnMountBit); | |
2602 | ||
2603 | *puUnMountBit = uUnMountBit; | |
2604 | ||
2605 | exit: | |
2606 | return(iErr); | |
2607 | } | |
2608 | ||
2609 | static int HFSTest_ValidateUnmount_wJournal( UVFSFileNode psRootNode ) { | |
2610 | int iErr = 0; | |
2611 | ||
2612 | printf("HFSTest_ValidateUnmount_wJournal\n"); | |
2613 | ||
2614 | UVFSFileNode psTestFolder = NULL; | |
2615 | iErr = CreateNewFolder( psRootNode, &psTestFolder, "TestFolder"); | |
2616 | printf("CreateNewFolder err [%d]\n", iErr); | |
2617 | if (iErr) | |
2618 | return iErr; | |
2619 | ||
2620 | HFS_fsOps.fsops_reclaim( psTestFolder ); | |
2621 | ||
2622 | // Read volume header & validate unmount is set (journaled data is still in cache) | |
2623 | uint32_t uUnMountBit; | |
2624 | if (ReadUnMountBit(psRootNode, &uUnMountBit)) { | |
2625 | goto exit; | |
2626 | } | |
2627 | ||
2628 | if (!uUnMountBit) { | |
2629 | printf("uUnMountBit is cleared though it should be set\n"); | |
2630 | iErr = -1; | |
2631 | goto exit; | |
2632 | } | |
2633 | ||
2634 | // Call Sync | |
2635 | HFS_fsOps.fsops_sync(psRootNode); | |
2636 | ||
2637 | // Read volume header & validate unmount is set | |
2638 | if (ReadUnMountBit(psRootNode, &uUnMountBit)) { | |
2639 | goto exit; | |
2640 | } | |
2641 | if (!uUnMountBit) { | |
2642 | printf("uUnMountBit is cleared though it should be set\n"); | |
2643 | iErr = -1; | |
2644 | goto exit; | |
2645 | } | |
2646 | ||
2647 | exit: | |
2648 | return iErr; | |
2649 | } | |
2650 | ||
2651 | static int HFSTest_ValidateUnmount( UVFSFileNode psRootNode ) { | |
2652 | int iErr = 0; | |
2653 | uint32_t uUnMountBit; | |
2654 | ||
2655 | printf("HFSTest_ValidateUnmount\n"); | |
2656 | ||
2657 | UVFSFileNode psTestFolder = NULL; | |
2658 | iErr = CreateNewFolder( psRootNode, &psTestFolder, "TestFolder_1"); | |
2659 | printf("CreateNewFolder err [%d]\n", iErr); | |
2660 | if (iErr) | |
2661 | return iErr; | |
2662 | ||
2663 | HFS_fsOps.fsops_reclaim( psTestFolder ); | |
2664 | ||
2665 | // Read volume header & validate unmount is cleared | |
2666 | if (ReadUnMountBit(psRootNode, &uUnMountBit)) { | |
2667 | goto exit; | |
2668 | } | |
2669 | ||
2670 | if (uUnMountBit) { | |
2671 | printf("uUnMountBit is set though it should be cleared\n"); | |
2672 | iErr = -1; | |
2673 | goto exit; | |
2674 | } | |
2675 | ||
2676 | // Call Sync | |
2677 | HFS_fsOps.fsops_sync(psRootNode); | |
2678 | ||
2679 | // Read volume header & validate unmount is set | |
2680 | if (ReadUnMountBit(psRootNode, &uUnMountBit)) { | |
2681 | goto exit; | |
2682 | } | |
2683 | if (!uUnMountBit) { | |
2684 | printf("uUnMountBit is cleared though it should be set\n"); | |
2685 | iErr = -1; | |
2686 | goto exit; | |
2687 | } | |
2688 | ||
2689 | iErr = CreateNewFolder( psRootNode, &psTestFolder, "TestFolder_2"); | |
2690 | printf("CreateNewFolder err [%d]\n", iErr); | |
2691 | if (iErr) | |
2692 | return iErr; | |
2693 | ||
2694 | HFS_fsOps.fsops_reclaim( psTestFolder ); | |
2695 | ||
2696 | // Read volume header & validate unmount is cleared | |
2697 | if (ReadUnMountBit(psRootNode, &uUnMountBit)) { | |
2698 | goto exit; | |
2699 | } | |
2700 | ||
2701 | if (uUnMountBit) { | |
2702 | printf("uUnMountBit is set though it should be cleared\n"); | |
2703 | iErr = -1; | |
2704 | goto exit; | |
2705 | } | |
2706 | ||
2707 | // Call Sync | |
2708 | HFS_fsOps.fsops_sync(psRootNode); | |
2709 | ||
2710 | // Read volume header & validate unmount is set | |
2711 | if (ReadUnMountBit(psRootNode, &uUnMountBit)) { | |
2712 | goto exit; | |
2713 | } | |
2714 | if (!uUnMountBit) { | |
2715 | printf("uUnMountBit is cleared though it should be set\n"); | |
2716 | iErr = -1; | |
2717 | goto exit; | |
2718 | } | |
2719 | ||
2720 | exit: | |
2721 | return iErr; | |
2722 | } | |
2723 | ||
2724 | static int HFSTest_OneSync( UVFSFileNode RootNode ) { | |
2725 | int iErr = 0; | |
2726 | char pcFolderName[256]; | |
2727 | ||
2728 | printf("HFSTest_OneSync\n"); | |
2729 | ||
2730 | for(unsigned u=0; u<5; u++) { | |
2731 | UVFSFileNode TestFolder = NULL; | |
2732 | sprintf(pcFolderName, "TestFolder_%u", u); | |
2733 | ||
2734 | iErr = CreateNewFolder( RootNode, &TestFolder, pcFolderName); | |
2735 | printf("CreateNewFolder err [%d]\n", iErr); | |
2736 | if (iErr) | |
2737 | return iErr; | |
2738 | HFS_fsOps.fsops_reclaim( TestFolder ); | |
2739 | } | |
2740 | ||
2741 | for(unsigned u=0; u<5; u++) { | |
2742 | bool bFound = false; | |
2743 | sprintf(pcFolderName, "TestFolder_%u", u); | |
2744 | read_directory_and_search_for_name( RootNode, pcFolderName, &bFound, NULL, 0); | |
2745 | if (!bFound) | |
2746 | { | |
2747 | printf("Error: %s wasn't found in Root.\n", pcFolderName); | |
2748 | return -1; | |
2749 | } | |
2750 | else | |
2751 | { | |
2752 | printf("%s found in Root!\n", pcFolderName); | |
2753 | } | |
2754 | } | |
2755 | ||
2756 | printf("Calling Sync\n"); | |
2757 | HFS_fsOps.fsops_sync(RootNode); | |
2758 | ||
2759 | return iErr; | |
2760 | } | |
2761 | ||
2762 | static int | |
2763 | HFSTest_MakeDir( UVFSFileNode RootNode ) | |
2764 | { | |
2765 | int iErr = 0; | |
2766 | ||
2767 | printf("HFSTest_MakeDir\n"); | |
2768 | ||
2769 | UVFSFileNode TestFolder = NULL; | |
2770 | iErr = CreateNewFolder( RootNode, &TestFolder, "TestFolder"); | |
2771 | printf("CreateNewFolder err [%d]\n", iErr); | |
2772 | if (iErr) | |
2773 | return iErr; | |
2774 | ||
2775 | bool bFound = false; | |
2776 | read_directory_and_search_for_name( RootNode, "TestFolder", &bFound, NULL, 0); | |
2777 | if (!bFound) | |
2778 | { | |
2779 | printf("Error: TestFolder wasn't found in Root.\n"); | |
2780 | return -1; | |
2781 | } | |
2782 | else | |
2783 | { | |
2784 | printf("TestFolder found in Root!\n"); | |
2785 | } | |
2786 | ||
2787 | // Remove D1 | |
2788 | iErr = RemoveFolder(RootNode,"TestFolder"); | |
2789 | printf("Remove Folder D1 from Root err [%d]\n", iErr); | |
2790 | if (iErr) | |
2791 | return iErr; | |
2792 | ||
2793 | bFound = false; | |
2794 | read_directory_and_search_for_name( RootNode, "TestFolder", &bFound, NULL, 0 ); | |
2795 | if (bFound) | |
2796 | { | |
2797 | printf("Found deleted dir!"); | |
2798 | return -1; | |
2799 | } | |
2800 | ||
2801 | HFS_fsOps.fsops_reclaim( TestFolder ); | |
2802 | ||
2803 | return iErr; | |
2804 | } | |
2805 | ||
2806 | __unused static int | |
2807 | HFSTest_MakeDirAndKeep( UVFSFileNode psRootNode ) | |
2808 | { | |
2809 | int iErr = 0; | |
2810 | char pcFolderName[256]; | |
2811 | ||
2812 | printf("HFSTest_MakeDirAndKeep\n"); | |
2813 | ||
2814 | for(unsigned u=0; u<100; u++) { | |
2815 | UVFSFileNode TestFolder = NULL; | |
2816 | sprintf(pcFolderName, "TestFolder_%u", u); | |
2817 | iErr = CreateNewFolder( psRootNode, &TestFolder, pcFolderName); | |
2818 | printf("CreateNewFolder err [%d]\n", iErr); | |
2819 | if (iErr) | |
2820 | return iErr; | |
2821 | usleep(guSyncerPeriod * 10); // Allow the syncer to run (at 1/100th rate) | |
2822 | ||
2823 | HFS_fsOps.fsops_reclaim( TestFolder ); | |
2824 | } | |
2825 | ||
2826 | for(unsigned u=0; u<100; u++) { | |
2827 | bool bFound = false; | |
2828 | sprintf(pcFolderName, "TestFolder_%u", u); | |
2829 | read_directory_and_search_for_name( psRootNode, pcFolderName, &bFound, NULL, 0); | |
2830 | if (!bFound) | |
2831 | { | |
2832 | printf("Error: %s wasn't found in Root.\n", pcFolderName); | |
2833 | return -1; | |
2834 | } | |
2835 | else | |
2836 | { | |
2837 | printf("%s found in Root!\n", pcFolderName); | |
2838 | } | |
2839 | } | |
2840 | ||
2841 | return iErr; | |
2842 | } | |
2843 | ||
2844 | static int | |
2845 | HFSTest_ReadDefragmentFile( UVFSFileNode RootNode ) | |
2846 | { | |
2847 | ||
2848 | int iErr = 0; | |
2849 | ||
2850 | printf("HFSTest_ReadDefragmentFile\n"); | |
2851 | ||
2852 | ||
2853 | UVFSFileNode DeFragmentFile = NULL; | |
2854 | iErr = HFS_fsOps.fsops_lookup( RootNode, "defragment1.bin", &DeFragmentFile ); | |
2855 | printf("Lookup err [%d]\n", iErr); | |
2856 | if ( iErr ) | |
2857 | return iErr; | |
2858 | ||
2859 | UVFSFileAttributes sOutAttr; | |
2860 | iErr = HFS_fsOps.fsops_getattr( DeFragmentFile, &sOutAttr ); | |
2861 | printf("GetAttr err [%d]\n", iErr); | |
2862 | if ( iErr ) | |
2863 | return iErr; | |
2864 | ||
2865 | #define FILE_SIZE (1638400) | |
2866 | if ( sOutAttr.fa_allocsize != FILE_SIZE || sOutAttr.fa_size != FILE_SIZE) | |
2867 | { | |
2868 | printf("Wrong size [%llu\n] [%llu\n]\n", sOutAttr.fa_size, sOutAttr.fa_allocsize); | |
2869 | return -1; | |
2870 | } | |
2871 | ||
2872 | void* pvReadBuf = malloc(FILE_SIZE); | |
2873 | memset(pvReadBuf, 0, FILE_SIZE); | |
2874 | ||
2875 | size_t iActuallyRead; | |
2876 | iErr = HFS_fsOps.fsops_read( DeFragmentFile, 0, FILE_SIZE, pvReadBuf, &iActuallyRead ); | |
2877 | ||
2878 | HFS_fsOps.fsops_reclaim( DeFragmentFile ); | |
2879 | ||
2880 | if ( iErr != 0 ) | |
2881 | { | |
2882 | printf("HFS_fsOps.fsops_read return status %d\n", iErr); | |
2883 | free(pvReadBuf); | |
2884 | return iErr; | |
2885 | } | |
2886 | ||
2887 | if ( iActuallyRead != FILE_SIZE ) | |
2888 | { | |
2889 | printf("iActuallyRead != FILE_SIZE %lu\n", iActuallyRead); | |
2890 | free(pvReadBuf); | |
2891 | return -1; | |
2892 | } | |
2893 | ||
2894 | uint32_t uDetectedNum = 0; | |
2895 | char pcDetectedNum[17] = {0}; | |
2896 | for ( uint32_t uIdx=0; uIdx<FILE_SIZE/16; uIdx++ ) | |
2897 | { | |
2898 | memcpy(pcDetectedNum, pvReadBuf + uIdx*16, 16); | |
2899 | sscanf(pcDetectedNum, "%u", &uDetectedNum); | |
2900 | ||
2901 | if ( uIdx+1 != uDetectedNum ) | |
2902 | { | |
2903 | printf("Read failed. Expected [%u], detected [%u]\n", uIdx, uDetectedNum); | |
2904 | free(pvReadBuf); | |
2905 | return -1; | |
2906 | } | |
2907 | } | |
2908 | ||
2909 | free(pvReadBuf); | |
2910 | return iErr; | |
2911 | } | |
2912 | ||
2913 | static int | |
2914 | HFSTest_RemoveDir( UVFSFileNode RootNode ) | |
2915 | { | |
2916 | int iErr = 0; | |
2917 | ||
2918 | UVFSFileNode MainDir = NULL; | |
2919 | iErr = HFS_fsOps.fsops_lookup( RootNode, "MainDir", &MainDir ); | |
2920 | if ( iErr != 0 ) | |
2921 | { | |
2922 | printf("Failed to lookup for main dir\n"); | |
2923 | return iErr; | |
2924 | } | |
2925 | ||
2926 | // Try to delete non empty directoy. | |
2927 | iErr = HFS_fsOps.fsops_rmdir( RootNode, "MainDir" ); | |
2928 | if ( iErr != ENOTEMPTY ) | |
2929 | { | |
2930 | printf( "Return status is [%d], expected [%d]\n", iErr, ENOTEMPTY ); | |
2931 | return -1; | |
2932 | } | |
2933 | ||
2934 | // Delete empty dirs.. Dir[1..10]; | |
2935 | char pcDirName[10]; | |
2936 | for ( int iDirIdx=1; iDirIdx<11; iDirIdx++ ) | |
2937 | { | |
2938 | memset( pcDirName, 0, sizeof(pcDirName) ); | |
2939 | sprintf( pcDirName, "Dir%d", iDirIdx); | |
2940 | ||
2941 | // Try to delete empty directoy. | |
2942 | iErr = HFS_fsOps.fsops_rmdir( MainDir, pcDirName ); | |
2943 | printf( "remove dir ended with err [%d]\n", iErr ); | |
2944 | if ( iErr != 0 ) | |
2945 | { | |
2946 | return iErr; | |
2947 | } | |
2948 | } | |
2949 | ||
2950 | // Reclaim main dir. | |
2951 | HFS_fsOps.fsops_reclaim( MainDir ); | |
2952 | ||
2953 | // Now, try to delete empty main directoy. | |
2954 | iErr = HFS_fsOps.fsops_rmdir( RootNode, "MainDir" ); | |
2955 | if ( iErr != 0 ) | |
2956 | { | |
2957 | printf( "Failed to remove main dir [%d]\n", iErr ); | |
2958 | return iErr; | |
2959 | } | |
2960 | ||
2961 | // Make sure main directory deleted. | |
2962 | iErr = HFS_fsOps.fsops_lookup( RootNode, "MainDir", &MainDir ); | |
2963 | if ( iErr == 0 ) | |
2964 | { | |
2965 | printf("Main dir still exist.\n"); | |
2966 | return -1; | |
2967 | } | |
2968 | ||
2969 | // Try to remove unexisting directory | |
2970 | iErr = HFS_fsOps.fsops_rmdir( RootNode, "MainDir" ); | |
2971 | if ( iErr != ENOENT ) | |
2972 | { | |
2973 | printf( "Expected [%d], detected [%d]\n", ENOENT, iErr ); | |
2974 | return -1; | |
2975 | } | |
2976 | ||
2977 | return 0; | |
2978 | } | |
2979 | ||
2980 | static int | |
2981 | HFSTest_Remove( UVFSFileNode RootNode ) | |
2982 | { | |
2983 | int iErr = 0; | |
2984 | ||
2985 | #define NUM_OF_FILES (2) | |
2986 | ||
2987 | char* ppcFilesNames[NUM_OF_FILES] = { "SpecialFileName+-)(*&^%$#@\\!\\}\\{~~<>||??\\.txt", "file1.txt" }; | |
2988 | ||
2989 | for ( uint8_t uIdx=0; uIdx<NUM_OF_FILES; uIdx++ ) | |
2990 | { | |
2991 | bool bFound = false; | |
2992 | read_directory_and_search_for_name( RootNode, ppcFilesNames[uIdx], &bFound, NULL, 0); | |
2993 | if ( !bFound ) | |
2994 | { | |
2995 | printf( "Failed to found [%s] status [%d]\n", ppcFilesNames[uIdx], iErr ); | |
2996 | return -1; | |
2997 | } | |
2998 | ||
2999 | iErr = HFS_fsOps.fsops_remove( RootNode, ppcFilesNames[uIdx], NULL); | |
3000 | if ( iErr != 0 ) | |
3001 | { | |
3002 | printf( "Failed to remove [%s] status [%d]\n", ppcFilesNames[uIdx], iErr ); | |
3003 | return iErr; | |
3004 | } | |
3005 | ||
3006 | bFound = false; | |
3007 | read_directory_and_search_for_name( RootNode, ppcFilesNames[uIdx], &bFound, NULL, 0); | |
3008 | if ( bFound ) | |
3009 | { | |
3010 | printf( "Found [%s] status [%d]\n", ppcFilesNames[uIdx], iErr ); | |
3011 | return -1; | |
3012 | } | |
3013 | ||
3014 | iErr = HFS_fsOps.fsops_remove( RootNode, ppcFilesNames[uIdx], NULL); | |
3015 | if ( iErr != ENOENT ) | |
3016 | { | |
3017 | printf( "Removed deleted file [%s] status [%d]\n", ppcFilesNames[uIdx], iErr ); | |
3018 | return -1; | |
3019 | } | |
3020 | } | |
3021 | ||
3022 | return 0; | |
3023 | } | |
3024 | ||
3025 | static void SetExpectedAttr(char* pcName, uint32_t uType, UVFSDirEntryAttr* psAttr) | |
3026 | { | |
3027 | psAttr->dea_nameoff = UVFS_DIRENTRYATTR_NAMEOFF; | |
3028 | memcpy (UVFS_DIRENTRYATTR_NAMEPTR(psAttr),pcName, strlen(pcName) + 1); | |
3029 | psAttr->dea_attrs.fa_type = uType; | |
3030 | } | |
3031 | ||
3032 | static int | |
3033 | HFSTest_ReadDir( UVFSFileNode RootNode ) | |
3034 | { | |
3035 | int iErr = 0; | |
3036 | ||
3037 | uint32_t uEntrySize = sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH; | |
3038 | UVFSDirEntryAttr *psReadDirTestsData = malloc(6*uEntrySize); | |
3039 | if (psReadDirTestsData == NULL) | |
3040 | return ENOMEM; | |
3041 | ||
3042 | UVFSDirEntryAttr *psCurrentReadDirTestsData = psReadDirTestsData; | |
3043 | SetExpectedAttr(".", UVFS_FA_TYPE_DIR, psCurrentReadDirTestsData); | |
3044 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3045 | SetExpectedAttr("..", UVFS_FA_TYPE_DIR, psCurrentReadDirTestsData); | |
3046 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3047 | SetExpectedAttr(".DS_Store", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
3048 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3049 | SetExpectedAttr("D1", UVFS_FA_TYPE_DIR, psCurrentReadDirTestsData); | |
3050 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3051 | SetExpectedAttr("F1", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
3052 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3053 | SetExpectedAttr("L1", UVFS_FA_TYPE_SYMLINK, psCurrentReadDirTestsData); | |
3054 | ||
3055 | // | |
3056 | // {.pcTestName = ".", .uTyppe = UVFS_FA_TYPE_DIR}, | |
3057 | // {.pcTestName = "..", .uTyppe = UVFS_FA_TYPE_DIR}, | |
3058 | // {.pcTestName = ".DS_Store", .uTyppe = UVFS_FA_TYPE_FILE}, | |
3059 | // {.pcTestName = "D1", .uTyppe = UVFS_FA_TYPE_DIR}, | |
3060 | // {.pcTestName = "F1", .uTyppe = UVFS_FA_TYPE_FILE}, | |
3061 | // {.pcTestName = "L1", .uTyppe = UVFS_FA_TYPE_SYMLINK}, | |
3062 | // }; | |
3063 | ||
3064 | bool bFound; | |
3065 | UVFSFileNode MainDir = NULL; | |
3066 | iErr = HFS_fsOps.fsops_lookup( RootNode, "D1", &MainDir ); | |
3067 | printf("Lookup err [%d]\n", iErr); | |
3068 | if ( iErr ) | |
3069 | return iErr; | |
3070 | ||
3071 | iErr = read_directory_and_search_for_name( MainDir, "D1", &bFound, psReadDirTestsData, 6); | |
3072 | free(psReadDirTestsData); | |
3073 | // Reclaim main dir. | |
3074 | HFS_fsOps.fsops_reclaim(MainDir); | |
3075 | ||
3076 | return iErr; | |
3077 | } | |
3078 | ||
3079 | static int __used | |
3080 | HFSTest_ReadDirAttr( UVFSFileNode RootNode ) | |
3081 | { | |
3082 | int iErr = 0; | |
3083 | ||
3084 | // struct ReadDirTestData_s psReadDirTestsData[] = { | |
3085 | // {.pcTestName = ".DS_Store", .uTyppe = UVFS_FA_TYPE_FILE, .uSize = 6148, .uNlink = 1, .uAllocatedSize = 8192}, | |
3086 | // {.pcTestName = "D1", .uTyppe = UVFS_FA_TYPE_DIR, .uSize = 0, .uNlink = 2, .uAllocatedSize = 0}, | |
3087 | // {.pcTestName = "F1", .uTyppe = UVFS_FA_TYPE_FILE, .uSize = 4, .uNlink = 1, .uAllocatedSize = 4096}, | |
3088 | // {.pcTestName = "L1", .uTyppe = UVFS_FA_TYPE_SYMLINK, .uSize = 23, .uNlink = 1, .uAllocatedSize = 4096}, | |
3089 | // }; | |
3090 | ||
3091 | UVFSFileNode MainDir = NULL; | |
3092 | iErr = HFS_fsOps.fsops_lookup( RootNode, "D1", &MainDir ); | |
3093 | printf("Lookup err [%d]\n", iErr); | |
3094 | if ( iErr ) | |
3095 | return iErr; | |
3096 | ||
3097 | uint32_t uEntrySize = sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH; | |
3098 | UVFSDirEntryAttr *psReadDirTestsData = malloc(4*uEntrySize); | |
3099 | if (psReadDirTestsData == NULL) | |
3100 | return ENOMEM; | |
3101 | ||
3102 | UVFSFileNode psVnode = NULL; | |
3103 | UVFSFileNode psVnode1 = NULL; | |
3104 | UVFSFileNode psVnode2 = NULL; | |
3105 | UVFSFileNode psVnode3 = NULL; | |
3106 | UVFSDirEntryAttr *psCurrentReadDirTestsData = psReadDirTestsData; | |
3107 | SetExpectedAttr(".DS_Store", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
3108 | iErr = HFS_fsOps.fsops_lookup( MainDir, ".DS_Store", &psVnode ); | |
3109 | iErr = HFS_fsOps.fsops_getattr( psVnode, &psCurrentReadDirTestsData->dea_attrs ); | |
3110 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3111 | SetExpectedAttr("D1", UVFS_FA_TYPE_DIR, psCurrentReadDirTestsData); | |
3112 | iErr = HFS_fsOps.fsops_lookup( MainDir, "D1", &psVnode1 ); | |
3113 | iErr = HFS_fsOps.fsops_getattr( psVnode1, &psCurrentReadDirTestsData->dea_attrs ); | |
3114 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3115 | SetExpectedAttr("F1", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
3116 | iErr = HFS_fsOps.fsops_lookup( MainDir, "F1", &psVnode2 ); | |
3117 | iErr = HFS_fsOps.fsops_getattr( psVnode2, &psCurrentReadDirTestsData->dea_attrs ); | |
3118 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3119 | SetExpectedAttr("L1", UVFS_FA_TYPE_SYMLINK, psCurrentReadDirTestsData); | |
3120 | iErr = HFS_fsOps.fsops_lookup( MainDir, "L1", &psVnode3 ); | |
3121 | iErr = HFS_fsOps.fsops_getattr( psVnode3, &psCurrentReadDirTestsData->dea_attrs ); | |
3122 | ||
3123 | iErr = ReadDirAttr(MainDir, psReadDirTestsData, 4); | |
3124 | free(psReadDirTestsData); | |
3125 | // Reclaim main dir. | |
3126 | HFS_fsOps.fsops_reclaim(MainDir); | |
3127 | HFS_fsOps.fsops_reclaim(psVnode); | |
3128 | HFS_fsOps.fsops_reclaim(psVnode1); | |
3129 | HFS_fsOps.fsops_reclaim(psVnode2); | |
3130 | HFS_fsOps.fsops_reclaim(psVnode3); | |
3131 | ||
3132 | return iErr; | |
3133 | } | |
3134 | ||
3135 | static int | |
3136 | HFSTest_ReadSymlink( UVFSFileNode RootNode ) | |
3137 | { | |
3138 | void* pvBuf = malloc(200); | |
3139 | assert( pvBuf != NULL ); | |
3140 | memset( pvBuf, 0, 200 ); | |
3141 | char* pcSymLinkContent = "/just/for/check/that/symlink/work/properly"; | |
3142 | char* pcSymlinkFileName = "symlinkfile"; | |
3143 | UVFSFileNode outNode = NULL; | |
3144 | ||
3145 | int iErr = HFS_fsOps.fsops_lookup(RootNode, pcSymlinkFileName, &outNode); | |
3146 | if (iErr) | |
3147 | printf("Dir read failed, D2 wasn't found in Root"); | |
3148 | ||
3149 | // Verify Symlink content | |
3150 | size_t iActuallyRead; | |
3151 | UVFSFileAttributes sOutAttr = {0}; | |
3152 | iErr = HFS_fsOps.fsops_readlink( outNode, pvBuf, 200, &iActuallyRead, &sOutAttr ); | |
3153 | if ( iErr != 0 ) | |
3154 | { | |
3155 | printf( "fsops_readlink failed with eror code : %d\n", iErr ); | |
3156 | goto exit; | |
3157 | } | |
3158 | ||
3159 | if ( strcmp( pvBuf, pcSymLinkContent) != 0 ) | |
3160 | { | |
3161 | printf( "Read bad symlink content\n" ); | |
3162 | iErr = -1; | |
3163 | goto exit; | |
3164 | } | |
3165 | ||
3166 | HFS_fsOps.fsops_reclaim( outNode ); | |
3167 | ||
3168 | exit: | |
3169 | if (pvBuf) | |
3170 | free(pvBuf); | |
3171 | ||
3172 | return iErr; | |
3173 | } | |
3174 | ||
3175 | static int | |
3176 | HFSTest_Symlink( UVFSFileNode RootNode ) | |
3177 | { | |
3178 | ||
3179 | #define SYMLINK_MODE \ | |
3180 | ( UVFS_FA_MODE_USR(UVFS_FA_MODE_RWX) | \ | |
3181 | UVFS_FA_MODE_GRP(UVFS_FA_MODE_R) | \ | |
3182 | UVFS_FA_MODE_OTH(UVFS_FA_MODE_R | UVFS_FA_MODE_X) ) | |
3183 | ||
3184 | void* pvBuf = malloc(200); | |
3185 | assert( pvBuf != NULL ); | |
3186 | memset( pvBuf, 0xff, 200 ); | |
3187 | char* pcSymLinkContent = "/just/for/check/that/symlink/work/properly"; | |
3188 | char* pcSymlinkFileName = "symlinkfile"; | |
3189 | UVFSFileAttributes sAttr = {0}; | |
3190 | sAttr.fa_validmask = UVFS_FA_VALID_MODE; | |
3191 | sAttr.fa_type = UVFS_FA_TYPE_SYMLINK; | |
3192 | sAttr.fa_mode = SYMLINK_MODE; | |
3193 | UVFSFileNode outNode = NULL; | |
3194 | ||
3195 | // Create Symlink. | |
3196 | int iErr = HFS_fsOps.fsops_symlink( RootNode, pcSymlinkFileName, pcSymLinkContent, &sAttr, &outNode ); | |
3197 | if ( iErr != 0 ) | |
3198 | { | |
3199 | printf( "fsops_symlink failed with eror code : %d\n", iErr ); | |
3200 | goto exit; | |
3201 | } | |
3202 | ||
3203 | // Enable once vnode functionality will be merged. | |
3204 | ||
3205 | // Verify Symlink content | |
3206 | size_t iActuallyRead; | |
3207 | UVFSFileAttributes sOutAttr = {0}; | |
3208 | iErr = HFS_fsOps.fsops_readlink( outNode, pvBuf, 200, &iActuallyRead, &sOutAttr ); | |
3209 | if ( iErr != 0 ) | |
3210 | { | |
3211 | printf( "fsops_readlink failed with eror code : %d\n", iErr ); | |
3212 | goto exit; | |
3213 | } | |
3214 | ||
3215 | if ( strcmp( pvBuf, pcSymLinkContent) != 0 ) | |
3216 | { | |
3217 | printf( "Read bad symlink content\n" ); | |
3218 | iErr = -1; | |
3219 | goto exit; | |
3220 | } | |
3221 | ||
3222 | if ( sOutAttr.fa_mode != SYMLINK_MODE) | |
3223 | { | |
3224 | printf( "Mode mismatch [%d != %d]\n", sOutAttr.fa_mode, SYMLINK_MODE); | |
3225 | iErr = -1; | |
3226 | goto exit; | |
3227 | } | |
3228 | ||
3229 | if ( sOutAttr.fa_type != UVFS_FA_TYPE_SYMLINK ) | |
3230 | { | |
3231 | printf( "Type mismatch\n" ); | |
3232 | iErr = -1; | |
3233 | goto exit; | |
3234 | } | |
3235 | ||
3236 | ||
3237 | HFS_fsOps.fsops_reclaim( outNode ); | |
3238 | ||
3239 | // Remove link. | |
3240 | iErr = HFS_fsOps.fsops_remove( RootNode, pcSymlinkFileName, NULL); | |
3241 | if ( iErr != 0 ) | |
3242 | { | |
3243 | printf( "Failed to remove symlink %d\n", iErr ); | |
3244 | goto exit; | |
3245 | } | |
3246 | ||
3247 | bool bFound = false; | |
3248 | read_directory_and_search_for_name( RootNode, pcSymlinkFileName, &bFound, NULL, 0 ); | |
3249 | if ( bFound ) | |
3250 | { | |
3251 | printf( "Failed to remove symlink\n"); | |
3252 | iErr = -1; | |
3253 | goto exit; | |
3254 | } | |
3255 | ||
3256 | exit: | |
3257 | if (pvBuf) | |
3258 | free(pvBuf); | |
3259 | ||
3260 | return iErr; | |
3261 | } | |
3262 | ||
3263 | static int HFSTest_SymlinkOnFile( UVFSFileNode pRootNode ) { | |
3264 | // This test creates a file and a folder on root. | |
3265 | // It then tries to create a SymLink inside the folder and expects pass, | |
3266 | // and creates a SymLink inside a file and expects a failure. | |
3267 | printf("HFSTest_SymlinkOnFile\n"); | |
3268 | ||
3269 | char *pcFolderName = "NewFolder"; | |
3270 | char *pcFileName = "NewFile.txt"; | |
3271 | uint32_t uFileLen = 985; | |
3272 | char *pcSymlinkFilename = "SymLinkFile"; | |
3273 | char *pcSymLinkContent = "/SymlinkContent"; | |
3274 | int iErr = 0; | |
3275 | UVFSFileNode pFolderNode = NULL; | |
3276 | UVFSFileNode pFileNode = NULL; | |
3277 | UVFSFileNode pSymLinkOnRootNode = NULL; | |
3278 | UVFSFileNode pSymLinkOnFolderNode = NULL; | |
3279 | UVFSFileNode pSymLinkOnFileNode = NULL; | |
3280 | ||
3281 | iErr = CreateNewFolder( pRootNode, &pFolderNode, pcFolderName); | |
3282 | printf("CreateNewFolder err [%d]\n", iErr); | |
3283 | if (iErr) { | |
3284 | printf("Error: CreateNewFolder failed.\n"); | |
3285 | return iErr; | |
3286 | } | |
3287 | ||
3288 | //Create new file with size 512 | |
3289 | CreateNewFile(pRootNode, &pFileNode, pcFileName, uFileLen); | |
3290 | printf("Create %s Len %u err [%d]\n", pcFileName, uFileLen, iErr); | |
3291 | if (iErr) { | |
3292 | printf("Error: CreateNewFile failed.\n"); | |
3293 | return iErr; | |
3294 | } | |
3295 | ||
3296 | bool bFound = false; | |
3297 | read_directory_and_search_for_name( pRootNode, pcFolderName, &bFound, NULL, 0); | |
3298 | if (!bFound) { | |
3299 | printf("Error: %s wasn't found in Root.\n", pcFolderName); | |
3300 | return -1; | |
3301 | } else { | |
3302 | printf("%s found in Root!\n", pcFolderName); | |
3303 | } | |
3304 | ||
3305 | read_directory_and_search_for_name( pRootNode, pcFileName, &bFound, NULL, 0); | |
3306 | if (!bFound) { | |
3307 | printf("Error: %s wasn't found in Root.\n", pcFileName); | |
3308 | return -1; | |
3309 | } else { | |
3310 | printf("%s found in Root!\n", pcFileName); | |
3311 | } | |
3312 | ||
3313 | UVFSFileAttributes sAttr = {0}; | |
3314 | sAttr.fa_validmask = UVFS_FA_VALID_MODE; | |
3315 | sAttr.fa_type = UVFS_FA_TYPE_SYMLINK; | |
3316 | sAttr.fa_mode = SYMLINK_MODE; | |
3317 | ||
3318 | // Create Symlink on root | |
3319 | iErr = HFS_fsOps.fsops_symlink( pRootNode, pcSymlinkFilename, pcSymLinkContent, &sAttr, &pSymLinkOnRootNode ); | |
3320 | if ( iErr != 0 ) { | |
3321 | printf( "fsops_symlink failed to create %s with eror code : %d\n", pcSymlinkFilename, iErr ); | |
3322 | return(iErr); | |
3323 | } | |
3324 | ||
3325 | // Create Symlink on folder | |
3326 | iErr = HFS_fsOps.fsops_symlink( pFolderNode, pcSymlinkFilename, pcSymLinkContent, &sAttr, &pSymLinkOnFolderNode ); | |
3327 | if ( iErr != 0 ) { | |
3328 | printf( "fsops_symlink failed to create %s inside %s with eror code : %d\n", pcSymlinkFilename, pcFolderName, iErr ); | |
3329 | return(iErr); | |
3330 | } | |
3331 | ||
3332 | // Create Symlink on file | |
3333 | iErr = HFS_fsOps.fsops_symlink( pFileNode, pcSymlinkFilename, pcSymLinkContent, &sAttr, &pSymLinkOnFileNode ); | |
3334 | if ( iErr == 0 ) { | |
3335 | printf( "fsops_symlink error: did not fail to create %s inside %s with eror code : %d\n", pcSymlinkFilename, pcFileName, iErr ); | |
3336 | return(-1); | |
3337 | } | |
3338 | ||
3339 | // cleanup | |
3340 | assert(pSymLinkOnFileNode == NULL); | |
3341 | HFS_fsOps.fsops_reclaim( pFileNode ); | |
3342 | HFS_fsOps.fsops_reclaim( pFolderNode ); | |
3343 | HFS_fsOps.fsops_reclaim( pSymLinkOnFolderNode ); | |
3344 | HFS_fsOps.fsops_reclaim( pSymLinkOnRootNode ); | |
3345 | ||
3346 | return 0; | |
3347 | } | |
3348 | ||
3349 | static int | |
3350 | HFSTest_SetAttr( UVFSFileNode RootNode ) | |
3351 | { | |
3352 | int iErr = 0; | |
3353 | ||
3354 | UVFSFileNode Dir1 = NULL; | |
3355 | iErr = HFS_fsOps.fsops_lookup(RootNode, "D2", &Dir1); | |
3356 | if (iErr) | |
3357 | printf("Dir read failed, D2 wasn't found in Root"); | |
3358 | UVFSFileNode File1 = NULL; | |
3359 | iErr = HFS_fsOps.fsops_lookup(Dir1, "a.txt", &File1); | |
3360 | ||
3361 | if (iErr) | |
3362 | { | |
3363 | printf("File not found!\n"); | |
3364 | return -1; | |
3365 | } | |
3366 | ||
3367 | // Change file size | |
3368 | // Set Attr, make F1 larger | |
3369 | iErr = SetAttrChangeSize(File1,12*1024); | |
3370 | printf("SetAttrChangeSize to 12K err [%d]\n",iErr); | |
3371 | if (iErr) | |
3372 | { | |
3373 | return iErr; | |
3374 | } | |
3375 | ||
3376 | iErr = SetAttrChangeSize(File1,4*1024); | |
3377 | printf("SetAttrChangeSize to 4 err [%d]\n",iErr); | |
3378 | if (iErr) | |
3379 | { | |
3380 | return iErr; | |
3381 | } | |
3382 | ||
3383 | iErr = SetAttrChangeSize(File1,0*1024); | |
3384 | printf("SetAttrChangeSize to 0 err [%d]\n",iErr); | |
3385 | if (iErr) | |
3386 | { | |
3387 | return iErr; | |
3388 | } | |
3389 | ||
3390 | iErr = SetAttrChangeSize(File1,8*1024*1024); | |
3391 | printf("SetAttrChangeSize to 120MB err [%d]\n",iErr); | |
3392 | if (iErr) | |
3393 | { | |
3394 | return iErr; | |
3395 | } | |
3396 | ||
3397 | iErr = SetAttrChangeMode(File1, UVFS_FA_MODE_GRP(UVFS_FA_MODE_RWX) | UVFS_FA_MODE_USR(UVFS_FA_MODE_RWX)); | |
3398 | printf("Changed file mode to RO err[ %d]\n",iErr); | |
3399 | if (iErr) | |
3400 | { | |
3401 | return iErr; | |
3402 | } | |
3403 | ||
3404 | iErr = SetAttrChangeUidGid(File1, 222, 555); | |
3405 | ||
3406 | printf("Changed Uid and Gid err [%d]\n", iErr); | |
3407 | if (iErr) | |
3408 | { | |
3409 | return iErr; | |
3410 | } | |
3411 | ||
3412 | iErr = SetAttrChangeAtimeMtime(File1); | |
3413 | ||
3414 | printf("Changed Atime and Mtime err [%d]\n", iErr); | |
3415 | if (iErr) | |
3416 | { | |
3417 | return iErr; | |
3418 | } | |
3419 | ||
3420 | HFS_fsOps.fsops_reclaim(File1); | |
3421 | ||
3422 | HFS_fsOps.fsops_reclaim(Dir1); | |
3423 | ||
3424 | iErr = HFS_fsOps.fsops_lookup(RootNode, "D2", &Dir1); | |
3425 | if (iErr) | |
3426 | printf("Dir read failed, D2 wasn't found in Root"); | |
3427 | iErr = HFS_fsOps.fsops_lookup(Dir1, "a.txt", &File1); | |
3428 | if (iErr) | |
3429 | { | |
3430 | printf("File not found! (2)\n"); | |
3431 | return -1; | |
3432 | } | |
3433 | ||
3434 | iErr = SetAttrChangeAtimeMtime(File1); | |
3435 | ||
3436 | printf("Changed Atime and Mtime (2) err [%d]\n", iErr); | |
3437 | if (iErr) | |
3438 | { | |
3439 | return iErr; | |
3440 | } | |
3441 | ||
3442 | HFS_fsOps.fsops_reclaim(File1); | |
3443 | ||
3444 | HFS_fsOps.fsops_reclaim(Dir1); | |
3445 | ||
3446 | return iErr; | |
3447 | } | |
3448 | ||
3449 | static char* gpcFSAttrs [] = { | |
3450 | UVFS_FSATTR_PC_LINK_MAX, | |
3451 | UVFS_FSATTR_PC_NAME_MAX, | |
3452 | UVFS_FSATTR_PC_NO_TRUNC, | |
3453 | UVFS_FSATTR_PC_FILESIZEBITS, | |
3454 | UVFS_FSATTR_PC_XATTR_SIZE_BITS, | |
3455 | UVFS_FSATTR_BLOCKSIZE, | |
3456 | UVFS_FSATTR_IOSIZE, | |
3457 | UVFS_FSATTR_TOTALBLOCKS, | |
3458 | UVFS_FSATTR_BLOCKSFREE, | |
3459 | UVFS_FSATTR_BLOCKSAVAIL, | |
3460 | UVFS_FSATTR_BLOCKSUSED, | |
3461 | UVFS_FSATTR_CNAME, | |
3462 | UVFS_FSATTR_FSTYPENAME, | |
3463 | UVFS_FSATTR_FSSUBTYPE, | |
3464 | UVFS_FSATTR_VOLNAME, | |
3465 | UVFS_FSATTR_VOLUUID, | |
3466 | UVFS_FSATTR_CAPS_FORMAT, | |
3467 | UVFS_FSATTR_CAPS_INTERFACES, | |
3468 | UVFS_FSATTR_LAST_MTIME, | |
3469 | UVFS_FSATTR_MOUNT_TIME | |
3470 | }; | |
3471 | ||
3472 | static int | |
3473 | HFSTest_GetFSAttr( UVFSFileNode RootNode ) | |
3474 | { | |
3475 | int iErr = 0; | |
3476 | size_t uLen = 512; | |
3477 | size_t uRetLen = 0; | |
3478 | UVFSFSAttributeValue* psAttrVal = (UVFSFSAttributeValue*)malloc(uLen); | |
3479 | assert( psAttrVal ); | |
3480 | ||
3481 | for ( uint32_t uIdx=0; uIdx<ARR_LEN(gpcFSAttrs); uIdx++ ) | |
3482 | { | |
3483 | memset( psAttrVal, 0, uLen ); | |
3484 | ||
3485 | iErr = HFS_fsOps.fsops_getfsattr( RootNode, gpcFSAttrs[uIdx], psAttrVal, uLen, &uRetLen ); | |
3486 | if ( iErr != 0 ) | |
3487 | { | |
3488 | printf( "fsops_getfsattr attr = %s return with error code [%d]\n", gpcFSAttrs[uIdx], iErr ); | |
3489 | goto exit; | |
3490 | } | |
3491 | ||
3492 | printf( "FSAttr = [%s] Value = [", gpcFSAttrs[uIdx]); | |
3493 | if ( UVFS_FSATTR_IS_BOOL( gpcFSAttrs[uIdx] ) ) | |
3494 | { | |
3495 | printf( psAttrVal->fsa_bool? "true" : "false" ); | |
3496 | } | |
3497 | else if ( UVFS_FSATTR_IS_NUMBER( gpcFSAttrs[uIdx] ) ) | |
3498 | { | |
3499 | printf( "%llu", psAttrVal->fsa_number ); | |
3500 | } | |
3501 | else if ( UVFS_FSATTR_IS_OPAQUE( gpcFSAttrs[uIdx] ) ) | |
3502 | { | |
3503 | printf("0x"); | |
3504 | for ( uint32_t uOp=0; uOp<uRetLen; uOp++ ) | |
3505 | { | |
3506 | printf( "%x", psAttrVal->fsa_opaque[uOp] ); | |
3507 | } | |
3508 | } | |
3509 | else if ( UVFS_FSATTR_IS_STRING( gpcFSAttrs[uIdx] ) ) | |
3510 | { | |
3511 | printf( "%s", psAttrVal->fsa_string ); | |
3512 | } | |
3513 | else | |
3514 | { | |
3515 | assert(0); | |
3516 | } | |
3517 | printf("].\n"); | |
3518 | } | |
3519 | ||
3520 | exit: | |
3521 | free(psAttrVal); | |
3522 | return (iErr); | |
3523 | } | |
3524 | ||
3525 | static int | |
3526 | HFSTest_WriteRead( UVFSFileNode RootNode ) | |
3527 | { | |
3528 | #define FILENAME "NewFileForTest" | |
3529 | #define MAXFILESIZE (1024*1024*1024) | |
3530 | ||
3531 | int iErr = 0; | |
3532 | UVFSFileNode psFile = NULL; | |
3533 | size_t iActuallyWrite = 0; | |
3534 | size_t iActuallyRead = 0; | |
3535 | void* pvOutBuf = malloc(MAXFILESIZE); | |
3536 | void* pvInBuf = malloc(MAXFILESIZE); | |
3537 | assert( pvOutBuf != NULL && pvInBuf != NULL ); | |
3538 | uint64_t* puOutBuf = pvOutBuf; | |
3539 | uint64_t* puInBuf = pvInBuf; | |
3540 | ||
3541 | // Create new file with size 50,000 Bytes | |
3542 | assert( CreateNewFile( RootNode, &psFile, FILENAME, 50000 ) == 0 ); | |
3543 | ||
3544 | // lets write 10,000 Bytes with 0xCD | |
3545 | memset(pvOutBuf, 0, MAXFILESIZE); | |
3546 | memset(pvInBuf, 0, MAXFILESIZE); | |
3547 | ||
3548 | memset(pvOutBuf, 0xCD, 10000); | |
3549 | ||
3550 | assert( HFS_fsOps.fsops_write( psFile, 0, 10000, pvOutBuf, &iActuallyWrite ) == 0 ); | |
3551 | assert( HFS_fsOps.fsops_read( psFile, 0, 10000, pvInBuf, &iActuallyRead ) == 0 ); | |
3552 | ||
3553 | // Lets test it... | |
3554 | for ( uint64_t uIdx=0; uIdx<(MAXFILESIZE/sizeof(uint64_t)); uIdx++ ) | |
3555 | { | |
3556 | assert( puInBuf[uIdx] == puOutBuf[uIdx] ); | |
3557 | } | |
3558 | ||
3559 | // Lets extend the file to 100,000 Bytes... | |
3560 | memset(pvOutBuf+10000, 0xED, 90000); | |
3561 | assert( HFS_fsOps.fsops_write( psFile, 10000, 90000, pvOutBuf+10000, &iActuallyWrite ) == 0 ); | |
3562 | assert( HFS_fsOps.fsops_read( psFile, 0, 100000, pvInBuf, &iActuallyRead ) == 0 ); | |
3563 | ||
3564 | // Lets test it... | |
3565 | for ( uint64_t uIdx=0; uIdx<(MAXFILESIZE/sizeof(uint64_t)); uIdx++ ) | |
3566 | { | |
3567 | assert( puInBuf[uIdx] == puOutBuf[uIdx] ); | |
3568 | } | |
3569 | ||
3570 | memset(pvOutBuf, 0, MAXFILESIZE); | |
3571 | memset(pvInBuf, 0, MAXFILESIZE); | |
3572 | assert( SetAttrChangeSize(psFile, 10000) == 0 ); | |
3573 | memset(pvOutBuf, 0xCD, 10000); | |
3574 | memset(pvOutBuf+20000, 0xBB, 10000); | |
3575 | ||
3576 | assert( HFS_fsOps.fsops_write( psFile, 20000, 10000, pvOutBuf+20000, &iActuallyWrite ) == 0 ); | |
3577 | assert( HFS_fsOps.fsops_read( psFile, 0, 30000, pvInBuf, &iActuallyRead ) == 0 ); | |
3578 | ||
3579 | // Lets test it... | |
3580 | for ( uint64_t uIdx=0; uIdx<(MAXFILESIZE/sizeof(uint64_t)); uIdx++ ) | |
3581 | { | |
3582 | assert( puInBuf[uIdx] == puOutBuf[uIdx] ); | |
3583 | } | |
3584 | ||
3585 | HFS_fsOps.fsops_reclaim( psFile ); | |
3586 | ||
3587 | goto exit; | |
3588 | ||
3589 | exit: | |
3590 | return iErr; | |
3591 | } | |
3592 | ||
3593 | static int | |
3594 | HFSTest_RandomIO( UVFSFileNode RootNode ) | |
3595 | { | |
3596 | #define MAX_IO_SIZE (1024*1024) | |
3597 | #define MAX_IO_OFFSET (80*MAX_IO_SIZE) | |
3598 | #define TEST_RUN_TIME_SEC (30) | |
3599 | ||
3600 | int iErr = 0; | |
3601 | UVFSFileNode psFile; | |
3602 | static mach_timebase_info_data_t sTimebaseInfo; | |
3603 | mach_timebase_info(&sTimebaseInfo); | |
3604 | ||
3605 | void* pvWriteBuf = malloc(MAX_IO_SIZE); | |
3606 | void* pvReadBuf = malloc(MAX_IO_SIZE); | |
3607 | ||
3608 | int* puBuf = pvWriteBuf; | |
3609 | for ( uint64_t uIdx=0; uIdx<(MAX_IO_SIZE/sizeof(int)); uIdx++ ) | |
3610 | { | |
3611 | puBuf[uIdx] = rand(); | |
3612 | } | |
3613 | ||
3614 | iErr = CreateNewFile( RootNode, &psFile, "SimpleFile", 0 ); | |
3615 | assert(iErr == 0); | |
3616 | ||
3617 | uint64_t start = mach_absolute_time(); | |
3618 | uint64_t elapsedSec = 0; | |
3619 | // while( elapsedSec < TEST_RUN_TIME_SEC ) | |
3620 | for(uint32_t uWriteReadCnt=1000; uWriteReadCnt; uWriteReadCnt--) | |
3621 | { | |
3622 | uint64_t uNextIOSize = rand() % MAX_IO_SIZE; | |
3623 | uint64_t uNextIOOffset = rand() % MAX_IO_OFFSET; | |
3624 | ||
3625 | printf("uNextIOSize = %llu, uNextIOOffset = %llu\n", uNextIOSize, uNextIOOffset); | |
3626 | ||
3627 | size_t iActuallyWrite; | |
3628 | size_t iActuallyRead; | |
3629 | ||
3630 | iErr = HFS_fsOps.fsops_write( psFile, uNextIOOffset, uNextIOSize, pvWriteBuf, &iActuallyWrite ); | |
3631 | assert(iErr==0); | |
3632 | iErr = HFS_fsOps.fsops_read( psFile, uNextIOOffset, uNextIOSize, pvReadBuf, &iActuallyRead ); | |
3633 | assert(iErr==0); | |
3634 | ||
3635 | uint8_t* puRead = pvReadBuf; | |
3636 | uint8_t* puWrite = pvWriteBuf; | |
3637 | for ( uint64_t uIdx=0; uIdx<uNextIOSize; uIdx++ ) | |
3638 | { | |
3639 | assert( puRead[uIdx] == puWrite[uIdx] ); | |
3640 | } | |
3641 | ||
3642 | uint64_t end = mach_absolute_time(); | |
3643 | uint64_t elapsed = end - start; | |
3644 | uint64_t elapsedNano = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom; | |
3645 | elapsedSec = elapsedNano / 1000 / 1000 / 1000; | |
3646 | } | |
3647 | ||
3648 | free(pvReadBuf); | |
3649 | free(pvWriteBuf); | |
3650 | ||
3651 | HFS_fsOps.fsops_reclaim(psFile); | |
3652 | ||
3653 | return 0; | |
3654 | } | |
3655 | ||
3656 | static int | |
3657 | HFSTest_HardLink( UVFSFileNode RootNode ) | |
3658 | { | |
3659 | int iErr = 0; | |
3660 | ||
3661 | // Validate files exist on media | |
3662 | UVFSFileNode psOriginalFile = NULL; | |
3663 | iErr = HFS_fsOps.fsops_lookup( RootNode, "original_file.txt", &psOriginalFile ); | |
3664 | printf("Lookup for original file err [%d]\n", iErr); | |
3665 | if ( iErr ) | |
3666 | return iErr; | |
3667 | ||
3668 | UVFSFileNode psFirstLink = NULL; | |
3669 | iErr = HFS_fsOps.fsops_lookup( RootNode, "first_link.txt", &psFirstLink ); | |
3670 | printf("Lookup for original file err [%d]\n", iErr); | |
3671 | if ( iErr ) | |
3672 | return iErr; | |
3673 | ||
3674 | UVFSFileNode psDirectory = NULL; | |
3675 | iErr = HFS_fsOps.fsops_lookup( RootNode, "dir", &psDirectory ); | |
3676 | printf("Lookup for original file err [%d]\n", iErr); | |
3677 | if ( iErr ) | |
3678 | return iErr; | |
3679 | ||
3680 | UVFSFileNode psSecondLink = NULL; | |
3681 | iErr = HFS_fsOps.fsops_lookup( psDirectory, "second_link.txt", &psSecondLink ); | |
3682 | printf("Lookup for original file err [%d]\n", iErr); | |
3683 | if ( iErr ) | |
3684 | return iErr; | |
3685 | ||
3686 | ||
3687 | UVFSFileAttributes sOutAttrs; | |
3688 | iErr = HFS_fsOps.fsops_getattr(psOriginalFile, &sOutAttrs); | |
3689 | printf("GetAttr for original file err [%d]\n", iErr); | |
3690 | if (iErr) | |
3691 | return iErr; | |
3692 | ||
3693 | if (sOutAttrs.fa_nlink != 3) | |
3694 | { | |
3695 | printf("nlink of original file should be 3, got [%d]\n", sOutAttrs.fa_nlink); | |
3696 | return 1; | |
3697 | } | |
3698 | ||
3699 | void* pvOriginalFileBuf = malloc(sOutAttrs.fa_size); | |
3700 | void* pvFirstLinkeBuf = malloc(sOutAttrs.fa_size); | |
3701 | void* pvSecondLinkeBuf = malloc(sOutAttrs.fa_size); | |
3702 | uint64_t* puOriginalFileBuf = pvOriginalFileBuf; | |
3703 | uint64_t* puFirstLinkeBuf = pvFirstLinkeBuf; | |
3704 | uint64_t* puSecondLinkeBuf = pvSecondLinkeBuf; | |
3705 | ||
3706 | size_t iActuallyRead = 0; | |
3707 | assert( HFS_fsOps.fsops_read( psOriginalFile, 0, sOutAttrs.fa_size, pvOriginalFileBuf, &iActuallyRead ) == 0 ); | |
3708 | assert( HFS_fsOps.fsops_read( psFirstLink, 0, sOutAttrs.fa_size, pvFirstLinkeBuf, &iActuallyRead ) == 0 ); | |
3709 | assert( HFS_fsOps.fsops_read( psSecondLink, 0, sOutAttrs.fa_size, pvSecondLinkeBuf, &iActuallyRead ) == 0 ); | |
3710 | ||
3711 | // Lets test if all links has the same content it... | |
3712 | for ( uint64_t uIdx=0; uIdx<(sOutAttrs.fa_size/sizeof(uint64_t)); uIdx++ ) | |
3713 | { | |
3714 | assert( puOriginalFileBuf[uIdx] == puFirstLinkeBuf[uIdx] ); | |
3715 | assert( puOriginalFileBuf[uIdx] == puSecondLinkeBuf[uIdx] ); | |
3716 | } | |
3717 | ||
3718 | // Save content of the original file and fill up 0x1000 0xAAs | |
3719 | void* pvNewContentBuf = malloc(sOutAttrs.fa_size + 1000); | |
3720 | uint64_t* puNewContentBuf = pvNewContentBuf; | |
3721 | ||
3722 | memcpy(pvNewContentBuf, pvOriginalFileBuf ,sOutAttrs.fa_size); | |
3723 | memset(pvNewContentBuf + sOutAttrs.fa_size, 0xAA,1000); | |
3724 | ||
3725 | assert( HFS_fsOps.fsops_write( psOriginalFile, 0, sOutAttrs.fa_size + 1000, pvNewContentBuf, &iActuallyRead ) == 0 ); | |
3726 | free(pvOriginalFileBuf); | |
3727 | free(pvFirstLinkeBuf); | |
3728 | free(pvSecondLinkeBuf); | |
3729 | ||
3730 | pvOriginalFileBuf = malloc(sOutAttrs.fa_size + 1000); | |
3731 | pvFirstLinkeBuf = malloc(sOutAttrs.fa_size + 1000); | |
3732 | pvSecondLinkeBuf = malloc(sOutAttrs.fa_size + 1000); | |
3733 | puOriginalFileBuf = pvOriginalFileBuf; | |
3734 | puFirstLinkeBuf = pvFirstLinkeBuf; | |
3735 | puSecondLinkeBuf = pvSecondLinkeBuf; | |
3736 | ||
3737 | // Make sure the file and its hardlinks have the new content | |
3738 | assert( HFS_fsOps.fsops_read( psOriginalFile, 0, sOutAttrs.fa_size + 1000, pvOriginalFileBuf, &iActuallyRead ) == 0 ); | |
3739 | assert( HFS_fsOps.fsops_read( psFirstLink, 0, sOutAttrs.fa_size + 1000, pvFirstLinkeBuf, &iActuallyRead ) == 0 ); | |
3740 | assert( HFS_fsOps.fsops_read( psSecondLink, 0, sOutAttrs.fa_size + 1000, pvSecondLinkeBuf, &iActuallyRead ) == 0 ); | |
3741 | for ( uint64_t uIdx=0; uIdx<((sOutAttrs.fa_size + 1000)/sizeof(uint64_t)); uIdx++ ) | |
3742 | { | |
3743 | assert( puOriginalFileBuf[uIdx] == puNewContentBuf[uIdx] ); | |
3744 | assert( puOriginalFileBuf[uIdx] == puFirstLinkeBuf[uIdx] ); | |
3745 | assert( puOriginalFileBuf[uIdx] == puSecondLinkeBuf[uIdx] ); | |
3746 | } | |
3747 | ||
3748 | iErr = HFS_fsOps.fsops_remove( RootNode, "original_file.txt", NULL); | |
3749 | printf( "Remove original file err [%d]\n", iErr ); | |
3750 | if ( iErr != 0 ) | |
3751 | return iErr; | |
3752 | ||
3753 | iErr = HFS_fsOps.fsops_getattr(psFirstLink, &sOutAttrs); | |
3754 | printf("GetAttr for first link err [%d]\n", iErr); | |
3755 | if (iErr) | |
3756 | return iErr; | |
3757 | ||
3758 | if (sOutAttrs.fa_nlink != 2) | |
3759 | { | |
3760 | printf("nlink of first link should be 2, got [%d]\n", sOutAttrs.fa_nlink); | |
3761 | return 1; | |
3762 | } | |
3763 | ||
3764 | RenameFile(psDirectory, psSecondLink,"second_link.txt", RootNode, psFirstLink,"first_link.txt" ); | |
3765 | ||
3766 | iErr = HFS_fsOps.fsops_getattr(psSecondLink, &sOutAttrs); | |
3767 | printf("GetAttr for second link err [%d]\n", iErr); | |
3768 | if (iErr) | |
3769 | return iErr; | |
3770 | ||
3771 | ||
3772 | if (sOutAttrs.fa_nlink != 2) | |
3773 | { | |
3774 | printf("nlink of first link should be 2, got [%d]\n", sOutAttrs.fa_nlink); | |
3775 | return 1; | |
3776 | } | |
3777 | ||
3778 | iErr = HFS_fsOps.fsops_remove( RootNode, "first_link.txt", NULL); | |
3779 | printf( "Remove first link err [%d]\n", iErr ); | |
3780 | if ( iErr != 0 ) | |
3781 | return iErr; | |
3782 | ||
3783 | free(pvOriginalFileBuf); | |
3784 | free(pvFirstLinkeBuf); | |
3785 | free(pvSecondLinkeBuf); | |
3786 | free(pvNewContentBuf); | |
3787 | HFS_fsOps.fsops_reclaim(psOriginalFile); | |
3788 | HFS_fsOps.fsops_reclaim(psFirstLink); | |
3789 | HFS_fsOps.fsops_reclaim(psSecondLink); | |
3790 | HFS_fsOps.fsops_reclaim(psDirectory); | |
3791 | ||
3792 | return iErr; | |
3793 | } | |
3794 | ||
3795 | static int | |
3796 | HFSTest_CreateHardLink( UVFSFileNode RootNode ) | |
3797 | { | |
3798 | uint32_t uOriginalFileSize = 500000; | |
3799 | ||
3800 | int iErr = 0; | |
3801 | UVFSFileNode psFile = NULL; | |
3802 | size_t iActuallyWrite = 0; | |
3803 | size_t iActuallyRead = 0; | |
3804 | void* pvOutBuf = malloc(uOriginalFileSize); | |
3805 | void* pvInBuf = malloc(uOriginalFileSize); | |
3806 | assert( pvOutBuf != NULL && pvInBuf != NULL ); | |
3807 | uint64_t* puOutBuf = pvOutBuf; | |
3808 | uint64_t* puInBuf = pvInBuf; | |
3809 | ||
3810 | // Create the original file with size 500,000 Bytes | |
3811 | iErr = CreateNewFile( RootNode, &psFile, "original_file.txt", uOriginalFileSize); | |
3812 | assert( iErr == 0 ); | |
3813 | ||
3814 | // lets write 10,000 Bytes with 0xCD | |
3815 | memset(pvOutBuf, 0, uOriginalFileSize); | |
3816 | memset(pvInBuf, 0, uOriginalFileSize); | |
3817 | ||
3818 | memset(pvOutBuf, 0xCD, uOriginalFileSize); | |
3819 | ||
3820 | assert( HFS_fsOps.fsops_write( psFile, 0, uOriginalFileSize, pvOutBuf, &iActuallyWrite ) == 0 ); | |
3821 | assert( HFS_fsOps.fsops_read( psFile, 0, uOriginalFileSize, pvInBuf, &iActuallyRead ) == 0 ); | |
3822 | ||
3823 | // Lets test it... | |
3824 | for ( uint64_t uIdx=0; uIdx<(uOriginalFileSize/sizeof(uint64_t)); uIdx++ ) | |
3825 | { | |
3826 | assert( puInBuf[uIdx] == puOutBuf[uIdx] ); | |
3827 | } | |
3828 | ||
3829 | UVFSFileNode psDirectory = NULL; | |
3830 | assert (CreateNewFolder(RootNode,&psDirectory,"dir") == 0); | |
3831 | assert (CreateHardLink(psFile,RootNode,"first_link.txt") == 0); | |
3832 | assert (CreateHardLink(psFile,psDirectory,"second_link.txt") == 0); | |
3833 | ||
3834 | HFS_fsOps.fsops_reclaim( psFile ); | |
3835 | HFS_fsOps.fsops_reclaim( psDirectory ); | |
3836 | ||
3837 | assert (HFSTest_HardLink( RootNode ) == 0); | |
3838 | ||
3839 | goto exit; | |
3840 | ||
3841 | exit: | |
3842 | return iErr; | |
3843 | } | |
3844 | ||
3845 | static int | |
3846 | HFSTest_RenameToHardlink( UVFSFileNode RootNode ) | |
3847 | { | |
3848 | UVFSFileNode psFile0 = NULL; | |
3849 | UVFSFileNode psFile1 = NULL; | |
3850 | UVFSFileNode psLink = NULL; | |
3851 | UVFSFileAttributes sOutAttrs = {0}; | |
3852 | ||
3853 | assert ( CreateNewFile( RootNode, &psFile0, "simple_file.txt", 0 ) == 0 ); | |
3854 | assert ( CreateNewFile( RootNode, &psFile1, "original_file.txt", 0 ) == 0 ); | |
3855 | assert ( CreateHardLink( psFile1, RootNode, "first_link.txt" ) == 0 ); | |
3856 | assert ( CreateHardLink( psFile1, RootNode, "second_link.txt" ) == 0 ); | |
3857 | assert ( HFS_fsOps.fsops_lookup( RootNode, "first_link.txt", &psLink ) == 0 ); | |
3858 | assert( RenameFile(RootNode, psFile0, "simple_file.txt", RootNode, psLink, "first_link.txt") == 0 ); | |
3859 | ||
3860 | assert( HFS_fsOps.fsops_getattr(psFile1, &sOutAttrs) == 0 ); | |
3861 | ||
3862 | assert( HFS_fsOps.fsops_reclaim(psFile0) == 0 ); | |
3863 | for ( uint32_t uIdx=0; uIdx<sOutAttrs.fa_nlink; uIdx++ ) | |
3864 | assert( HFS_fsOps.fsops_reclaim(psFile1) == 0 ); | |
3865 | ||
3866 | return 0; | |
3867 | } | |
3868 | ||
3869 | static int | |
3870 | HFSTest_JustMount( __unused UVFSFileNode RootNode ) | |
3871 | { | |
3872 | return 0; | |
3873 | } | |
3874 | ||
3875 | static int HFSTest_OpenJournal( __unused UVFSFileNode RootNode ) { | |
3876 | ||
3877 | printf("HFSTest_OpenJournal:\n"); | |
3878 | ||
3879 | return 0; | |
3880 | } | |
3881 | ||
3882 | static int HFSTest_WriteToJournal(UVFSFileNode RootNode ) { | |
3883 | int iErr = 0; | |
3884 | ||
3885 | printf("HFSTest_WriteToJournal:\n"); | |
3886 | ||
3887 | printf("Create a new folder:\n"); | |
3888 | UVFSFileNode TestFolder = NULL; | |
3889 | iErr = CreateNewFolder( RootNode, &TestFolder, "TestFolder"); | |
3890 | printf("CreateNewFolder err [%d]\n", iErr); | |
3891 | if (iErr) { | |
3892 | return iErr; | |
3893 | } | |
3894 | ||
3895 | printf("Create new file with size 0:\n"); | |
3896 | UVFSFileNode TestFile1 = NULL; | |
3897 | CreateNewFile(TestFolder, &TestFile1, "TestFile.txt",0); | |
3898 | printf("Create TestFile in TestFolder err [%d]\n", iErr); | |
3899 | if (iErr) { | |
3900 | return iErr; | |
3901 | } | |
3902 | ||
3903 | printf("Create new file with size 512:\n"); | |
3904 | UVFSFileNode TestFile2 = NULL; | |
3905 | CreateNewFile(TestFolder, &TestFile2, "TestFile2.txt",512); | |
3906 | printf("Create TestFile2 in TestFolder err [%d]\n", iErr); | |
3907 | if (iErr) { | |
3908 | return iErr; | |
3909 | } | |
3910 | ||
3911 | uint32_t uEntrySize = sizeof(UVFSDirEntryAttr) + MAX_UTF8_NAME_LENGTH; | |
3912 | UVFSDirEntryAttr *psReadDirTestsData = malloc(2*uEntrySize); | |
3913 | if (psReadDirTestsData == NULL) | |
3914 | return ENOMEM; | |
3915 | ||
3916 | UVFSDirEntryAttr *psCurrentReadDirTestsData = psReadDirTestsData; | |
3917 | SetExpectedAttr("TestFile.txt", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
3918 | iErr = HFS_fsOps.fsops_getattr( TestFile1, &psCurrentReadDirTestsData->dea_attrs ); | |
3919 | psCurrentReadDirTestsData = (UVFSDirEntryAttr *) ((void*) psCurrentReadDirTestsData + uEntrySize); | |
3920 | SetExpectedAttr("TestFile2.txt", UVFS_FA_TYPE_FILE, psCurrentReadDirTestsData); | |
3921 | iErr = HFS_fsOps.fsops_getattr( TestFile2, &psCurrentReadDirTestsData->dea_attrs ); | |
3922 | ||
3923 | printf("Read DIR attr:\n"); | |
3924 | iErr = ReadDirAttr(TestFolder, psReadDirTestsData, 2); | |
3925 | free(psReadDirTestsData); | |
3926 | printf("ReadDirAttr err [%d]\n", iErr); | |
3927 | if (iErr) { | |
3928 | goto exit; | |
3929 | } | |
3930 | ||
3931 | printf("Remove File1:\n"); | |
3932 | iErr = RemoveFile(TestFolder,"TestFile.txt"); | |
3933 | printf("Remove File TestFile from TestFolder err [%d]\n", iErr); | |
3934 | if (iErr) { | |
3935 | goto exit; | |
3936 | } | |
3937 | ||
3938 | printf("Remove File2:\n"); | |
3939 | iErr = RemoveFile(TestFolder,"TestFile2.txt"); | |
3940 | printf("Remove File TestFile2 from TestFolder err [%d]\n", iErr); | |
3941 | if (iErr) { | |
3942 | goto exit; | |
3943 | } | |
3944 | ||
3945 | printf("Remove TestFolder:\n"); | |
3946 | iErr = RemoveFolder(RootNode,"TestFolder"); | |
3947 | printf("Remove Folder TestFolder from Root err [%d]\n", iErr); | |
3948 | if (iErr) { | |
3949 | goto exit; | |
3950 | } | |
3951 | ||
3952 | exit: | |
3953 | HFS_fsOps.fsops_reclaim(TestFolder); | |
3954 | HFS_fsOps.fsops_reclaim(TestFile1); | |
3955 | HFS_fsOps.fsops_reclaim(TestFile2); | |
3956 | return iErr; | |
3957 | } | |
3958 | ||
3959 | static int __used | |
3960 | HFSTest_SetXattr( UVFSFileNode RootNode ) | |
3961 | { | |
3962 | const char * pcAttr = "com.apple.test.set"; | |
3963 | const char * pcAttr2 = "com.apple.test.set2"; | |
3964 | char pcData[] = "This is attribute data"; | |
3965 | char pcData2[] = "This is attribute data 2"; | |
3966 | int iErr = 0; | |
3967 | ||
3968 | UVFSFileNode TestFile = NULL; | |
3969 | iErr = HFS_fsOps.fsops_lookup( RootNode, "kl_set.test", &TestFile ); | |
3970 | if ( iErr ) | |
3971 | { | |
3972 | printf("Lookup err [%d]\n", iErr); | |
3973 | return iErr; | |
3974 | } | |
3975 | ||
3976 | // Add Attribute - create | |
3977 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr, pcData, strlen(pcData)+1, UVFSXattrHowCreate); | |
3978 | if ( iErr ) | |
3979 | { | |
3980 | printf("SetAttr err [%d]\n", iErr); | |
3981 | goto out; | |
3982 | } | |
3983 | ||
3984 | // Add Attribute - create with failure | |
3985 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr, pcData2, strlen(pcData2)+1, UVFSXattrHowCreate); | |
3986 | if ( iErr != EEXIST) | |
3987 | { | |
3988 | printf("SetAttr err [%d]\n", iErr); | |
3989 | goto out; | |
3990 | } | |
3991 | ||
3992 | // Add Attribute - set | |
3993 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr, pcData2, strlen(pcData2)+1, UVFSXattrHowSet); | |
3994 | if ( iErr ) | |
3995 | { | |
3996 | printf("SetAttr err [%d]\n", iErr); | |
3997 | goto out; | |
3998 | } | |
3999 | ||
4000 | // Add Attribute - replace | |
4001 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr, pcData, strlen(pcData)+1, UVFSXattrHowReplace); | |
4002 | if ( iErr ) | |
4003 | { | |
4004 | printf("SetAttr err [%d]\n", iErr); | |
4005 | goto out; | |
4006 | } | |
4007 | ||
4008 | // Add Attribute - replace with failure | |
4009 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr2, pcData, strlen(pcData)+1, UVFSXattrHowReplace); | |
4010 | if ( iErr != ENOATTR ) | |
4011 | { | |
4012 | printf("SetAttr err [%d]\n", iErr); | |
4013 | goto out; | |
4014 | } | |
4015 | ||
4016 | // Add Attribute - remove | |
4017 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr, pcData, strlen(pcData)+1, UVFSXattrHowRemove); | |
4018 | if ( iErr ) | |
4019 | { | |
4020 | printf("SetAttr err [%d]\n", iErr); | |
4021 | goto out; | |
4022 | } | |
4023 | ||
4024 | // Add Attribute - remove with failure | |
4025 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr, pcData, strlen(pcData)+1, UVFSXattrHowRemove); | |
4026 | if ( iErr != ENOATTR ) | |
4027 | { | |
4028 | printf("SetAttr err [%d]\n", iErr); | |
4029 | goto out; | |
4030 | } | |
4031 | ||
4032 | // Get Attribute - check nothing left | |
4033 | size_t actual_size = INT32_MAX; | |
4034 | iErr = HFS_fsOps.fsops_listxattr(TestFile, NULL, 0, &actual_size); | |
4035 | if ( iErr || (actual_size != 0)) | |
4036 | { | |
4037 | printf("ListAttr err [%d]\n", iErr); | |
4038 | goto out; | |
4039 | } | |
4040 | ||
4041 | // Add Attribute - create extended attribute and check content | |
4042 | const char * pcAttr3 = "com.apple.test.set3"; | |
4043 | uint8_t *pBuffer = NULL; | |
4044 | uint8_t *pBufferRet = NULL; | |
4045 | ||
4046 | // Test more than one sector and ending outside boundary. | |
4047 | #define ATTR_EXT_SIZE (5000) | |
4048 | ||
4049 | pBuffer = malloc(ATTR_EXT_SIZE); | |
4050 | pBufferRet = malloc(ATTR_EXT_SIZE); | |
4051 | ||
4052 | if ( pBuffer == NULL || pBufferRet == NULL) | |
4053 | { | |
4054 | iErr = ENOMEM; | |
4055 | goto out; | |
4056 | } | |
4057 | ||
4058 | for (int i = 0; i < ATTR_EXT_SIZE; ++i) | |
4059 | { | |
4060 | pBuffer[i] = i % 256; | |
4061 | pBufferRet[i] = 0xff; | |
4062 | } | |
4063 | ||
4064 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr3, pBuffer, ATTR_EXT_SIZE, UVFSXattrHowCreate); | |
4065 | if ( iErr ) | |
4066 | { | |
4067 | printf("SetAttr err [%d]\n", iErr); | |
4068 | goto out_mem; | |
4069 | } | |
4070 | ||
4071 | iErr = HFS_fsOps.fsops_getxattr(TestFile, pcAttr3, pBufferRet, ATTR_EXT_SIZE, &actual_size); | |
4072 | if ( iErr ) | |
4073 | { | |
4074 | printf("GetAttr err [%d]\n", iErr); | |
4075 | goto out_mem; | |
4076 | } | |
4077 | ||
4078 | // check data | |
4079 | assert(actual_size == ATTR_EXT_SIZE); | |
4080 | ||
4081 | for (int i = 0; i < ATTR_EXT_SIZE; ++i) | |
4082 | { | |
4083 | assert(pBuffer[i] == pBufferRet[i]); | |
4084 | } | |
4085 | ||
4086 | iErr = HFS_fsOps.fsops_setxattr(TestFile, pcAttr3, pBuffer, ATTR_EXT_SIZE, UVFSXattrHowRemove); | |
4087 | if ( iErr ) | |
4088 | { | |
4089 | printf("SetAttr err [%d]\n", iErr); | |
4090 | goto out_mem; | |
4091 | } | |
4092 | ||
4093 | out_mem: | |
4094 | free(pBuffer); | |
4095 | free(pBufferRet); | |
4096 | ||
4097 | out: | |
4098 | // Reclaim test file | |
4099 | HFS_fsOps.fsops_reclaim(TestFile); | |
4100 | ||
4101 | return iErr; | |
4102 | } | |
4103 | ||
4104 | ||
4105 | static int __used | |
4106 | HFSTest_ListXattr( UVFSFileNode RootNode ) | |
4107 | { | |
4108 | int iErr = 0; | |
4109 | ||
4110 | UVFSFileNode TestFile = NULL; | |
4111 | iErr = HFS_fsOps.fsops_lookup( RootNode, "kl.test", &TestFile ); | |
4112 | if ( iErr ) | |
4113 | { | |
4114 | printf("Lookup err [%d]\n", iErr); | |
4115 | return iErr; | |
4116 | } | |
4117 | ||
4118 | // Get required size | |
4119 | size_t actual_size = 0; | |
4120 | iErr = HFS_fsOps.fsops_listxattr(TestFile, NULL, 0, &actual_size); | |
4121 | if ( iErr ) | |
4122 | { | |
4123 | printf("ListAttr err [%d]\n", iErr); | |
4124 | goto out; | |
4125 | } | |
4126 | ||
4127 | // Get Attributes | |
4128 | size_t size = actual_size; | |
4129 | char *pcBuffer = malloc(size); | |
4130 | if ( pcBuffer == NULL ) | |
4131 | { | |
4132 | iErr = ENOMEM; | |
4133 | goto out; | |
4134 | } | |
4135 | ||
4136 | actual_size = 0; | |
4137 | iErr = HFS_fsOps.fsops_listxattr(TestFile, pcBuffer, size, &actual_size); | |
4138 | if ( iErr ) | |
4139 | { | |
4140 | printf("ListAttr err [%d]\n", iErr); | |
4141 | goto mem_err; | |
4142 | } | |
4143 | ||
4144 | // Just check it | |
4145 | assert(actual_size == size); | |
4146 | ||
4147 | // Print Attributes Names | |
4148 | size_t attr_size = 0; | |
4149 | char *pcAttribues = pcBuffer; | |
4150 | ||
4151 | while (attr_size < size) | |
4152 | { | |
4153 | // Get required size | |
4154 | actual_size = 0; | |
4155 | iErr = HFS_fsOps.fsops_getxattr(TestFile, pcAttribues, NULL, 0, &actual_size); | |
4156 | if ( iErr ) | |
4157 | { | |
4158 | printf("GetAttr size err [%d]\n", iErr); | |
4159 | goto mem_err; | |
4160 | } | |
4161 | ||
4162 | // Get Attributes | |
4163 | size_t bufsize = actual_size+1; | |
4164 | char *pcAttrBuffer = malloc(bufsize); | |
4165 | if ( pcAttrBuffer == NULL ) | |
4166 | { | |
4167 | iErr = ENOMEM; | |
4168 | goto mem_err; | |
4169 | } | |
4170 | bzero(pcAttrBuffer, bufsize); | |
4171 | ||
4172 | HFS_fsOps.fsops_getxattr(TestFile, pcAttribues, pcAttrBuffer, bufsize, &actual_size); | |
4173 | if ( iErr ) | |
4174 | { | |
4175 | printf("GetAttr err [%d]\n", iErr); | |
4176 | free(pcAttrBuffer); | |
4177 | goto mem_err; | |
4178 | } | |
4179 | ||
4180 | printf("Found attribute '%s' : %s\n", pcAttribues, pcAttrBuffer); | |
4181 | ||
4182 | free(pcAttrBuffer); | |
4183 | ||
4184 | size_t curr_attr_size = strlen(pcAttribues) + 1; | |
4185 | ||
4186 | attr_size += curr_attr_size; | |
4187 | pcAttribues += curr_attr_size; | |
4188 | } | |
4189 | ||
4190 | mem_err: | |
4191 | free(pcBuffer); | |
4192 | ||
4193 | out: | |
4194 | // Reclaim test file | |
4195 | HFS_fsOps.fsops_reclaim(TestFile); | |
4196 | ||
4197 | return iErr; | |
4198 | } | |
4199 | ||
4200 | /* | |
4201 | * Tests List Struct. | |
4202 | */ | |
4203 | ||
4204 | #if HFS_CRASH_TEST | |
4205 | #define ADD_TEST_WITH_CRASH_ABORT(testName, dmgPath, testHandler, CrashAbortType, CrashAbortCallback, CrashAbortCount) \ | |
4206 | { .pcTestName = testName, .pcDMGPath = dmgPath, .pfTestHandler = testHandler, \ | |
4207 | .eCrashID = CrashAbortType, .pAbortFunc = CrashAbortCallback, \ | |
4208 | .uCrashAbortCnt = CrashAbortCount \ | |
4209 | } | |
4210 | #endif | |
4211 | ||
4212 | #define ADD_TEST(testName, dmgPath, testHandler) \ | |
4213 | { .pcTestName = testName, .pcDMGPath = dmgPath, .pfTestHandler = testHandler, \ | |
4214 | } | |
4215 | ||
4216 | #define ADD_TEST_NO_SYNC(testName, dmgPath, testHandler) \ | |
4217 | { .pcTestName = testName, .pcDMGPath = dmgPath, .pfTestHandler = testHandler, \ | |
4218 | } | |
4219 | ||
4220 | TestData_S gsTestsData[] = { | |
4221 | #if 1 // Enable non-journal tests | |
4222 | ADD_TEST( "HFSTest_JustMount", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_JustMount ), | |
4223 | ADD_TEST( "HFSTest_ReadDefragmentFile", "/Volumes/SSD_Shared/FS_DMGs/HFSDeFragment.dmg", &HFSTest_ReadDefragmentFile ), | |
4224 | ADD_TEST( "HFSTest_RemoveDir", "/Volumes/SSD_Shared/FS_DMGs/HFSRemoveDir.dmg", &HFSTest_RemoveDir ), | |
4225 | ADD_TEST( "HFSTest_Remove", "/Volumes/SSD_Shared/FS_DMGs/HFSRemove.dmg", &HFSTest_Remove ), | |
4226 | ADD_TEST( "HFSTest_ReadDir", "/Volumes/SSD_Shared/FS_DMGs/HFSReadDir.dmg", &HFSTest_ReadDir ), | |
4227 | ADD_TEST( "HFSTest_ReadDirAttr", "/Volumes/SSD_Shared/FS_DMGs/HFSReadDir.dmg", &HFSTest_ReadDirAttr ), | |
4228 | ADD_TEST( "HFSTest_MakeDir", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_MakeDir ), | |
4229 | ADD_TEST( "HFSTest_SetAttr", "/Volumes/SSD_Shared/FS_DMGs/HFSSetAttr.dmg", &HFSTest_SetAttr ), | |
4230 | ADD_TEST( "HFSTest_ReadSymLink", "/Volumes/SSD_Shared/FS_DMGs/HFSReadSymLink.dmg", &HFSTest_ReadSymlink ), | |
4231 | ADD_TEST( "HFSTest_GetFSAttr", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_GetFSAttr ), | |
4232 | ADD_TEST( "HFSTest_Create", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_Create ), | |
4233 | ADD_TEST( "HFSTest_Symlink", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_Symlink ), | |
4234 | ADD_TEST( "HFSTest_SymlinkOnFile", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_SymlinkOnFile ), | |
4235 | ADD_TEST( "HFSTest_Rename", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_Rename ), | |
4236 | ADD_TEST( "HFSTest_WriteRead", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_WriteRead ), | |
4237 | ADD_TEST( "HFSTest_RandomIO", "/Volumes/SSD_Shared/FS_DMGs/HFS100MB.dmg", &HFSTest_RandomIO ), | |
4238 | ADD_TEST( "HFSTest_Create1000Files", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_Create1000Files ), | |
4239 | ADD_TEST( "HFSTest_HardLink", "/Volumes/SSD_Shared/FS_DMGs/HFSHardLink.dmg", &HFSTest_HardLink ), | |
4240 | ADD_TEST( "HFSTest_CreateHardLink", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_CreateHardLink ), | |
4241 | ADD_TEST( "HFSTest_RenameToHardlink", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_RenameToHardlink ), | |
4242 | ADD_TEST( "HFSTest_SetXattr", "/Volumes/SSD_Shared/FS_DMGs/HFSXattr.dmg", &HFSTest_SetXattr ), | |
4243 | ADD_TEST( "HFSTest_ListXattr", "/Volumes/SSD_Shared/FS_DMGs/HFSXattr.dmg", &HFSTest_ListXattr ), | |
4244 | ADD_TEST( "HFSTest_RootFillUp", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_RootFillUp ), | |
4245 | ADD_TEST( "HFSTest_ScanDir", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_ScanDir ), | |
4246 | ADD_TEST( "HFSTest_MultiThreadedRW", CREATE_HFS_DMG, &HFSTest_MultiThreadedRW_wJournal ), | |
4247 | ADD_TEST_NO_SYNC( "HFSTest_ValidateUnmount", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_ValidateUnmount ), | |
4248 | ADD_TEST( "HFSTest_ScanID", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_ScanID ), | |
4249 | #endif | |
4250 | #if 1 // Enbale journal-tests | |
4251 | ADD_TEST( "HFSTest_OpenJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_OpenJournal ), | |
4252 | ADD_TEST( "HFSTest_WriteToJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_WriteToJournal ), | |
4253 | ADD_TEST( "HFSTest_JustMount_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_JustMount ), | |
4254 | ADD_TEST( "HFSTest_ReadDefragmentFile_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-DeFragment.dmg", &HFSTest_ReadDefragmentFile ), | |
4255 | ADD_TEST( "HFSTest_RemoveDir_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-RemoveDir.dmg", &HFSTest_RemoveDir ), | |
4256 | ADD_TEST( "HFSTest_Remove_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Remove.dmg", &HFSTest_Remove ), | |
4257 | ADD_TEST( "HFSTest_ReadDir_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-ReadDir.dmg", &HFSTest_ReadDir ), | |
4258 | ADD_TEST( "HFSTest_ReadDirAttr_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-ReadDir.dmg", &HFSTest_ReadDirAttr ), | |
4259 | ADD_TEST( "HFSTest_MakeDir_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_MakeDir ), | |
4260 | ADD_TEST( "HFSTest_SetAttr_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-SetAttr.dmg", &HFSTest_SetAttr ), | |
4261 | ADD_TEST( "HFSTest_ReadSymLink_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-ReadSymLink.dmg", &HFSTest_ReadSymlink ), | |
4262 | ADD_TEST( "HFSTest_GetFSAttr_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_GetFSAttr ), | |
4263 | ADD_TEST( "HFSTest_Create_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_Create ), | |
4264 | ADD_TEST( "HFSTest_Symlink_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_Symlink ), | |
4265 | ADD_TEST( "HFSTest_SymlinkOnFile", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", &HFSTest_SymlinkOnFile ), | |
4266 | ADD_TEST( "HFSTest_Rename_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_Rename ), | |
4267 | ADD_TEST( "HFSTest_WriteRead_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_WriteRead ), | |
4268 | ADD_TEST( "HFSTest_RandomIO_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-144MB.dmg", &HFSTest_RandomIO ), | |
4269 | ADD_TEST( "HFSTest_Create1000Files_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-EmptyLarge.dmg", &HFSTest_Create1000Files ), | |
4270 | ADD_TEST( "HFSTest_HardLink_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-HardLink.dmg", &HFSTest_HardLink ), | |
4271 | ADD_TEST( "HFSTest_CreateHardLink_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-EmptyLarge.dmg", &HFSTest_CreateHardLink ), | |
4272 | ADD_TEST( "HFSTest_RootFillUp_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-EmptyLarge.dmg", &HFSTest_RootFillUp ), | |
4273 | ADD_TEST( "HFSTest_MultiThreadedRW_wJournal", "", &HFSTest_MultiThreadedRW_wJournal ), | |
4274 | ADD_TEST( "HFSTest_DeleteAHugeDefragmentedFile_wJournal", "", &HFSTest_DeleteAHugeDefragmentedFile_wJournal ), | |
4275 | ADD_TEST( "HFSTest_CreateJournal_Sparse", CREATE_SPARSE_VOLUME, &HFSTest_OpenJournal ), | |
4276 | ADD_TEST( "HFSTest_MakeDirAndKeep_Sparse", CREATE_SPARSE_VOLUME, &HFSTest_MakeDirAndKeep ), | |
4277 | ADD_TEST( "HFSTest_CreateAndWriteToJournal_Sparse", CREATE_SPARSE_VOLUME, &HFSTest_WriteToJournal ), | |
4278 | ADD_TEST( "HFSTest_MultiThreadedRW_wJournal_Sparse", CREATE_SPARSE_VOLUME, &HFSTest_MultiThreadedRW_wJournal ), | |
4279 | ADD_TEST( "HFSTest_ScanDir", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_ScanDir ), | |
4280 | ADD_TEST_NO_SYNC( "HFSTest_ValidateUnmount_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_ValidateUnmount_wJournal ), | |
4281 | ADD_TEST( "HFSTest_Corrupted2ndDiskImage", "/Volumes/SSD_Shared/FS_DMGs/corrupted_80M.dmg.sparseimage", | |
4282 | &HFSTest_Corrupted2ndDiskImage ), | |
4283 | ADD_TEST( "HFSTest_ScanID", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", &HFSTest_ScanID ), | |
4284 | ||
4285 | #endif | |
4286 | #if HFS_CRASH_TEST | |
4287 | // The following 2 tests checks mount after unmount, no-journal | |
4288 | ADD_TEST_WITH_CRASH_ABORT( "HFSTest_OneSync", "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg", | |
4289 | &HFSTest_OneSync, CRASH_ABORT_RANDOM, HFSTest_SaveDMG, 0 ), | |
4290 | ADD_TEST( "HFSTest_ConfirmTestFolderExists", TEMP_DMG_BKUP, &HFSTest_ConfirmTestFolderExists ), | |
4291 | ||
4292 | // The following 2 tests checks mount after unmount with journal | |
4293 | ADD_TEST_WITH_CRASH_ABORT( "HFSTest_OneSync_wJournal", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4294 | &HFSTest_OneSync, CRASH_ABORT_RANDOM, HFSTest_SaveDMG, 0 ), | |
4295 | ADD_TEST( "HFSTest_ConfirmTestFolderExists", TEMP_DMG_BKUP, &HFSTest_ConfirmTestFolderExists ), | |
4296 | ||
4297 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_OpenJournal_wCrashOnMakeDir", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4298 | &HFSTest_OpenJournal, CRASH_ABORT_MAKE_DIR, HFSTest_FailTestOnCrashAbort, 0), | |
4299 | ||
4300 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_OpenJournal_wCrashAfterBlockData", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4301 | &HFSTest_OpenJournal, CRASH_ABORT_JOURNAL_AFTER_BLOCK_DATA, HFSTest_CrashAbort, 0), | |
4302 | ||
4303 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_OpenJournal_wCrashAfterJournalData", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4304 | &HFSTest_OpenJournal, CRASH_ABORT_JOURNAL_AFTER_JOURNAL_DATA, HFSTest_CrashAbort, 0), | |
4305 | ||
4306 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_OpenJournal_wCrashAfterJournalHeader", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4307 | &HFSTest_OpenJournal, CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER, HFSTest_CrashAbort, 0), | |
4308 | ||
4309 | ADD_TEST_WITH_CRASH_ABORT("MultiThreadedRW_wJournal_RandomCrash", CREATE_SPARSE_VOLUME, | |
4310 | &MultiThreadedRW_wJournal_RandomCrash, CRASH_ABORT_RANDOM, HFSTest_CrashAbortAtRandom, 0), | |
4311 | ||
4312 | // The following 2 tests check journal replay, make sure the drive is mountable, and the created fonder DOES exist | |
4313 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_MakeDirAndKeep_wCrashAfterJournalHeader", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4314 | &HFSTest_MakeDirAndKeep, CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER, HFSTest_CrashAbortOnMkDir, 0), | |
4315 | ADD_TEST( "HFSTest_ConfirmTestFolderExists", TEMP_DMG_BKUP, &HFSTest_ConfirmTestFolderExists ), | |
4316 | ||
4317 | // The following 2 tests check journal replay, make sure the drive is mountable, and the created fonder does NOT exist | |
4318 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_MakeDirAndKeep_wCrashAfterJournalData", "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4319 | &HFSTest_MakeDirAndKeep, CRASH_ABORT_JOURNAL_AFTER_JOURNAL_DATA, HFSTest_CrashAbortOnMkDir, 0), | |
4320 | ADD_TEST( "HFSTest_ConfirmTestFolderDoesntExists", TEMP_DMG_BKUP, &HFSTest_ConfirmTestFolderDoesntExists ), | |
4321 | ||
4322 | // The following 2 tests check journal replay, make sure the drive is mountable, and the created fonder DOES exist | |
4323 | ADD_TEST_WITH_CRASH_ABORT("HFSTest_MakeDirAndKeep_wCrashAfterJournalHeader_Sparse", CREATE_SPARSE_VOLUME, | |
4324 | &HFSTest_MakeDirAndKeep, CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER, HFSTest_CrashAbortOnMkDir, 1), | |
4325 | ADD_TEST( "HFSTest_ConfirmTestFolderExists", TEMP_DMG_BKUP_SPARSE, &HFSTest_ConfirmTestFolderExists ), | |
4326 | #endif | |
4327 | ||
4328 | }; | |
4329 | ||
4330 | void *SyncerThread(void *pvArgs) { | |
4331 | ||
4332 | int iErr = 0; | |
4333 | TestData_S *psTestData = pvArgs; | |
4334 | ||
4335 | printf("Syncer Thread runs every %u mS\n", guSyncerPeriod); | |
4336 | ||
4337 | while(psTestData->bSyncerOn) { | |
4338 | usleep(guSyncerPeriod * 1000); | |
4339 | iErr = HFS_fsOps.fsops_sync(psTestData->psRootNode); | |
4340 | psTestData->uSyncerCount++; | |
4341 | if (iErr) { | |
4342 | printf("fsops_sync returned %d\n", iErr); | |
4343 | break; | |
4344 | } | |
4345 | } | |
4346 | ||
4347 | TesterThreadReturnStatus_S *psReturnStatus = malloc(sizeof(TesterThreadReturnStatus_S)); | |
4348 | assert(psReturnStatus); | |
4349 | memset(psReturnStatus, 0, sizeof(*psReturnStatus)); | |
4350 | ||
4351 | printf("Syncer returns %d\n", iErr); | |
4352 | ||
4353 | psReturnStatus->iErr = iErr; | |
4354 | ||
4355 | return((void*)psReturnStatus); | |
4356 | } | |
4357 | ||
4358 | static int KickOffSyncerThread(TestData_S *psTestData) { | |
4359 | ||
4360 | int iErr = 0; | |
4361 | ||
4362 | if (guSyncerPeriod == 0) { | |
4363 | goto exit; | |
4364 | } | |
4365 | psTestData->bSyncerOn = true; | |
4366 | ||
4367 | pthread_attr_t sAttr; | |
4368 | pthread_attr_init(&sAttr); | |
4369 | pthread_attr_setdetachstate(&sAttr, PTHREAD_CREATE_JOINABLE); | |
4370 | ||
4371 | iErr = pthread_create(&psTestData->sSyncerThread, &sAttr, SyncerThread, psTestData); | |
4372 | ||
4373 | pthread_attr_destroy(&sAttr); | |
4374 | ||
4375 | exit: | |
4376 | return(iErr); | |
4377 | } | |
4378 | ||
4379 | static int ShutdownSyncerThread(TestData_S *psTestData) { | |
4380 | ||
4381 | int iErr = 0; | |
4382 | TesterThreadReturnStatus_S *psReturnStatus = NULL; | |
4383 | ||
4384 | if (guSyncerPeriod == 0) { | |
4385 | goto exit; | |
4386 | } | |
4387 | ||
4388 | psTestData->bSyncerOn = false; | |
4389 | iErr = pthread_join(psTestData->sSyncerThread, (void*)&psReturnStatus); | |
4390 | if (iErr) { | |
4391 | printf("Error waiting for Syncer thread! %d\n", iErr); | |
4392 | goto exit; | |
4393 | } | |
4394 | ||
4395 | printf("Syncer Thead ran %u times (iErr %d)\n", psTestData->uSyncerCount, iErr); | |
4396 | ||
4397 | assert(psReturnStatus); | |
4398 | ||
4399 | iErr = psReturnStatus->iErr; | |
4400 | if (iErr) { | |
4401 | printf("Syncer thread returned iErr = %d\n", iErr); | |
4402 | goto exit; | |
4403 | } | |
4404 | ||
4405 | exit: | |
4406 | if (psReturnStatus) { | |
4407 | free(psReturnStatus); | |
4408 | } | |
4409 | ||
4410 | return(iErr); | |
4411 | } | |
4412 | ||
4413 | static int HFSTest_RunTest(TestData_S *psTestData) { | |
4414 | UVFSScanVolsRequest sScanVolsReq = {0}; | |
4415 | UVFSScanVolsReply sScanVolsReply = {0}; | |
4416 | int iErr = 0; | |
4417 | int iFD = HFSTest_PrepareEnv( psTestData ); | |
4418 | giFD = iFD; | |
4419 | ||
4420 | iErr = HFS_fsOps.fsops_taste( iFD ); | |
4421 | printf("Taste err [%d]\n",iErr); | |
4422 | if ( iErr ) { | |
4423 | close(iFD); | |
4424 | HFSTest_DestroyEnv( iFD ); | |
4425 | return(iErr); | |
4426 | } | |
4427 | ||
4428 | iErr = HFS_fsOps.fsops_scanvols( iFD, &sScanVolsReq, &sScanVolsReply ); | |
4429 | printf("ScanVols err [%d]\n", iErr); | |
4430 | if ( iErr ) | |
4431 | { | |
4432 | close(iFD); | |
4433 | HFSTest_DestroyEnv( iFD ); | |
4434 | return(iErr); | |
4435 | } | |
4436 | ||
4437 | UVFSFileNode RootNode = NULL; | |
4438 | iErr = HFS_fsOps.fsops_mount( iFD, sScanVolsReply.sr_volid, 0, NULL, &RootNode ); | |
4439 | printf("Mount err [%d]\n", iErr); | |
4440 | if ( iErr ) | |
4441 | { | |
4442 | close(iFD); | |
4443 | HFSTest_DestroyEnv( iFD ); | |
4444 | return(iErr); | |
4445 | } | |
4446 | ||
4447 | psTestData->psRootNode = RootNode; | |
4448 | iErr = KickOffSyncerThread(psTestData); | |
4449 | if ( iErr ) { | |
4450 | close(iFD); | |
4451 | HFSTest_DestroyEnv( iFD ); | |
4452 | return(iErr); | |
4453 | } | |
4454 | ||
4455 | // Execute the test | |
4456 | iErr = psTestData->pfTestHandler( RootNode ); | |
4457 | printf("Test [%s] finish with error code [%d]\n", psTestData->pcTestName, iErr); | |
4458 | #if HFS_CRASH_TEST | |
4459 | if (psTestData->eCrashID == CRASH_ABORT_NONE) | |
4460 | #endif | |
4461 | if ( iErr ) { | |
4462 | close(iFD); | |
4463 | HFSTest_DestroyEnv( iFD ); | |
4464 | return(iErr); | |
4465 | } | |
4466 | ||
4467 | iErr = ShutdownSyncerThread(psTestData); | |
4468 | if ( iErr ) { | |
4469 | close(iFD); | |
4470 | HFSTest_DestroyEnv( iFD ); | |
4471 | return(iErr); | |
4472 | } | |
4473 | ||
4474 | iErr = HFS_fsOps.fsops_unmount(RootNode, UVFSUnmountHintNone); | |
4475 | printf("UnMount err [%d]\n", iErr); | |
4476 | if ( iErr ) { | |
4477 | close(iFD); | |
4478 | HFSTest_DestroyEnv( iFD ); | |
4479 | return(iErr); | |
4480 | } | |
4481 | ||
4482 | HFSTest_PrintCacheStats(); | |
4483 | ||
4484 | #if HFS_CRASH_TEST | |
4485 | if (psTestData->eCrashID != CRASH_ABORT_NONE) { | |
4486 | ||
4487 | // Execute post crash analysis | |
4488 | iErr = psTestData->pAbortFunc(psTestData, | |
4489 | gsCrashReport.eCrashID, | |
4490 | iFD, | |
4491 | gsCrashReport.psNode, | |
4492 | gsCrashReport.pSyncerThread); | |
4493 | ||
4494 | printf("Analysis [%s] finished with error code [%d]\n", psTestData->pcTestName, iErr); | |
4495 | ||
4496 | if (iErr) { | |
4497 | HFSTest_DestroyEnv( iFD ); | |
4498 | return(iErr); | |
4499 | } | |
4500 | } else | |
4501 | #endif | |
4502 | { | |
4503 | // close file | |
4504 | close(iFD); | |
4505 | ||
4506 | //assert(gCacheStat.buf_cache_size == 0); | |
4507 | ||
4508 | // Run fsck | |
4509 | char pcFsckCmd[512] = {0}; | |
4510 | strcat( pcFsckCmd, "/System/Library/Filesystems/hfs.fs/Contents/Resources/fsck_hfs -fd /dev/disk"); | |
4511 | ||
4512 | strcat( pcFsckCmd, pcLastDevPathName ); | |
4513 | if (pcDevNum[0] != '\0') { | |
4514 | strcat( pcFsckCmd, "s" ); | |
4515 | strcat( pcFsckCmd, pcDevNum ); | |
4516 | } | |
4517 | printf("Execute %s\n", pcFsckCmd); | |
4518 | iErr = system( pcFsckCmd ); | |
4519 | if ( iErr ) | |
4520 | { | |
4521 | printf( "*** Fsck CMD failed! (%d)\n", iErr); | |
4522 | HFSTest_DestroyEnv( iFD ); | |
4523 | return(iErr); | |
4524 | } else { | |
4525 | printf( "*** Fsck CMD succeeded!\n"); | |
4526 | } | |
4527 | ||
4528 | HFSTest_DestroyEnv( iFD ); | |
4529 | } | |
4530 | return(iErr); | |
4531 | } | |
4532 | ||
4533 | #if HFS_CRASH_TEST | |
4534 | int HFSTest_CrashAbort_Hanlder(CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, pthread_t pSyncerThread) { | |
4535 | printf("HFSTest_CrashAbort_Hanlder (%u):\n", guCrashAbortCnt); | |
4536 | if (guCrashAbortCnt) { | |
4537 | guCrashAbortCnt--; | |
4538 | return(0); | |
4539 | } | |
4540 | ||
4541 | close(iFD); // prevent additional writes to media | |
4542 | if (pSyncerThread == pthread_self()) { | |
4543 | printf("Crash Abort on Syncer Thread!\n"); | |
4544 | } | |
4545 | ||
4546 | gsCrashReport.uCrashCount++; | |
4547 | gsCrashReport.eCrashID = eAbort; | |
4548 | gsCrashReport.iFD = iFD; | |
4549 | gsCrashReport.psNode = psNode; | |
4550 | gsCrashReport.pSyncerThread = pSyncerThread; | |
4551 | ||
4552 | return(0); | |
4553 | } | |
4554 | #endif | |
4555 | ||
4556 | ||
4557 | int hfs_tester_run_fsck(void) | |
4558 | { | |
4559 | // Journaled | |
4560 | int iErr = HFS_fsOps.fsops_init(); | |
4561 | printf("Init err [%d]\n",iErr); | |
4562 | if (iErr) | |
4563 | exit(-1); | |
4564 | ||
4565 | TestData_S sTestData = { | |
4566 | .pcTestName = "hfs_tester_run_fsck", | |
4567 | .pcDMGPath = "/Volumes/SSD_Shared/FS_DMGs/HFSJ-Empty.dmg", | |
4568 | }; | |
4569 | ||
4570 | int iFD = HFSTest_PrepareEnv(&sTestData); | |
4571 | ||
4572 | iErr = HFS_fsOps.fsops_taste( iFD ); | |
4573 | printf("Taste err [%d]\n",iErr); | |
4574 | if ( iErr ) { | |
4575 | close(iFD); | |
4576 | HFSTest_DestroyEnv( iFD ); | |
4577 | return(iErr); | |
4578 | } | |
4579 | ||
4580 | iErr = HFS_fsOps.fsops_check(iFD, 0, NULL, QUICK_CHECK); | |
4581 | printf("Check err [%d]\n",iErr); | |
4582 | if (iErr) | |
4583 | exit(-1); | |
4584 | ||
4585 | close(iFD); | |
4586 | HFSTest_DestroyEnv( iFD ); | |
4587 | ||
4588 | // Non-Journaled | |
4589 | iErr = HFS_fsOps.fsops_init(); | |
4590 | printf("Init err [%d]\n",iErr); | |
4591 | if (iErr) | |
4592 | exit(-1); | |
4593 | ||
4594 | sTestData.pcDMGPath = "/Volumes/SSD_Shared/FS_DMGs/HFSEmpty.dmg"; | |
4595 | ||
4596 | iFD = HFSTest_PrepareEnv(&sTestData); | |
4597 | ||
4598 | iErr = HFS_fsOps.fsops_taste( iFD ); | |
4599 | printf("Taste err [%d]\n",iErr); | |
4600 | if ( iErr ) { | |
4601 | close(iFD); | |
4602 | HFSTest_DestroyEnv( iFD ); | |
4603 | return(iErr); | |
4604 | } | |
4605 | ||
4606 | iErr = HFS_fsOps.fsops_check(iFD, 0, NULL, QUICK_CHECK); | |
4607 | printf("Check err [%d]\n",iErr); | |
4608 | if (iErr) | |
4609 | exit(-1); | |
4610 | ||
4611 | close(iFD); | |
4612 | HFSTest_DestroyEnv( iFD ); | |
4613 | return iErr; | |
4614 | } | |
4615 | ||
4616 | int hfs_tester_run(uint32_t uFirstTest, uint32_t uLastTest) | |
4617 | { | |
4618 | uint32_t uTestRan = 0; | |
4619 | int iErr = HFS_fsOps.fsops_init(); | |
4620 | printf("Init err [%d]\n",iErr); | |
4621 | if (iErr) | |
4622 | exit(-1); | |
4623 | ||
4624 | uint32_t uAvailTests = sizeof(gsTestsData)/sizeof(gsTestsData[0]); | |
4625 | if ((!uLastTest) || | |
4626 | (uLastTest > uAvailTests)) { | |
4627 | ||
4628 | uLastTest = uAvailTests; | |
4629 | } | |
4630 | ||
4631 | for ( unsigned uTestNum=uFirstTest; uTestNum < uLastTest ; uTestNum++ ) | |
4632 | { | |
4633 | printf("******************************************************************************************\n"); | |
4634 | printf("**** about to run test [%s] [%u] \n", gsTestsData[uTestNum].pcTestName, uTestNum); | |
4635 | printf("******************************************************************************************\n"); | |
4636 | ||
4637 | #if HFS_CRASH_TEST | |
4638 | HFSTest_ClearCrashAbortFunctionArray(); | |
4639 | ||
4640 | if (gsTestsData[uTestNum].eCrashID) { | |
4641 | // Inject Crach condition | |
4642 | CrashAbort_E eCrashID = gsTestsData[uTestNum].eCrashID; | |
4643 | printf( "Adding Crash-Abort Function at (%u), %s.\n", eCrashID, ppcCrashAbortDesc[eCrashID] ); | |
4644 | guCrashAbortCnt = gsTestsData[uTestNum].uCrashAbortCnt; | |
4645 | gpsCrashAbortFunctionArray[eCrashID] = HFSTest_CrashAbort_Hanlder; | |
4646 | memset(&gsCrashReport, 0, sizeof(gsCrashReport)); | |
4647 | } | |
4648 | #endif | |
4649 | ||
4650 | iErr = HFSTest_RunTest(&gsTestsData[uTestNum]); | |
4651 | ||
4652 | if (iErr) { | |
4653 | exit(-1); | |
4654 | } | |
4655 | uTestRan++; | |
4656 | } | |
4657 | ||
4658 | HFS_fsOps.fsops_fini(); | |
4659 | ||
4660 | printf("*** Run %u out of %u tests successfully\n", uTestRan, uAvailTests); | |
4661 | ||
4662 | return 0; | |
4663 | } | |
4664 | ||
4665 | /*******************************************/ | |
4666 | /*******************************************/ | |
4667 | /*******************************************/ | |
4668 | // Predefined Tests END. | |
4669 | /*******************************************/ | |
4670 | /*******************************************/ | |
4671 | /*******************************************/ | |
4672 | int main( int argc, const char * argv[] ) { | |
4673 | uint32_t uFirstTest = 0; | |
4674 | uint32_t uLastTest = 0; | |
4675 | ||
4676 | time_t sTimeStamp = time(NULL); | |
4677 | char pcTimeStamp[256] = {0}; | |
4678 | strcpy(pcTimeStamp, ctime(&sTimeStamp)); | |
4679 | pcTimeStamp[strlen(pcTimeStamp)-1] = '\0'; // remove \n | |
4680 | sprintf(gpcResultsFolder, "\"/tmp/%s\"", pcTimeStamp); | |
4681 | printf("*** gpcResultsFolder is %s\n", gpcResultsFolder); | |
4682 | ||
4683 | ||
4684 | if ((argc < 2) || (argc > 5)) | |
4685 | { | |
4686 | printf("Usage : livefiles_hfs_tester < dev-path / RUN_HFS_TESTS > [First Test] [Last Test] [Syncer Period (mS)]\n"); | |
4687 | exit(1); | |
4688 | } | |
4689 | ||
4690 | printf( "livefiles_hfs_tester %s (%u)\n", argv[1], uFirstTest ); | |
4691 | ||
4692 | if (argc >= 3) { | |
4693 | sscanf(argv[2], "%u", &uFirstTest); | |
4694 | } | |
4695 | ||
4696 | if (argc >= 4) { | |
4697 | sscanf(argv[3], "%u", &uLastTest); | |
4698 | } | |
4699 | ||
4700 | if (argc >= 5) { | |
4701 | sscanf(argv[4], "%u", &guSyncerPeriod); | |
4702 | } | |
4703 | ||
4704 | if ( strncmp(argv[1], HFS_TEST_PREFIX, strlen(HFS_TEST_PREFIX)) == 0 ) | |
4705 | { | |
4706 | int err = hfs_tester_run(uFirstTest, uLastTest); | |
4707 | printf("*** hfs_tester_run return status : %d ***\n", err); | |
4708 | if (err >= 256) err = -1; // exit code overflow | |
4709 | exit(err); | |
4710 | ||
4711 | } else if ( strncmp(argv[1], HFS_RUN_FSCK, strlen(HFS_RUN_FSCK)) == 0 ) | |
4712 | { | |
4713 | int err = hfs_tester_run_fsck(); | |
4714 | printf("*** hfs_tester_run_fsck return status : %d ***\n", err); | |
4715 | if (err >= 256) err = -1; // exit code overflow | |
4716 | exit(err); | |
4717 | } | |
4718 | ||
4719 | UVFSScanVolsRequest sScanVolsReq = {0}; | |
4720 | UVFSScanVolsReply sScanVolsReply = {0}; | |
4721 | int err = 0; | |
4722 | int fd = open( argv[1], O_RDWR ); | |
4723 | int uCycleCounter = 0; | |
4724 | ||
4725 | UVFSFileNode RootNode = NULL; | |
4726 | if(fd < 0) | |
4727 | { | |
4728 | printf("Failed to open [%s] errno %d\n", argv[1], errno); | |
4729 | return EBADF; | |
4730 | } | |
4731 | ||
4732 | do | |
4733 | { | |
4734 | ||
4735 | err = HFS_fsOps.fsops_init(); | |
4736 | printf("Init err [%d]\n",err); | |
4737 | if (err) break; | |
4738 | ||
4739 | err = HFS_fsOps.fsops_taste(fd); | |
4740 | printf("Taste err [%d]\n",err); | |
4741 | if (err) break; | |
4742 | ||
4743 | err = HFS_fsOps.fsops_scanvols(fd, &sScanVolsReq, &sScanVolsReply); | |
4744 | printf("ScanVols err [%d]\n",err); | |
4745 | if (err) break; | |
4746 | ||
4747 | err = HFS_fsOps.fsops_mount(fd, sScanVolsReply.sr_volid, 0, NULL, &RootNode); | |
4748 | printf("Mount err [%d]\n",err); | |
4749 | if (err) break; | |
4750 | ||
4751 | ReadDirAttr(RootNode,NULL, 0); | |
4752 | ||
4753 | UVFSFileNode D1_Node = NULL; | |
4754 | err = CreateNewFolder(RootNode,&D1_Node,"D1"); | |
4755 | printf("CreateNewFolder err [%d]\n",err); | |
4756 | if (err) break; | |
4757 | ||
4758 | bool bFound = false; | |
4759 | read_directory_and_search_for_name( RootNode, "D1", &bFound, NULL, 0); | |
4760 | if (!bFound) | |
4761 | { | |
4762 | printf("Dir read failed, D1 wasn't found in Root"); | |
4763 | break; | |
4764 | } | |
4765 | ||
4766 | HFS_fsOps.fsops_reclaim(D1_Node); | |
4767 | ||
4768 | // Remove D1 | |
4769 | err = RemoveFolder(RootNode,"D1"); | |
4770 | printf("Remove Folder D1 from Root err [%d]\n",err); | |
4771 | if (err) break; | |
4772 | ||
4773 | uCycleCounter++; | |
4774 | }while(uCycleCounter < TEST_CYCLE_COUNT); | |
4775 | ||
4776 | err = HFS_fsOps.fsops_unmount(RootNode, UVFSUnmountHintNone); | |
4777 | printf("UnMount err [%d]\n",err); | |
4778 | ||
4779 | return err; | |
4780 | } | |
4781 | ||
4782 |