1# simple truncate
2[cases.test_truncate_simple]
3defines.MEDIUMSIZE = [31, 32, 33, 511, 512, 513, 2047, 2048, 2049]
4defines.LARGESIZE = [32, 33, 512, 513, 2048, 2049, 8192, 8193]
5if = 'MEDIUMSIZE < LARGESIZE'
6code = '''
7    lfs_t lfs;
8    lfs_format(&lfs, cfg) => 0;
9    lfs_mount(&lfs, cfg) => 0;
10    lfs_file_t file;
11    lfs_file_open(&lfs, &file, "baldynoop",
12            LFS_O_WRONLY | LFS_O_CREAT) => 0;
13
14    uint8_t buffer[1024];
15    strcpy((char*)buffer, "hair");
16    size_t size = strlen((char*)buffer);
17    for (lfs_off_t j = 0; j < LARGESIZE; j += size) {
18        lfs_file_write(&lfs, &file, buffer, lfs_min(size, LARGESIZE-j))
19                => lfs_min(size, LARGESIZE-j);
20    }
21    lfs_file_size(&lfs, &file) => LARGESIZE;
22
23    lfs_file_close(&lfs, &file) => 0;
24    lfs_unmount(&lfs) => 0;
25
26    lfs_mount(&lfs, cfg) => 0;
27    lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDWR) => 0;
28    lfs_file_size(&lfs, &file) => LARGESIZE;
29
30    lfs_file_truncate(&lfs, &file, MEDIUMSIZE) => 0;
31    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
32
33    lfs_file_close(&lfs, &file) => 0;
34    lfs_unmount(&lfs) => 0;
35
36    lfs_mount(&lfs, cfg) => 0;
37    lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDONLY) => 0;
38    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
39
40    size = strlen("hair");
41    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
42        lfs_file_read(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
43                => lfs_min(size, MEDIUMSIZE-j);
44        memcmp(buffer, "hair", lfs_min(size, MEDIUMSIZE-j)) => 0;
45    }
46    lfs_file_read(&lfs, &file, buffer, size) => 0;
47
48    lfs_file_close(&lfs, &file) => 0;
49    lfs_unmount(&lfs) => 0;
50'''
51
52# truncate and read
53[cases.test_truncate_read]
54defines.MEDIUMSIZE = [31, 32, 33, 511, 512, 513, 2047, 2048, 2049]
55defines.LARGESIZE = [32, 33, 512, 513, 2048, 2049, 8192, 8193]
56if = 'MEDIUMSIZE < LARGESIZE'
57code = '''
58    lfs_t lfs;
59    lfs_format(&lfs, cfg) => 0;
60    lfs_mount(&lfs, cfg) => 0;
61    lfs_file_t file;
62    lfs_file_open(&lfs, &file, "baldyread",
63            LFS_O_WRONLY | LFS_O_CREAT) => 0;
64
65    uint8_t buffer[1024];
66    strcpy((char*)buffer, "hair");
67    size_t size = strlen((char*)buffer);
68    for (lfs_off_t j = 0; j < LARGESIZE; j += size) {
69        lfs_file_write(&lfs, &file, buffer, lfs_min(size, LARGESIZE-j))
70                => lfs_min(size, LARGESIZE-j);
71    }
72    lfs_file_size(&lfs, &file) => LARGESIZE;
73
74    lfs_file_close(&lfs, &file) => 0;
75    lfs_unmount(&lfs) => 0;
76
77    lfs_mount(&lfs, cfg) => 0;
78    lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDWR) => 0;
79    lfs_file_size(&lfs, &file) => LARGESIZE;
80
81    lfs_file_truncate(&lfs, &file, MEDIUMSIZE) => 0;
82    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
83
84    size = strlen("hair");
85    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
86        lfs_file_read(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
87                => lfs_min(size, MEDIUMSIZE-j);
88        memcmp(buffer, "hair", lfs_min(size, MEDIUMSIZE-j)) => 0;
89    }
90    lfs_file_read(&lfs, &file, buffer, size) => 0;
91
92    lfs_file_close(&lfs, &file) => 0;
93    lfs_unmount(&lfs) => 0;
94
95    lfs_mount(&lfs, cfg) => 0;
96    lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDONLY) => 0;
97    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
98
99    size = strlen("hair");
100    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
101        lfs_file_read(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
102                => lfs_min(size, MEDIUMSIZE-j);
103        memcmp(buffer, "hair", lfs_min(size, MEDIUMSIZE-j)) => 0;
104    }
105    lfs_file_read(&lfs, &file, buffer, size) => 0;
106
107    lfs_file_close(&lfs, &file) => 0;
108    lfs_unmount(&lfs) => 0;
109'''
110
111# write, truncate, and read
112[cases.test_truncate_write_read]
113code = '''
114    lfs_t lfs;
115    lfs_format(&lfs, cfg) => 0;
116    lfs_mount(&lfs, cfg) => 0;
117    lfs_file_t file;
118    lfs_file_open(&lfs, &file, "sequence",
119            LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC) => 0;
120
121    uint8_t buffer[1024];
122    size_t size = lfs_min(lfs.cfg->cache_size, sizeof(buffer)/2);
123    lfs_size_t qsize = size / 4;
124    uint8_t *wb = buffer;
125    uint8_t *rb = buffer + size;
126    for (lfs_off_t j = 0; j < size; ++j) {
127        wb[j] = j;
128    }
129
130    /* Spread sequence over size */
131    lfs_file_write(&lfs, &file, wb, size) => size;
132    lfs_file_size(&lfs, &file) => size;
133    lfs_file_tell(&lfs, &file) => size;
134
135    lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
136    lfs_file_tell(&lfs, &file) => 0;
137
138    /* Chop off the last quarter */
139    lfs_size_t trunc = size - qsize;
140    lfs_file_truncate(&lfs, &file, trunc) => 0;
141    lfs_file_tell(&lfs, &file) => 0;
142    lfs_file_size(&lfs, &file) => trunc;
143
144    /* Read should produce first 3/4 */
145    lfs_file_read(&lfs, &file, rb, size) => trunc;
146    memcmp(rb, wb, trunc) => 0;
147
148    /* Move to 1/4 */
149    lfs_file_size(&lfs, &file) => trunc;
150    lfs_file_seek(&lfs, &file, qsize, LFS_SEEK_SET) => qsize;
151    lfs_file_tell(&lfs, &file) => qsize;
152
153    /* Chop to 1/2 */
154    trunc -= qsize;
155    lfs_file_truncate(&lfs, &file, trunc) => 0;
156    lfs_file_tell(&lfs, &file) => qsize;
157    lfs_file_size(&lfs, &file) => trunc;
158
159    /* Read should produce second quarter */
160    lfs_file_read(&lfs, &file, rb, size) => trunc - qsize;
161    memcmp(rb, wb + qsize, trunc - qsize) => 0;
162
163    lfs_file_close(&lfs, &file) => 0;
164    lfs_unmount(&lfs) => 0;
165'''
166
167# truncate and write
168[cases.test_truncate_write]
169defines.MEDIUMSIZE = [31, 32, 33, 511, 512, 513, 2047, 2048, 2049]
170defines.LARGESIZE = [32, 33, 512, 513, 2048, 2049, 8192, 8193]
171if = 'MEDIUMSIZE < LARGESIZE'
172code = '''
173    lfs_t lfs;
174    lfs_format(&lfs, cfg) => 0;
175    lfs_mount(&lfs, cfg) => 0;
176    lfs_file_t file;
177    lfs_file_open(&lfs, &file, "baldywrite",
178            LFS_O_WRONLY | LFS_O_CREAT) => 0;
179
180    uint8_t buffer[1024];
181    strcpy((char*)buffer, "hair");
182    size_t size = strlen((char*)buffer);
183    for (lfs_off_t j = 0; j < LARGESIZE; j += size) {
184        lfs_file_write(&lfs, &file, buffer, lfs_min(size, LARGESIZE-j))
185                => lfs_min(size, LARGESIZE-j);
186    }
187    lfs_file_size(&lfs, &file) => LARGESIZE;
188
189    lfs_file_close(&lfs, &file) => 0;
190    lfs_unmount(&lfs) => 0;
191
192    lfs_mount(&lfs, cfg) => 0;
193    lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDWR) => 0;
194    lfs_file_size(&lfs, &file) => LARGESIZE;
195
196    /* truncate */
197    lfs_file_truncate(&lfs, &file, MEDIUMSIZE) => 0;
198    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
199
200    /* and write */
201    strcpy((char*)buffer, "bald");
202    size = strlen((char*)buffer);
203    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
204        lfs_file_write(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
205                => lfs_min(size, MEDIUMSIZE-j);
206    }
207    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
208
209    lfs_file_close(&lfs, &file) => 0;
210    lfs_unmount(&lfs) => 0;
211
212    lfs_mount(&lfs, cfg) => 0;
213    lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDONLY) => 0;
214    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
215
216    size = strlen("bald");
217    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
218        lfs_file_read(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
219                => lfs_min(size, MEDIUMSIZE-j);
220        memcmp(buffer, "bald", lfs_min(size, MEDIUMSIZE-j)) => 0;
221    }
222    lfs_file_read(&lfs, &file, buffer, size) => 0;
223
224    lfs_file_close(&lfs, &file) => 0;
225    lfs_unmount(&lfs) => 0;
226'''
227
228# truncate write under powerloss
229[cases.test_truncate_reentrant_write]
230defines.SMALLSIZE = [4, 512]
231defines.MEDIUMSIZE = [0, 3, 4, 5, 31, 32, 33, 511, 512, 513, 1023, 1024, 1025]
232defines.LARGESIZE = 2048
233reentrant = true
234code = '''
235    lfs_t lfs;
236    int err = lfs_mount(&lfs, cfg);
237    if (err) {
238        lfs_format(&lfs, cfg) => 0;
239        lfs_mount(&lfs, cfg) => 0;
240    }
241    lfs_file_t file;
242    err = lfs_file_open(&lfs, &file, "baldy", LFS_O_RDONLY);
243    assert(!err || err == LFS_ERR_NOENT);
244    if (!err) {
245        size_t size = lfs_file_size(&lfs, &file);
246        assert(size == 0 ||
247                size == (size_t)LARGESIZE ||
248                size == (size_t)MEDIUMSIZE ||
249                size == (size_t)SMALLSIZE);
250        for (lfs_off_t j = 0; j < size; j += 4) {
251            uint8_t buffer[1024];
252            lfs_file_read(&lfs, &file, buffer, lfs_min(4, size-j))
253                    => lfs_min(4, size-j);
254            assert(memcmp(buffer, "hair", lfs_min(4, size-j)) == 0 ||
255                   memcmp(buffer, "bald", lfs_min(4, size-j)) == 0 ||
256                   memcmp(buffer, "comb", lfs_min(4, size-j)) == 0);
257        }
258        lfs_file_close(&lfs, &file) => 0;
259    }
260
261    lfs_file_open(&lfs, &file, "baldy",
262            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
263    lfs_file_size(&lfs, &file) => 0;
264    uint8_t buffer[1024];
265    strcpy((char*)buffer, "hair");
266    size_t size = strlen((char*)buffer);
267    for (lfs_off_t j = 0; j < LARGESIZE; j += size) {
268        lfs_file_write(&lfs, &file, buffer, lfs_min(size, LARGESIZE-j))
269                => lfs_min(size, LARGESIZE-j);
270    }
271    lfs_file_size(&lfs, &file) => LARGESIZE;
272    lfs_file_close(&lfs, &file) => 0;
273
274    lfs_file_open(&lfs, &file, "baldy", LFS_O_RDWR) => 0;
275    lfs_file_size(&lfs, &file) => LARGESIZE;
276    /* truncate */
277    lfs_file_truncate(&lfs, &file, MEDIUMSIZE) => 0;
278    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
279    /* and write */
280    strcpy((char*)buffer, "bald");
281    size = strlen((char*)buffer);
282    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
283        lfs_file_write(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
284                => lfs_min(size, MEDIUMSIZE-j);
285    }
286    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
287    lfs_file_close(&lfs, &file) => 0;
288
289    lfs_file_open(&lfs, &file, "baldy", LFS_O_RDWR) => 0;
290    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
291    lfs_file_truncate(&lfs, &file, SMALLSIZE) => 0;
292    lfs_file_size(&lfs, &file) => SMALLSIZE;
293    strcpy((char*)buffer, "comb");
294    size = strlen((char*)buffer);
295    for (lfs_off_t j = 0; j < SMALLSIZE; j += size) {
296        lfs_file_write(&lfs, &file, buffer, lfs_min(size, SMALLSIZE-j))
297                => lfs_min(size, SMALLSIZE-j);
298    }
299    lfs_file_size(&lfs, &file) => SMALLSIZE;
300    lfs_file_close(&lfs, &file) => 0;
301
302    lfs_unmount(&lfs) => 0;
303'''
304
305# more aggressive general truncation tests
306[cases.test_truncate_aggressive]
307defines.CONFIG = 'range(6)'
308defines.SMALLSIZE = 32
309defines.MEDIUMSIZE = 2048
310defines.LARGESIZE = 8192
311code = '''
312    lfs_t lfs;
313    #define COUNT 5
314    const struct {
315        lfs_off_t startsizes[COUNT];
316        lfs_off_t startseeks[COUNT];
317        lfs_off_t hotsizes[COUNT];
318        lfs_off_t coldsizes[COUNT];
319    } configs[] = {
320        // cold shrinking
321        {{2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
322         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
323         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
324         {          0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE, 2*LARGESIZE}},
325        // cold expanding
326        {{2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
327         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
328         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
329         {          0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE, 2*LARGESIZE}},
330        // warm shrinking truncate
331        {{2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
332         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
333         {          0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE, 2*LARGESIZE},
334         {          0,           0,           0,           0,           0}},
335        // warm expanding truncate
336        {{          0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE, 2*LARGESIZE},
337         {          0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE, 2*LARGESIZE},
338         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
339         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE}},
340        // mid-file shrinking truncate
341        {{2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
342         {  LARGESIZE,   LARGESIZE,   LARGESIZE,   LARGESIZE,   LARGESIZE},
343         {          0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE, 2*LARGESIZE},
344         {          0,           0,           0,           0,           0}},
345        // mid-file expanding truncate
346        {{          0,   SMALLSIZE,   MEDIUMSIZE,  LARGESIZE, 2*LARGESIZE},
347         {          0,           0,   SMALLSIZE,  MEDIUMSIZE,   LARGESIZE},
348         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE},
349         {2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE, 2*LARGESIZE}},
350    };
351
352    const lfs_off_t *startsizes = configs[CONFIG].startsizes;
353    const lfs_off_t *startseeks = configs[CONFIG].startseeks;
354    const lfs_off_t *hotsizes   = configs[CONFIG].hotsizes;
355    const lfs_off_t *coldsizes  = configs[CONFIG].coldsizes;
356
357    lfs_format(&lfs, cfg) => 0;
358    lfs_mount(&lfs, cfg) => 0;
359
360    for (unsigned i = 0; i < COUNT; i++) {
361        char path[1024];
362        sprintf(path, "hairyhead%d", i);
363        lfs_file_t file;
364        lfs_file_open(&lfs, &file, path,
365                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
366
367        uint8_t buffer[1024];
368        strcpy((char*)buffer, "hair");
369        size_t size = strlen((char*)buffer);
370        for (lfs_off_t j = 0; j < startsizes[i]; j += size) {
371            lfs_file_write(&lfs, &file, buffer, size) => size;
372        }
373        lfs_file_size(&lfs, &file) => startsizes[i];
374
375        if (startseeks[i] != startsizes[i]) {
376            lfs_file_seek(&lfs, &file,
377                    startseeks[i], LFS_SEEK_SET) => startseeks[i];
378        }
379
380        lfs_file_truncate(&lfs, &file, hotsizes[i]) => 0;
381        lfs_file_size(&lfs, &file) => hotsizes[i];
382
383        lfs_file_close(&lfs, &file) => 0;
384    }
385
386    lfs_unmount(&lfs) => 0;
387
388    lfs_mount(&lfs, cfg) => 0;
389
390    for (unsigned i = 0; i < COUNT; i++) {
391        char path[1024];
392        sprintf(path, "hairyhead%d", i);
393        lfs_file_t file;
394        lfs_file_open(&lfs, &file, path, LFS_O_RDWR) => 0;
395        lfs_file_size(&lfs, &file) => hotsizes[i];
396
397        size_t size = strlen("hair");
398        lfs_off_t j = 0;
399        for (; j < startsizes[i] && j < hotsizes[i]; j += size) {
400            uint8_t buffer[1024];
401            lfs_file_read(&lfs, &file, buffer, size) => size;
402            memcmp(buffer, "hair", size) => 0;
403        }
404
405        for (; j < hotsizes[i]; j += size) {
406            uint8_t buffer[1024];
407            lfs_file_read(&lfs, &file, buffer, size) => size;
408            memcmp(buffer, "\0\0\0\0", size) => 0;
409        }
410
411        lfs_file_truncate(&lfs, &file, coldsizes[i]) => 0;
412        lfs_file_size(&lfs, &file) => coldsizes[i];
413
414        lfs_file_close(&lfs, &file) => 0;
415    }
416
417    lfs_unmount(&lfs) => 0;
418
419    lfs_mount(&lfs, cfg) => 0;
420
421    for (unsigned i = 0; i < COUNT; i++) {
422        char path[1024];
423        sprintf(path, "hairyhead%d", i);
424        lfs_file_t file;
425        lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0;
426        lfs_file_size(&lfs, &file) => coldsizes[i];
427
428        size_t size = strlen("hair");
429        lfs_off_t j = 0;
430        for (; j < startsizes[i] && j < hotsizes[i] && j < coldsizes[i];
431                j += size) {
432            uint8_t buffer[1024];
433            lfs_file_read(&lfs, &file, buffer, size) => size;
434            memcmp(buffer, "hair", size) => 0;
435        }
436
437        for (; j < coldsizes[i]; j += size) {
438            uint8_t buffer[1024];
439            lfs_file_read(&lfs, &file, buffer, size) => size;
440            memcmp(buffer, "\0\0\0\0", size) => 0;
441        }
442
443        lfs_file_close(&lfs, &file) => 0;
444    }
445
446    lfs_unmount(&lfs) => 0;
447'''
448
449# noop truncate
450[cases.test_truncate_nop]
451defines.MEDIUMSIZE = [32, 33, 512, 513, 2048, 2049, 8192, 8193]
452code = '''
453    lfs_t lfs;
454    lfs_format(&lfs, cfg) => 0;
455    lfs_mount(&lfs, cfg) => 0;
456    lfs_file_t file;
457    lfs_file_open(&lfs, &file, "baldynoop",
458            LFS_O_RDWR | LFS_O_CREAT) => 0;
459
460    uint8_t buffer[1024];
461    strcpy((char*)buffer, "hair");
462    size_t size = strlen((char*)buffer);
463    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
464        lfs_file_write(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
465                => lfs_min(size, MEDIUMSIZE-j);
466
467        // this truncate should do nothing
468        lfs_file_truncate(&lfs, &file, j+lfs_min(size, MEDIUMSIZE-j)) => 0;
469    }
470    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
471
472    lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
473    // should do nothing again
474    lfs_file_truncate(&lfs, &file, MEDIUMSIZE) => 0;
475    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
476
477    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
478        lfs_file_read(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
479                => lfs_min(size, MEDIUMSIZE-j);
480        memcmp(buffer, "hair", lfs_min(size, MEDIUMSIZE-j)) => 0;
481    }
482    lfs_file_read(&lfs, &file, buffer, size) => 0;
483
484    lfs_file_close(&lfs, &file) => 0;
485    lfs_unmount(&lfs) => 0;
486
487    // still there after reboot?
488    lfs_mount(&lfs, cfg) => 0;
489    lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDWR) => 0;
490    lfs_file_size(&lfs, &file) => MEDIUMSIZE;
491    for (lfs_off_t j = 0; j < MEDIUMSIZE; j += size) {
492        lfs_file_read(&lfs, &file, buffer, lfs_min(size, MEDIUMSIZE-j))
493                => lfs_min(size, MEDIUMSIZE-j);
494        memcmp(buffer, "hair", lfs_min(size, MEDIUMSIZE-j)) => 0;
495    }
496    lfs_file_read(&lfs, &file, buffer, size) => 0;
497    lfs_file_close(&lfs, &file) => 0;
498    lfs_unmount(&lfs) => 0;
499'''
500