]> git.saurik.com Git - apple/hfs.git/blame - livefiles_hfs_plugin/livefiles_hfs_tester.c
hfs-522.100.5.tar.gz
[apple/hfs.git] / livefiles_hfs_plugin / livefiles_hfs_tester.c
CommitLineData
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
33uint32_t guSyncerPeriod = DEFAULT_SYNCER_PERIOD;
34
35typedef 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
42typedef 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
62typedef 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
73typedef 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
83char *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};
93uint32_t guCrashAbortCnt = 0;
94CrashReport_S gsCrashReport;
95#endif
96
97int 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
116typedef 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
127static int SetAttrChangeSize(UVFSFileNode FileNode,uint64_t uNewSize);
128static int SetAttrChangeMode(UVFSFileNode FileNode,uint32_t uNewMode);
129static int SetAttrChangeUidGid(UVFSFileNode FileNode, uint32_t uNewUid, uint32_t uNewGid);
130static int SetAttrChangeAtimeMtime(UVFSFileNode FileNode);
131static int GetAttrAndCompare(UVFSFileNode FileNode,UVFSFileAttributes* sInAttrs);
132static int HFSTest_RunTest(TestData_S *psTestData);
133static void *ReadWriteThread(void *pvArgs);
134
135
136struct unistr255 {
137 uint16_t length;
138 uint16_t chars[255];
139};
140
141u_char
142l2u[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 */
180static const uint16_t
181mac2sfm[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
200static void
201unistr255ToLowerCase( 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
212void 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(&timestamp_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
243CONV_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
407static bool
408HFSTest_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/* --------------------------------------------------------------------------------------------- */
455static void SetExpectedAttr(char* pcName, uint32_t uType, UVFSDirEntryAttr* psAttr);
456static int ReadDirAttr(UVFSFileNode psNode, UVFSDirEntryAttr* psReadDirTestsData, uint32_t uDirEntries);
457static int RemoveFolder(UVFSFileNode ParentNode,char* DirNameToRemove);
458static int CreateNewFolder(UVFSFileNode ParentNode,UVFSFileNode* NewDirNode,char* NewDirName);
459static int CreateHardLink(UVFSFileNode FromNode, UVFSFileNode ToDirNode, char* NewHardLinkName);
460static int RemoveFile(UVFSFileNode ParentNode,char* FileNameToRemove);
461static int CreateNewFile(UVFSFileNode ParentNode,UVFSFileNode* NewFileNode,char* NewFileName,uint64_t size);
462static int read_directory_and_search_for_name( UVFSFileNode psNode, char* pcSearchName, bool* pbFound, UVFSDirEntryAttr* psReadDirTestsData, uint32_t uDirEntries );
463static int RenameFile(UVFSFileNode FromParentNode,UVFSFileNode FromNode,char* FromName, UVFSFileNode ToParentNode,UVFSFileNode ToNode,char* ToName);
464/* --------------------------------------------------------------------------------------------- */
465
466static 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
475static 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
484static 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
493static 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
508static 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
522static 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
536static 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
648static int
649ReadDirAttr( 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
727static int
728GetAttrAndCompare(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
768fail:
769 error = 1;
770out:
771 if (error) printf("Failed in compare attr\n");
772 return error;
773}
774
775static int
776SetAttrChangeSize(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
792static int
793SetAttrChangeMode(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
807static int
808SetAttrChangeUidGid(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
824static int
825SetAttrChangeAtimeMtime(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
889typedef int (*test_hander_t)( UVFSFileNode RootNode );
890
891char pcLastDevPathName[50] = {0};
892char pcDevPath[50] = {0};
893char pcDevNum[50] = {0};
894char gpcResultsFolder[256] = {0};
895
896static int
897HFSTest_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
1095static void
1096HFSTest_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
1126void HFSTest_ClearCrashAbortFunctionArray(void) {
1127 for(unsigned u=0; u<CRASH_ABORT_LAST; u++)
1128 gpsCrashAbortFunctionArray[u] = NULL;
1129}
1130
1131typedef struct {
1132 char pcMountedDev[512];
1133 char pcMountedVol[512];
1134} MountedDrive_S;
1135
1136int 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
1184int 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
1205int 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
1228int 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
1241int 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
1265int 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
1277int 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
1293static 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
1313static 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
1329int 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
1401exit:
1402 return(iErr);
1403}
1404
1405int 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 }
1433exit:
1434 return(iErr);
1435}
1436
1437int 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
1478exit:
1479 return(iErr);
1480}
1481
1482int 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
1524exit:
1525 printf("HFSTest_CrashAbortOnMkDir returns %d\n", iErr);
1526 return(iErr);
1527}
1528
1529int 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
1563exit:
1564 return(iErr);
1565}
1566#endif
1567
1568static int
1569HFSTest_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
1760exit:
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
1790static int
1791HFSTest_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
1857exit:
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
1866static 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
1914exit:
1915 return iErr;
1916}
1917
1918
1919static 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 }
2055exit:
2056 psThrdData->iRetVal = iErr;
2057 return psThrdData;
2058}
2059
2060#if HFS_CRASH_TEST
2061static 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
2112exit:
2113 return iErr;
2114
2115}
2116#endif
2117
2118static 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
2155exit:
2156 return iErr;
2157}
2158
2159static int
2160HFSTest_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
2192exit:
2193 return iErr;
2194}
2195
2196static int
2197HFSTest_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
2276exit:
2277 HFS_fsOps.fsops_reclaim(TestFolder);
2278 HFS_fsOps.fsops_reclaim(TestFile1);
2279 HFS_fsOps.fsops_reclaim(TestFile2);
2280 return iErr;
2281}
2282
2283static 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
2331static 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
2343exit:
2344 return iErr;
2345}
2346
2347static 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;
2412exit:
2413 return iErr;
2414}
2415
2416static 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
2585static 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
2605exit:
2606 return(iErr);
2607}
2608
2609static 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
2647exit:
2648 return iErr;
2649}
2650
2651static 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
2720exit:
2721 return iErr;
2722}
2723
2724static 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
2762static int
2763HFSTest_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
2807HFSTest_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
2844static int
2845HFSTest_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
2913static int
2914HFSTest_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
2980static int
2981HFSTest_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
3025static 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
3032static int
3033HFSTest_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
3079static int __used
3080HFSTest_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
3135static int
3136HFSTest_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
3168exit:
3169 if (pvBuf)
3170 free(pvBuf);
3171
3172 return iErr;
3173}
3174
3175static int
3176HFSTest_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
3256exit:
3257 if (pvBuf)
3258 free(pvBuf);
3259
3260 return iErr;
3261}
3262
3263static 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
3349static int
3350HFSTest_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
3449static 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
3472static int
3473HFSTest_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
3520exit:
3521 free(psAttrVal);
3522 return (iErr);
3523}
3524
3525static int
3526HFSTest_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
3589exit:
3590 return iErr;
3591}
3592
3593static int
3594HFSTest_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
3656static int
3657HFSTest_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
3795static int
3796HFSTest_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
3841exit:
3842 return iErr;
3843}
3844
3845static int
3846HFSTest_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
3869static int
3870HFSTest_JustMount( __unused UVFSFileNode RootNode )
3871{
3872 return 0;
3873}
3874
3875static int HFSTest_OpenJournal( __unused UVFSFileNode RootNode ) {
3876
3877 printf("HFSTest_OpenJournal:\n");
3878
3879 return 0;
3880}
3881
3882static 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
3952exit:
3953 HFS_fsOps.fsops_reclaim(TestFolder);
3954 HFS_fsOps.fsops_reclaim(TestFile1);
3955 HFS_fsOps.fsops_reclaim(TestFile2);
3956 return iErr;
3957}
3958
3959static int __used
3960HFSTest_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
4093out_mem:
4094 free(pBuffer);
4095 free(pBufferRet);
4096
4097out:
4098 // Reclaim test file
4099 HFS_fsOps.fsops_reclaim(TestFile);
4100
4101 return iErr;
4102}
4103
4104
4105static int __used
4106HFSTest_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
4190mem_err:
4191 free(pcBuffer);
4192
4193out:
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
4220TestData_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
4330void *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
4358static 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
4375exit:
4376 return(iErr);
4377}
4378
4379static 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
4405exit:
4406 if (psReturnStatus) {
4407 free(psReturnStatus);
4408 }
4409
4410 return(iErr);
4411}
4412
4413static 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
4534int 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
4557int 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
4616int 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/*******************************************/
4672int 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