mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-28 00:21:52 +03:00
Change offset in fdopen only if setting O_APPEND
fdopen should only be allowed to change the offset in the file it attaches to if it is setting O_APPEND. If O_APPEND is already set, it should not change the state of the handle.
This commit is contained in:
@ -1,5 +1,10 @@
|
|||||||
2014-03-17 Siddhesh Poyarekar <siddhesh@redhat.com>
|
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]
|
[BZ #16680]
|
||||||
* libio/fileops.c (_IO_file_open): Seek to end of file but
|
* libio/fileops.c (_IO_file_open): Seek to end of file but
|
||||||
don't cache the offset.
|
don't cache the offset.
|
||||||
|
@ -59,6 +59,11 @@ _IO_new_fdopen (fd, mode)
|
|||||||
int i;
|
int i;
|
||||||
int use_mmap = 0;
|
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)
|
switch (*mode)
|
||||||
{
|
{
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -128,6 +133,7 @@ _IO_new_fdopen (fd, mode)
|
|||||||
*/
|
*/
|
||||||
if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND))
|
if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND))
|
||||||
{
|
{
|
||||||
|
do_seek = true;
|
||||||
#ifdef F_SETFL
|
#ifdef F_SETFL
|
||||||
if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1)
|
if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1)
|
||||||
#endif
|
#endif
|
||||||
@ -167,10 +173,11 @@ _IO_new_fdopen (fd, mode)
|
|||||||
_IO_mask_flags (&new_f->fp.file, read_write,
|
_IO_mask_flags (&new_f->fp.file, read_write,
|
||||||
_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
|
_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
|
||||||
|
|
||||||
/* For append mode, set the file offset to the end of the file. Don't
|
/* For append mode, set the file offset to the end of the file if we added
|
||||||
update the offset cache though, since the file handle is not active. */
|
O_APPEND to the file descriptor flags. Don't update the offset cache
|
||||||
if ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
|
though, since the file handle is not active. */
|
||||||
== (_IO_IS_APPENDING | _IO_NO_READS))
|
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);
|
_IO_off64_t new_pos = _IO_SYSSEEK (&new_f->fp.file, 0, _IO_seek_end);
|
||||||
if (new_pos == _IO_pos_BAD && errno != ESPIPE)
|
if (new_pos == _IO_pos_BAD && errno != ESPIPE)
|
||||||
|
@ -414,6 +414,61 @@ do_append_test (const char *filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user