summaryrefslogtreecommitdiff
path: root/mysys/mf_iocache.c
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2007-02-13 16:35:29 -0500
committerunknown <cmiller@zippy.cornsilk.net>2007-02-13 16:35:29 -0500
commit035062b2a7506bfa159bfc67ed710a19beee2114 (patch)
tree5c1b3bbbf429e5745127941b3eacebf8a66d3fb8 /mysys/mf_iocache.c
parent6f628013e818b729407fa6952e553dccf59f14d0 (diff)
downloadmariadb-git-035062b2a7506bfa159bfc67ed710a19beee2114.tar.gz
Bug#25807: LOAD DATA INFILE does not work with Pipes
Showstopper and regression against 5.0.24. Previously, we ignored seek() errors (see Bug#22828) and let seek()s against pipes fail. Now, since we check that a seek didn't fail, and return without reading, this bug popped up. This restores the behavior for file-ish objects that could never be seek()ed. mysys/mf_iocache.c: If we detect early that the file is not tell()able, then we should assume that it's also not seek()able and therefore we should never set the (poorly named) "seek_not_done" flag so that we don't immedi- ately try to seek() when reading later. The problem was that tell() was returning -1, so when we read later, we needlessly tried to seek to position (unsigned long) -1 . Also, if we think we're supposed to seek to a position in a file and the file is un-tell()able, then abort.
Diffstat (limited to 'mysys/mf_iocache.c')
-rw-r--r--mysys/mf_iocache.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index fc81f0bad03..e40490776f8 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -157,6 +157,7 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
pbool use_async_io, myf cache_myflags)
{
uint min_cache;
+ my_off_t pos;
my_off_t end_of_file= ~(my_off_t) 0;
DBUG_ENTER("init_io_cache");
DBUG_PRINT("enter",("cache: 0x%lx type: %d pos: %ld",
@@ -169,7 +170,25 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
info->arg = 0;
info->alloced_buffer = 0;
info->buffer=0;
- info->seek_not_done= test(file >= 0 && seek_offset != my_tell(file, MYF(0)));
+
+ pos= my_tell(file, MYF(0));
+ if ((pos == (my_off_t) -1) && (my_errno == ESPIPE))
+ {
+ /*
+ This kind of object doesn't support seek() or tell(). Don't set a flag
+ that will make us again try to seek() later and fail.
+ */
+ info->seek_not_done= 0;
+ /*
+ Additionally, if we're supposed to start somewhere other than the
+ the beginning of whatever this file is, then somebody made a bad
+ assumption.
+ */
+ DBUG_ASSERT(seek_offset == 0);
+ }
+ else
+ info->seek_not_done= test(file >= 0 && seek_offset != pos);
+
info->disk_writes= 0;
#ifdef THREAD
info->share=0;
@@ -454,13 +473,23 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
*/
if (info->seek_not_done)
{
- if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
- == MY_FILEPOS_ERROR)
+ if ((my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
+ != MY_FILEPOS_ERROR))
{
- info->error= -1;
- DBUG_RETURN(1);
+ /* No error, reset seek_not_done flag. */
+ info->seek_not_done= 0;
+ }
+ else
+ {
+ /*
+ If the seek failed and the error number is ESPIPE, it is because
+ info->file is a pipe or socket or FIFO. We never should have tried
+ to seek on that. See Bugs#25807 and #22828 for more info.
+ */
+ DBUG_ASSERT(my_errno != ESPIPE);
+ info->error= -1;
+ DBUG_RETURN(1);
}
- info->seek_not_done=0;
}
diff_length=(uint) (pos_in_file & (IO_SIZE-1));