diff options
author | unknown <cmiller@zippy.cornsilk.net> | 2007-02-13 16:35:29 -0500 |
---|---|---|
committer | unknown <cmiller@zippy.cornsilk.net> | 2007-02-13 16:35:29 -0500 |
commit | 035062b2a7506bfa159bfc67ed710a19beee2114 (patch) | |
tree | 5c1b3bbbf429e5745127941b3eacebf8a66d3fb8 /mysys/mf_iocache.c | |
parent | 6f628013e818b729407fa6952e553dccf59f14d0 (diff) | |
download | mariadb-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.c | 41 |
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)); |