1 /* cpio.c - cpio and tar filesystem. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc.
6 * This program 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 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/file.h>
22 #include <grub/misc.h>
23 #include <grub/disk.h>
25 #include <grub/i18n.h>
26 #include <grub/archelp.h>
28 GRUB_MOD_LICENSE ("GPLv3+");
30 struct grub_archelp_data
40 grub_cpio_find_file (struct grub_archelp_data
*data
, char **name
,
41 grub_int32_t
*mtime
, grub_uint32_t
*mode
)
45 grub_uint32_t modeval
;
47 data
->hofs
= data
->next_hofs
;
49 if (grub_disk_read (data
->disk
, 0, data
->hofs
, sizeof (hd
), &hd
))
52 if (grub_memcmp (hd
.magic
, MAGIC
, sizeof (hd
.magic
)) != 0
54 && grub_memcmp (hd
.magic
, MAGIC2
, sizeof (hd
.magic
)) != 0
57 return grub_error (GRUB_ERR_BAD_FS
, "invalid cpio archive");
58 data
->size
= read_number (hd
.filesize
, ARRAY_SIZE (hd
.filesize
));
60 *mtime
= read_number (hd
.mtime
, ARRAY_SIZE (hd
.mtime
));
61 modeval
= read_number (hd
.mode
, ARRAY_SIZE (hd
.mode
));
62 namesize
= read_number (hd
.namesize
, ARRAY_SIZE (hd
.namesize
));
64 /* Don't allow negative numbers. */
65 if (namesize
>= 0x80000000)
67 /* Probably a corruption, don't attempt to recover. */
68 *mode
= GRUB_ARCHELP_ATTR_END
;
74 *name
= grub_malloc (namesize
+ 1);
78 if (grub_disk_read (data
->disk
, 0, data
->hofs
+ sizeof (hd
),
84 (*name
)[namesize
] = 0;
86 if (data
->size
== 0 && modeval
== 0 && namesize
== 11
87 && grub_memcmp(*name
, "TRAILER!!!", 11) == 0)
89 *mode
= GRUB_ARCHELP_ATTR_END
;
94 data
->dofs
= data
->hofs
+ ALIGN_CPIO (sizeof (hd
) + namesize
);
95 data
->next_hofs
= data
->dofs
+ ALIGN_CPIO (data
->size
);
100 grub_cpio_get_link_target (struct grub_archelp_data
*data
)
106 return grub_strdup ("");
107 ret
= grub_malloc (data
->size
+ 1);
111 err
= grub_disk_read (data
->disk
, 0, data
->dofs
, data
->size
,
118 ret
[data
->size
] = '\0';
123 grub_cpio_rewind (struct grub_archelp_data
*data
)
128 static struct grub_archelp_ops arcops
=
130 .find_file
= grub_cpio_find_file
,
131 .get_link_target
= grub_cpio_get_link_target
,
132 .rewind
= grub_cpio_rewind
135 static struct grub_archelp_data
*
136 grub_cpio_mount (grub_disk_t disk
)
139 struct grub_archelp_data
*data
;
141 if (grub_disk_read (disk
, 0, 0, sizeof (hd
), &hd
))
144 if (grub_memcmp (hd
.magic
, MAGIC
, sizeof (MAGIC
) - 1)
146 && grub_memcmp (hd
.magic
, MAGIC2
, sizeof (MAGIC2
) - 1)
151 data
= (struct grub_archelp_data
*) grub_zalloc (sizeof (*data
));
160 grub_error (GRUB_ERR_BAD_FS
, "not a " FSNAME
" filesystem");
165 grub_cpio_dir (grub_device_t device
, const char *path_in
,
166 grub_fs_dir_hook_t hook
, void *hook_data
)
168 struct grub_archelp_data
*data
;
171 data
= grub_cpio_mount (device
->disk
);
175 err
= grub_archelp_dir (data
, &arcops
,
176 path_in
, hook
, hook_data
);
184 grub_cpio_open (grub_file_t file
, const char *name_in
)
186 struct grub_archelp_data
*data
;
189 data
= grub_cpio_mount (file
->device
->disk
);
193 err
= grub_archelp_open (data
, &arcops
, name_in
);
201 file
->size
= data
->size
;
207 grub_cpio_read (grub_file_t file
, char *buf
, grub_size_t len
)
209 struct grub_archelp_data
*data
;
213 data
->disk
->read_hook
= file
->read_hook
;
214 data
->disk
->read_hook_data
= file
->read_hook_data
;
216 ret
= (grub_disk_read (data
->disk
, 0, data
->dofs
+ file
->offset
,
217 len
, buf
)) ? -1 : (grub_ssize_t
) len
;
218 data
->disk
->read_hook
= 0;
224 grub_cpio_close (grub_file_t file
)
226 struct grub_archelp_data
*data
;
234 static struct grub_fs grub_cpio_fs
= {
236 .dir
= grub_cpio_dir
,
237 .open
= grub_cpio_open
,
238 .read
= grub_cpio_read
,
239 .close
= grub_cpio_close
,
241 .reserved_first_sector
= 0,
242 .blocklist_install
= 0,