1 /* fs.c - filesystem manager */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2005,2007 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/>.
20 #include <grub/disk.h>
23 #include <grub/file.h>
25 #include <grub/misc.h>
26 #include <grub/types.h>
28 #include <grub/term.h>
29 #include <grub/i18n.h>
32 grub_fs_t grub_fs_list
= 0;
34 grub_fs_autoload_hook_t grub_fs_autoload_hook
= 0;
36 /* Helper for grub_fs_probe. */
38 probe_dummy_iter (const char *filename
__attribute__ ((unused
)),
39 const struct grub_dirhook_info
*info
__attribute__ ((unused
)),
40 void *data
__attribute__ ((unused
)))
46 grub_fs_probe (grub_device_t device
)
49 const char *first_probe
;
54 /* Make it sure not to have an infinite recursive calls. */
57 first_probe
= grub_env_get("ventoy_fs_probe");
60 first_probe
= "iso9660";
62 len
= grub_strlen(first_probe
);
64 /* use iso9660 first */
65 for (p
= grub_fs_list
; p
; p
= p
->next
)
67 if (grub_strncmp(p
->name
, first_probe
, len
) == 0)
75 grub_dprintf ("fs", "Detecting %s...\n", p
->name
);
77 /* This is evil: newly-created just mounted BtrFS after copying all
78 GRUB files has a very peculiar unrecoverable corruption which
79 will be fixed at sync but we'd rather not do a global sync and
80 syncing just files doesn't seem to help. Relax the check for
83 if (grub_strcmp (p
->name
, "btrfs") == 0)
86 p
->fs_uuid (device
, &label
);
92 (p
->fs_dir
) (device
, "/", probe_dummy_iter
, NULL
);
93 if (grub_errno
== GRUB_ERR_NONE
)
97 grub_dprintf ("fs", "%s detection failed.\n", p
->name
);
100 if (grub_errno
!= GRUB_ERR_BAD_FS
101 && grub_errno
!= GRUB_ERR_OUT_OF_RANGE
)
104 grub_errno
= GRUB_ERR_NONE
;
107 for (p
= grub_fs_list
; p
; p
= p
->next
)
109 grub_dprintf ("fs", "Detecting %s...\n", p
->name
);
111 /* This is evil: newly-created just mounted BtrFS after copying all
112 GRUB files has a very peculiar unrecoverable corruption which
113 will be fixed at sync but we'd rather not do a global sync and
114 syncing just files doesn't seem to help. Relax the check for
117 if (grub_strcmp (p
->name
, "btrfs") == 0)
120 p
->fs_uuid (device
, &label
);
126 (p
->fs_dir
) (device
, "/", probe_dummy_iter
, NULL
);
127 if (grub_errno
== GRUB_ERR_NONE
)
131 grub_dprintf ("fs", "%s detection failed.\n", p
->name
);
134 if (grub_errno
!= GRUB_ERR_BAD_FS
135 && grub_errno
!= GRUB_ERR_OUT_OF_RANGE
)
138 grub_errno
= GRUB_ERR_NONE
;
141 /* Let's load modules automatically. */
142 if (grub_fs_autoload_hook
&& count
== 0)
146 while (grub_fs_autoload_hook ())
150 (p
->fs_dir
) (device
, "/", probe_dummy_iter
, NULL
);
151 if (grub_errno
== GRUB_ERR_NONE
)
157 if (grub_errno
!= GRUB_ERR_BAD_FS
158 && grub_errno
!= GRUB_ERR_OUT_OF_RANGE
)
164 grub_errno
= GRUB_ERR_NONE
;
170 else if (device
->net
&& device
->net
->fs
)
171 return device
->net
->fs
;
173 grub_error (GRUB_ERR_UNKNOWN_FS
, N_("unknown filesystem"));
179 /* Block list support routines. */
183 grub_disk_addr_t offset
;
184 unsigned long length
;
188 grub_fs_blocklist_open (grub_file_t file
, const char *name
)
190 char *p
= (char *) name
;
193 grub_disk_t disk
= file
->device
->disk
;
194 struct grub_fs_block
*blocks
;
196 /* First, count the number of blocks. */
200 p
= grub_strchr (p
, ',');
206 /* Allocate a block list. */
207 blocks
= grub_zalloc (sizeof (struct grub_fs_block
) * (num
+ 1));
213 for (i
= 0; i
< num
; i
++)
217 blocks
[i
].offset
= grub_strtoull (p
, &p
, 0);
218 if (grub_errno
!= GRUB_ERR_NONE
|| *p
!= '+')
220 grub_error (GRUB_ERR_BAD_FILENAME
,
221 N_("invalid file name `%s'"), name
);
227 blocks
[i
].length
= grub_strtoul (p
, &p
, 0);
228 if (grub_errno
!= GRUB_ERR_NONE
229 || blocks
[i
].length
== 0
230 || (*p
&& *p
!= ',' && ! grub_isspace (*p
)))
232 grub_error (GRUB_ERR_BAD_FILENAME
,
233 N_("invalid file name `%s'"), name
);
237 if (disk
->total_sectors
< blocks
[i
].offset
+ blocks
[i
].length
)
239 grub_error (GRUB_ERR_BAD_FILENAME
, "beyond the total sectors");
243 file
->size
+= (blocks
[i
].length
<< GRUB_DISK_SECTOR_BITS
);
249 return GRUB_ERR_NONE
;
257 grub_fs_blocklist_read (grub_file_t file
, char *buf
, grub_size_t len
)
259 struct grub_fs_block
*p
;
260 grub_disk_addr_t sector
;
262 grub_ssize_t ret
= 0;
264 if (len
> file
->size
- file
->offset
)
265 len
= file
->size
- file
->offset
;
267 sector
= (file
->offset
>> GRUB_DISK_SECTOR_BITS
);
268 offset
= (file
->offset
& (GRUB_DISK_SECTOR_SIZE
- 1));
269 for (p
= file
->data
; p
->length
&& len
> 0; p
++)
271 if (sector
< p
->length
)
276 if (((size
+ offset
+ GRUB_DISK_SECTOR_SIZE
- 1)
277 >> GRUB_DISK_SECTOR_BITS
) > p
->length
- sector
)
278 size
= ((p
->length
- sector
) << GRUB_DISK_SECTOR_BITS
) - offset
;
280 if (grub_disk_read (file
->device
->disk
, p
->offset
+ sector
, offset
,
281 size
, buf
) != GRUB_ERR_NONE
)
286 sector
-= ((size
+ offset
) >> GRUB_DISK_SECTOR_BITS
);
287 offset
= ((size
+ offset
) & (GRUB_DISK_SECTOR_SIZE
- 1));
296 struct grub_fs grub_fs_blocklist
=
300 .fs_open
= grub_fs_blocklist_open
,
301 .fs_read
= grub_fs_blocklist_read
,