* grub-core/io/bufio.c (grub_bufio_read): Fix handling of corner cases.

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-12-25 15:43:15 +01:00
parent bbc47747ad
commit cc4fddf5f5
2 changed files with 22 additions and 22 deletions

View file

@ -1,3 +1,7 @@
2011-12-25 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/io/bufio.c (grub_bufio_read): Fix handling of corner cases.
2011-12-25 Vladimir Serbinenko <phcoder@gmail.com> 2011-12-25 Vladimir Serbinenko <phcoder@gmail.com>
* docs/grub.texi (Filesystems): Mention AFS. * docs/grub.texi (Filesystems): Mention AFS.

View file

@ -107,7 +107,9 @@ static grub_ssize_t
grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
{ {
grub_size_t res = 0; grub_size_t res = 0;
grub_off_t next_buf;
grub_bufio_t bufio = file->data; grub_bufio_t bufio = file->data;
grub_ssize_t really_read;
if (file->size == GRUB_FILE_SIZE_UNKNOWN) if (file->size == GRUB_FILE_SIZE_UNKNOWN)
file->size = bufio->file->size; file->size = bufio->file->size;
@ -130,22 +132,19 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
buf += n; buf += n;
} }
if (! len) if (len == 0)
return res; return res;
/* Need to read some more. */ /* Need to read some more. */
bufio->buffer_at = grub_divmod64 (file->offset + res + len, bufio->block_size, next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1);
0) * bufio->block_size;
/* Now read between file->offset + res and bufio->buffer_at. */ /* Now read between file->offset + res and bufio->buffer_at. */
if (file->offset + res < bufio->buffer_at) if (file->offset + res < next_buf)
{ {
grub_size_t read_now; grub_size_t read_now;
grub_ssize_t really_read; read_now = next_buf - (file->offset + res);
read_now = bufio->buffer_at - (file->offset + res);
grub_file_seek (bufio->file, file->offset + res); grub_file_seek (bufio->file, file->offset + res);
really_read = grub_file_read (bufio->file, buf, read_now); really_read = grub_file_read (bufio->file, buf, read_now);
if (grub_errno) if (really_read < 0)
return -1; return -1;
if (file->size == GRUB_FILE_SIZE_UNKNOWN) if (file->size == GRUB_FILE_SIZE_UNKNOWN)
file->size = bufio->file->size; file->size = bufio->file->size;
@ -168,24 +167,21 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
} }
/* Read into buffer. */ /* Read into buffer. */
grub_file_seek (bufio->file, bufio->buffer_at); grub_file_seek (bufio->file, next_buf);
bufio->buffer_len = grub_file_read (bufio->file, bufio->buffer, really_read = grub_file_read (bufio->file, bufio->buffer,
bufio->block_size); bufio->block_size);
if (grub_errno) if (really_read < 0)
return -1; return -1;
bufio->buffer_at = next_buf;
bufio->buffer_len = really_read;
if (file->size == GRUB_FILE_SIZE_UNKNOWN) if (file->size == GRUB_FILE_SIZE_UNKNOWN)
file->size = bufio->file->size; file->size = bufio->file->size;
if (len < bufio->buffer_len) if (len > bufio->buffer_len)
{ len = bufio->buffer_len;
grub_memcpy (buf, &bufio->buffer[0], len); grub_memcpy (buf, &bufio->buffer[file->offset + res - next_buf], len);
res += len; res += len;
}
else
{
grub_memcpy (buf, &bufio->buffer[0], bufio->buffer_len);
res += bufio->buffer_len;
}
return res; return res;
} }