several net bugfixes and improvements and fix some memory leaks
This commit is contained in:
parent
da1b289afc
commit
bd40efbf0b
8 changed files with 365 additions and 180 deletions
|
@ -35,6 +35,7 @@ struct grub_bufio
|
|||
grub_file_t file;
|
||||
grub_size_t block_size;
|
||||
grub_size_t buffer_len;
|
||||
grub_off_t buffer_at;
|
||||
char buffer[0];
|
||||
};
|
||||
typedef struct grub_bufio *grub_bufio_t;
|
||||
|
@ -70,6 +71,7 @@ grub_bufio_open (grub_file_t io, int size)
|
|||
bufio->file = io;
|
||||
bufio->block_size = size;
|
||||
bufio->buffer_len = 0;
|
||||
bufio->buffer_at = 0;
|
||||
|
||||
file->device = io->device;
|
||||
file->offset = 0;
|
||||
|
@ -104,83 +106,87 @@ grub_buffile_open (const char *name, int size)
|
|||
static grub_ssize_t
|
||||
grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_size_t res = len;
|
||||
grub_size_t res = 0;
|
||||
grub_bufio_t bufio = file->data;
|
||||
grub_uint64_t pos;
|
||||
|
||||
if ((file->offset >= bufio->file->offset) &&
|
||||
(file->offset < bufio->file->offset + bufio->buffer_len))
|
||||
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
file->size = bufio->file->size;
|
||||
|
||||
/* First part: use whatever we already have in the buffer. */
|
||||
if ((file->offset >= bufio->buffer_at) &&
|
||||
(file->offset < bufio->buffer_at + bufio->buffer_len))
|
||||
{
|
||||
grub_size_t n;
|
||||
grub_uint64_t pos;
|
||||
|
||||
pos = file->offset - bufio->file->offset;
|
||||
pos = file->offset - bufio->buffer_at;
|
||||
n = bufio->buffer_len - pos;
|
||||
if (n > len)
|
||||
n = len;
|
||||
|
||||
grub_memcpy (buf, &bufio->buffer[pos], n);
|
||||
len -= n;
|
||||
if (! len)
|
||||
return res;
|
||||
res += n;
|
||||
|
||||
buf += n;
|
||||
bufio->file->offset += bufio->buffer_len;
|
||||
pos = 0;
|
||||
}
|
||||
if (! len)
|
||||
return res;
|
||||
|
||||
/* Need to read some more. */
|
||||
bufio->buffer_at = grub_divmod64 (file->offset + res + len, bufio->block_size,
|
||||
0) * bufio->block_size;
|
||||
|
||||
/* Now read between file->offset + res and bufio->buffer_at. */
|
||||
if (file->offset + res < bufio->buffer_at)
|
||||
{
|
||||
grub_size_t read_now;
|
||||
grub_ssize_t really_read;
|
||||
read_now = bufio->buffer_at - (file->offset + res);
|
||||
grub_file_seek (bufio->file, file->offset + res);
|
||||
really_read = grub_file_read (bufio->file, buf, read_now);
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
file->size = bufio->file->size;
|
||||
len -= really_read;
|
||||
buf += really_read;
|
||||
res += really_read;
|
||||
|
||||
/* Partial read. File ended unexpectedly. Save the last chunk in buffer.
|
||||
*/
|
||||
if (really_read != (grub_ssize_t) read_now)
|
||||
{
|
||||
bufio->buffer_len = really_read;
|
||||
if (bufio->buffer_len > bufio->block_size)
|
||||
bufio->buffer_len = bufio->block_size;
|
||||
bufio->buffer_at = file->offset + res - bufio->buffer_len;
|
||||
grub_memcpy (&bufio->buffer[0], buf - bufio->buffer_len,
|
||||
bufio->buffer_len);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read into buffer. */
|
||||
grub_file_seek (bufio->file, bufio->buffer_at);
|
||||
bufio->buffer_len = grub_file_read (bufio->file, bufio->buffer,
|
||||
bufio->block_size);
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
file->size = bufio->file->size;
|
||||
|
||||
if (len < bufio->buffer_len)
|
||||
{
|
||||
grub_memcpy (buf, &bufio->buffer[0], len);
|
||||
res += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufio->file->offset = grub_divmod64 (file->offset, bufio->block_size,
|
||||
&pos);
|
||||
bufio->file->offset *= bufio->block_size;
|
||||
grub_memcpy (buf, &bufio->buffer[0], bufio->buffer_len);
|
||||
res += bufio->buffer_len;
|
||||
}
|
||||
|
||||
if (pos + len >= bufio->block_size)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
grub_size_t n;
|
||||
|
||||
bufio->file->fs->read (bufio->file, bufio->buffer,
|
||||
bufio->block_size);
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
|
||||
n = bufio->block_size - pos;
|
||||
grub_memcpy (buf, &bufio->buffer[pos], n);
|
||||
len -= n;
|
||||
buf += n;
|
||||
bufio->file->offset += bufio->block_size;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
while (len >= bufio->block_size)
|
||||
{
|
||||
bufio->file->fs->read (bufio->file, buf, bufio->block_size);
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
|
||||
len -= bufio->block_size;
|
||||
buf += bufio->block_size;
|
||||
bufio->file->offset += bufio->block_size;
|
||||
}
|
||||
|
||||
if (! len)
|
||||
{
|
||||
bufio->buffer_len = 0;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bufio->buffer_len = bufio->file->size - bufio->file->offset;
|
||||
if (bufio->buffer_len > bufio->block_size)
|
||||
bufio->buffer_len = bufio->block_size;
|
||||
|
||||
bufio->file->fs->read (bufio->file, bufio->buffer, bufio->buffer_len);
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
|
||||
grub_memcpy (buf, &bufio->buffer[pos], len);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue