Skip to content

Instantly share code, notes, and snippets.

@submachine
Last active August 29, 2015 13:57
Show Gist options
  • Save submachine/9624465 to your computer and use it in GitHub Desktop.
Save submachine/9624465 to your computer and use it in GitHub Desktop.
A sequence of calls to test ftell with fseek/rewind/fread/fwrite functions while in append mode.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
const char *data = "zzzzzzzzzz";
const char *more_data = "aaaaaaaaaa";
#define TEST_FILE_PATH "tst-rewind-ftell.out"
/* http://pubs.opengroup.org/onlinepubs/007908775/xsh/stdio.html
When opening with any 'a' mode, the position of the file position
indicator after fopen is implementation defined. For glibc, this it is at
the end of the file for 'a' and at the beginning of the file for 'a+'. */
int
main ()
{
FILE *stream;
long pos, writesize, filesize, nelem;
char buf[10];
#define WRITE(ptr) \
do \
{ \
writesize = strlen(ptr); \
fwrite (ptr, 1, writesize, stream); \
filesize += writesize; \
} while (0)
#define FILESIZE() filesize
/* New file => pos is 0. */
unlink (TEST_FILE_PATH);
filesize = 0; /* For book-keeping. */
stream = fopen (TEST_FILE_PATH, "a");
pos = ftell (stream);
assert (pos == 0);
/* pos moves with writes. */
WRITE (data);
pos = ftell (stream);
assert (pos == FILESIZE ());
/* rewind sets pos back to 0 again. */
rewind (stream);
pos = ftell (stream);
assert (pos == 0);
/* fopen (a) sets pos at end. */
fclose (stream);
stream = fopen (TEST_FILE_PATH, "a");
pos = ftell (stream);
assert (pos == FILESIZE ());
/* fseek(0) -> fwrite sets pos jumps back to end. */
fseek (stream, 0, SEEK_SET);
pos = ftell (stream);
assert (pos == 0);
WRITE (more_data);
pos = ftell (stream);
assert (pos == FILESIZE ());
/* fopen (a+) sets pos at beginning. */
fclose (stream);
stream = fopen (TEST_FILE_PATH, "a+");
pos = ftell (stream);
assert (pos == 0);
/* and now! write sets pos back at end. */
WRITE (more_data);
pos = ftell (stream);
assert (pos == FILESIZE ());
/* rewind sets pos back at 0 again. */
rewind (stream);
pos = ftell (stream);
assert (pos == 0);
/* Since we did rewind, it is safe to read now. */
/* read moves pos forward. */
nelem = fread (buf, sizeof (buf), 1, stream);
assert (nelem == 1);
assert (strncmp (buf, data, sizeof (buf)) == 0);
pos = ftell (stream);
assert (pos == sizeof (buf));
fseek (stream, 0, SEEK_CUR);
/* Since we did fseek, it is safe to write now. */
/* write sets pos back at end. */
WRITE (more_data);
pos = ftell (stream);
assert (pos == FILESIZE ());
/* This write is there only so that we do 'fflush'
after it so we become eligible to read again. */
WRITE (more_data);
fflush (stream);
/* Since we did fflush, it is safe to read now. */
/* nothing to read, we are at EOF. */
nelem = fread (buf, sizeof (buf), 1, stream);
assert (nelem == 0);
assert (feof (stream) && !ferror (stream));
pos = ftell (stream);
assert (pos == FILESIZE ());
/* read from mid-file works. */
fseek (stream, sizeof (buf), SEEK_SET);
nelem = fread (buf, sizeof (buf), 1, stream);
assert (nelem == 1);
assert (strncmp (buf, more_data, sizeof (buf)) == 0);
pos = ftell (stream);
assert (pos == 2 * sizeof (buf));
fclose (stream);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment