Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / fs / cpio_common.c
blob50fea47d1819bbb1070499baa04f9679ac774f0c
1 /* cpio.c - cpio and tar filesystem. */
2 /*
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>
21 #include <grub/mm.h>
22 #include <grub/misc.h>
23 #include <grub/disk.h>
24 #include <grub/dl.h>
25 #include <grub/i18n.h>
26 #include <grub/archelp.h>
28 GRUB_MOD_LICENSE ("GPLv3+");
30 struct grub_archelp_data
32 grub_disk_t disk;
33 grub_off_t hofs;
34 grub_off_t next_hofs;
35 grub_off_t dofs;
36 grub_off_t size;
39 static grub_err_t
40 grub_cpio_find_file (struct grub_archelp_data *data, char **name,
41 grub_int32_t *mtime, grub_uint32_t *mode)
43 struct head hd;
44 grub_size_t namesize;
45 grub_uint32_t modeval;
47 data->hofs = data->next_hofs;
49 if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
50 return grub_errno;
52 if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0
53 #ifdef MAGIC2
54 && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0
55 #endif
57 return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
58 data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
59 if (mtime)
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;
69 return GRUB_ERR_NONE;
72 *mode = modeval;
74 *name = grub_malloc (namesize + 1);
75 if (*name == NULL)
76 return grub_errno;
78 if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
79 namesize, *name))
81 grub_free (*name);
82 return grub_errno;
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;
90 grub_free (*name);
91 return GRUB_ERR_NONE;
94 data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize);
95 data->next_hofs = data->dofs + ALIGN_CPIO (data->size);
96 return GRUB_ERR_NONE;
99 static char *
100 grub_cpio_get_link_target (struct grub_archelp_data *data)
102 char *ret;
103 grub_err_t err;
105 if (data->size == 0)
106 return grub_strdup ("");
107 ret = grub_malloc (data->size + 1);
108 if (!ret)
109 return NULL;
111 err = grub_disk_read (data->disk, 0, data->dofs, data->size,
112 ret);
113 if (err)
115 grub_free (ret);
116 return NULL;
118 ret[data->size] = '\0';
119 return ret;
122 static void
123 grub_cpio_rewind (struct grub_archelp_data *data)
125 data->next_hofs = 0;
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)
138 struct head hd;
139 struct grub_archelp_data *data;
141 if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd))
142 goto fail;
144 if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)
145 #ifdef MAGIC2
146 && grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1)
147 #endif
149 goto fail;
151 data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data));
152 if (!data)
153 goto fail;
155 data->disk = disk;
157 return data;
159 fail:
160 grub_error (GRUB_ERR_BAD_FS, "not a " FSNAME " filesystem");
161 return 0;
164 static grub_err_t
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;
169 grub_err_t err;
171 data = grub_cpio_mount (device->disk);
172 if (!data)
173 return grub_errno;
175 err = grub_archelp_dir (data, &arcops,
176 path_in, hook, hook_data);
178 grub_free (data);
180 return err;
183 static grub_err_t
184 grub_cpio_open (grub_file_t file, const char *name_in)
186 struct grub_archelp_data *data;
187 grub_err_t err;
189 data = grub_cpio_mount (file->device->disk);
190 if (!data)
191 return grub_errno;
193 err = grub_archelp_open (data, &arcops, name_in);
194 if (err)
196 grub_free (data);
198 else
200 file->data = data;
201 file->size = data->size;
203 return err;
206 static grub_ssize_t
207 grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
209 struct grub_archelp_data *data;
210 grub_ssize_t ret;
212 data = file->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;
220 return ret;
223 static grub_err_t
224 grub_cpio_close (grub_file_t file)
226 struct grub_archelp_data *data;
228 data = file->data;
229 grub_free (data);
231 return grub_errno;
234 static struct grub_fs grub_cpio_fs = {
235 .name = FSNAME,
236 .dir = grub_cpio_dir,
237 .open = grub_cpio_open,
238 .read = grub_cpio_read,
239 .close = grub_cpio_close,
240 #ifdef GRUB_UTIL
241 .reserved_first_sector = 0,
242 .blocklist_install = 0,
243 #endif