The behavior of ff_ftell()
surprises me. The FreeRTOS+FAT Standard API Reference claims that it “Returns the current read/write position of an open file in the embedded FAT file system. The position is returned as the number of bytes from the start of the file.” But I don’t think that’s true, unless I’m misunderstanding something.
Here is a little test. I start by simply opening (with truncation) a file, writing 8 bytes, and closing:
19 // FF_FILE *ff_fopen( const char *pcFile, const char *pcMode );
20 /* “w” Open a file for reading and writing.
21 If the file already exists it will be truncated to zero length.
22 If the file does not already exist it will be created.*/
23 FF_FILE *file = ff_fopen( pcFileName, "w" );
24 configASSERT(file);
25 char buf[8];
26 memset(buf, '1', sizeof(buf) - 1);
27 buf[sizeof(buf) - 1] = 0;
28 // size_t ff_fwrite( const void *pvBuffer, size_t xSize, size_t xItems, FF_FILE * pxStream );
29 size_t ni = ff_fwrite(buf, sizeof buf, 1, file);
30 configASSERT(1 == ni);
31 // long ff_ftell( FF_FILE *pxStream );
32 /* Returns the current read/write position of an open file in the embedded FAT file system.
33 The position is returned as the number of bytes from the start of the file.*/
34 printf("%d: ff_ftell(): %ld\n", __LINE__, ff_ftell(file));
35 // int ff_feof( FF_FILE *pxStream );
36 /*Queries an open file in the embedded FAT file system to see if the file’s read/write pointer is at the end of the file.*/
37 printf("%d: ff_feof(): %d\n", __LINE__, ff_feof(file));
38 // void ff_rewind( FF_FILE *pxStream );
39 ff_rewind(file);
40 printf("%d: ff_ftell(): %ld\n", __LINE__, ff_ftell(file));
41 printf("%d: ff_feof(): %d\n", __LINE__, ff_feof(file));
42 // int ff_fclose( FF_FILE *pxStream );;
43 int ec = ff_fclose(file);
44 configASSERT(!ec);
which produces this output:
34: ff_ftell(): 8
37: ff_feof(): 1
40: ff_ftell(): 0
41: ff_feof(): 0
So far, so good.
Now, I open the same file for reading and writing with append, and it gets surprising (to me):
46 /* “a+” Open a file for reading and writing.
47 If the file already exists then new data will be appended to the end of the file.
48 If the file does not already exist it will be created. */
49 file = ff_fopen( pcFileName, "a+" );
50 configASSERT(file);
51 // int ff_feof( FF_FILE *pxStream );
52 /*Queries an open file in the embedded FAT file system to see if the file’s read/write pointer is at the end of the file.*/
53 printf("%d: ff_feof(): %d\n", __LINE__, ff_feof(file));
54 printf("%d: ff_ftell(): %ld\n", __LINE__, ff_ftell(file));
55
56 memset(buf, '2', sizeof(buf));
57 ni = ff_fwrite(buf, sizeof buf, 1, file);
58 configASSERT(1 == ni);
59 printf("%d: ff_feof(): %d\n", __LINE__, ff_feof(file));
60 printf("%d: ff_ftell(): %ld\n", __LINE__, ff_ftell(file));
61 ec = ff_fseek( file, 0, FF_SEEK_END );
62 configASSERT(!ec);
63 printf("%d: ff_feof(): %d\n", __LINE__, ff_feof(file));
64 printf("%d: ff_ftell(): %ld\n", __LINE__, ff_ftell(file));
65 ff_rewind(file);
66 printf("%d: ff_feof(): %d\n", __LINE__, ff_feof(file));
67 printf("%d: ff_ftell(): %ld\n", __LINE__, ff_ftell(file));
68 while (!ff_feof(file)) {
69 ni = ff_fread(buf, sizeof buf, 1 , file);
70 if (1 == ni) {
71 printf("%.*s", sizeof(buf), buf);
72 } else {
73 int error = stdioGET_ERRNO();
74 printf("%d: read: %s (%d)\n", __LINE__, strerror(error), error);
75 }
76 };
77 putchar('\n');
78 ec = ff_fclose(file);
79 configASSERT(!ec);
which produces:
53: ff_feof(): 0
54: ff_ftell(): 0
Hmm, “If the file already exists then new data will be appended to the end of the file.”, but apparently the “current read/write position of an open file” is 0 in this case.
59: ff_feof(): 1
60: ff_ftell(): 16
So, now I’ve written 8 bytes (from a read/write position 0) and now I’m at 16? I mean, I should be, if the file is really opened for append, but how was the position 0 when I started?
63: ff_feof(): 1
64: ff_ftell(): 16
FF_SEEK_END made no difference, as expected.
66: ff_feof(): 0
67: ff_ftell(): 0
111111122222222
If I ff_rewind()
, I’m back to a new position 0, apparently, and I can read all 16 bytes.
This caused a bug for me when I relied on ff_ftell()
to determine whether a file opened in mode “a+”
was already existing (and new data will be appended to the end of the file) or it was newly created and empty. (ff_feof()
is no more helpful in this case).
I’ve gotten in the habit of putting an ff_fseek( file, 0, FF_SEEK_END )
before every ff_ftell()
.