2014-03-17 Siddhesh Poyarekar <siddhesh@redhat.com>
+ * libio/iofdopen.c (_IO_new_fdopen): Seek to end only if
+ setting O_APPEND.
+ * libio/tst-ftell-active-handler.c (do_append_test): Add a
+ test case.
+
[BZ #16680]
* libio/fileops.c (_IO_file_open): Seek to end of file but
don't cache the offset.
int i;
int use_mmap = 0;
+ /* Decide whether we modify the offset of the file we attach to and seek to
+ the end of file. We only do this if the mode is 'a' and if the file
+ descriptor did not have O_APPEND in its flags already. */
+ bool do_seek = false;
+
switch (*mode)
{
case 'r':
*/
if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND))
{
+ do_seek = true;
#ifdef F_SETFL
if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1)
#endif
_IO_mask_flags (&new_f->fp.file, read_write,
_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
- /* For append mode, set the file offset to the end of the file. Don't
- update the offset cache though, since the file handle is not active. */
- if ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
- == (_IO_IS_APPENDING | _IO_NO_READS))
+ /* For append mode, set the file offset to the end of the file if we added
+ O_APPEND to the file descriptor flags. Don't update the offset cache
+ though, since the file handle is not active. */
+ if (do_seek && ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
+ == (_IO_IS_APPENDING | _IO_NO_READS)))
{
_IO_off64_t new_pos = _IO_SYSSEEK (&new_f->fp.file, 0, _IO_seek_end);
if (new_pos == _IO_pos_BAD && errno != ESPIPE)
}
}
+ /* For fdopen in 'a' mode, the file descriptor should not change if the file
+ is already open with the O_APPEND flag set. */
+ fd = open (filename, O_WRONLY | O_APPEND, 0);
+ if (fd == -1)
+ {
+ printf ("open(O_APPEND) failed: %m\n");
+ return 1;
+ }
+
+ off_t seek_ret = lseek (fd, file_len - 1, SEEK_SET);
+ if (seek_ret == -1)
+ {
+ printf ("lseek[O_APPEND][0] failed: %m\n");
+ ret |= 1;
+ }
+
+ fp = fdopen (fd, "a");
+ if (fp == NULL)
+ {
+ printf ("fdopen(O_APPEND) failed: %m\n");
+ close (fd);
+ return 1;
+ }
+
+ off_t new_seek_ret = lseek (fd, 0, SEEK_CUR);
+ if (seek_ret == -1)
+ {
+ printf ("lseek[O_APPEND][1] failed: %m\n");
+ ret |= 1;
+ }
+
+ printf ("\tappend: fdopen (file, \"a\"): O_APPEND: ");
+
+ if (seek_ret != new_seek_ret)
+ {
+ printf ("incorrectly modified file offset to %ld, should be %ld",
+ new_seek_ret, seek_ret);
+ ret |= 1;
+ }
+ else
+ printf ("retained current file offset %ld", seek_ret);
+
+ new_seek_ret = ftello (fp);
+
+ if (seek_ret != new_seek_ret)
+ {
+ printf (", ftello reported incorrect offset %ld, should be %ld\n",
+ new_seek_ret, seek_ret);
+ ret |= 1;
+ }
+ else
+ printf (", ftello reported correct offset %ld\n", seek_ret);
+
+ fclose (fp);
+
return ret;
}