2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2013 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/file.h>
22 GRUB_MOD_LICENSE ("GPLv3+");
24 struct grub_offset_file
31 grub_offset_read (grub_file_t file
, char *buf
, grub_size_t len
)
33 struct grub_offset_file
*data
= file
->data
;
34 if (grub_file_seek (data
->parent
, data
->off
+ file
->offset
) == (grub_off_t
) -1)
36 return grub_file_read (data
->parent
, buf
, len
);
40 grub_offset_close (grub_file_t file
)
42 struct grub_offset_file
*data
= file
->data
;
45 grub_file_close (data
->parent
);
47 /* No need to close the same device twice. */
53 static struct grub_fs grub_offset_fs
= {
57 .read
= grub_offset_read
,
58 .close
= grub_offset_close
,
64 grub_file_offset_close (grub_file_t file
)
66 struct grub_offset_file
*off_data
= file
->data
;
67 off_data
->parent
= NULL
;
68 grub_file_close (file
);
72 grub_file_offset_open (grub_file_t parent
, grub_off_t start
, grub_off_t size
)
74 struct grub_offset_file
*off_data
;
75 grub_file_t off_file
, last_off_file
;
76 grub_file_filter_id_t filter
;
78 off_file
= grub_zalloc (sizeof (*off_file
));
79 off_data
= grub_zalloc (sizeof (*off_data
));
80 if (!off_file
|| !off_data
)
87 off_data
->off
= start
;
88 off_data
->parent
= parent
;
90 off_file
->device
= parent
->device
;
91 off_file
->data
= off_data
;
92 off_file
->fs
= &grub_offset_fs
;
93 off_file
->size
= size
;
96 for (filter
= GRUB_FILE_FILTER_COMPRESSION_FIRST
;
97 off_file
&& filter
<= GRUB_FILE_FILTER_COMPRESSION_LAST
; filter
++)
98 if (grub_file_filters_enabled
[filter
])
100 last_off_file
= off_file
;
101 off_file
= grub_file_filters_enabled
[filter
] (off_file
, parent
->name
);
106 off_data
->parent
= NULL
;
107 grub_file_close (last_off_file
);