1 /* bufio.c - buffered io access */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
23 #include <grub/misc.h>
25 #include <grub/bufio.h>
27 #define GRUB_BUFIO_DEF_SIZE 8192
28 #define GRUB_BUFIO_MAX_SIZE 1048576
33 grub_size_t block_size
;
34 grub_size_t buffer_len
;
37 typedef struct grub_bufio
*grub_bufio_t
;
39 static struct grub_fs grub_bufio_fs
;
42 grub_bufio_open (grub_file_t io
, int size
)
45 grub_bufio_t bufio
= 0;
47 file
= (grub_file_t
) grub_malloc (sizeof (*file
));
52 size
= GRUB_BUFIO_DEF_SIZE
;
53 else if (size
> GRUB_BUFIO_MAX_SIZE
)
54 size
= GRUB_BUFIO_MAX_SIZE
;
56 if ((size
< 0) || ((unsigned) size
> io
->size
))
57 size
= ((io
->size
> GRUB_BUFIO_MAX_SIZE
) ? GRUB_BUFIO_MAX_SIZE
:
60 bufio
= grub_malloc (sizeof (struct grub_bufio
) + size
);
68 bufio
->block_size
= size
;
69 bufio
->buffer_len
= 0;
71 file
->device
= io
->device
;
73 file
->size
= io
->size
;
76 file
->fs
= &grub_bufio_fs
;
82 grub_buffile_open (const char *name
, int size
)
86 io
= grub_file_open (name
);
90 file
= grub_bufio_open (io
, size
);
101 grub_bufio_read (grub_file_t file
, char *buf
, grub_size_t len
)
103 grub_size_t res
= len
;
104 grub_bufio_t bufio
= file
->data
;
107 if ((file
->offset
>= bufio
->file
->offset
) &&
108 (file
->offset
< bufio
->file
->offset
+ bufio
->buffer_len
))
112 pos
= file
->offset
- bufio
->file
->offset
;
113 n
= bufio
->buffer_len
- pos
;
117 grub_memcpy (buf
, &bufio
->buffer
[pos
], n
);
123 bufio
->file
->offset
+= bufio
->buffer_len
;
128 bufio
->file
->offset
= grub_divmod64 (file
->offset
, bufio
->block_size
,
130 bufio
->file
->offset
*= bufio
->block_size
;
133 if (pos
+ len
>= bufio
->block_size
)
139 bufio
->file
->fs
->read (bufio
->file
, bufio
->buffer
,
144 n
= bufio
->block_size
- pos
;
145 grub_memcpy (buf
, &bufio
->buffer
[pos
], n
);
148 bufio
->file
->offset
+= bufio
->block_size
;
152 while (len
>= bufio
->block_size
)
154 bufio
->file
->fs
->read (bufio
->file
, buf
, bufio
->block_size
);
158 len
-= bufio
->block_size
;
159 buf
+= bufio
->block_size
;
160 bufio
->file
->offset
+= bufio
->block_size
;
165 bufio
->buffer_len
= 0;
170 bufio
->buffer_len
= bufio
->file
->size
- bufio
->file
->offset
;
171 if (bufio
->buffer_len
> bufio
->block_size
)
172 bufio
->buffer_len
= bufio
->block_size
;
174 bufio
->file
->fs
->read (bufio
->file
, bufio
->buffer
, bufio
->buffer_len
);
178 grub_memcpy (buf
, &bufio
->buffer
[pos
], len
);
184 grub_bufio_close (grub_file_t file
)
186 grub_bufio_t bufio
= file
->data
;
188 grub_file_close (bufio
->file
);
196 static struct grub_fs grub_bufio_fs
=
201 .read
= grub_bufio_read
,
202 .close
= grub_bufio_close
,