~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to fs/cpio.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* cpio.c - cpio and tar filesystem.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
5
 
 *
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.
10
 
 *
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.
15
 
 *
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/>.
18
 
 */
19
 
 
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
 
 
26
 
#ifndef MODE_USTAR
27
 
/* cpio support */
28
 
#define MAGIC_BCPIO     070707
29
 
struct head
30
 
{
31
 
  grub_uint16_t magic;
32
 
  grub_uint16_t dev;
33
 
  grub_uint16_t ino;
34
 
  grub_uint16_t mode;
35
 
  grub_uint16_t uid;
36
 
  grub_uint16_t gid;
37
 
  grub_uint16_t nlink;
38
 
  grub_uint16_t rdev;
39
 
  grub_uint16_t mtime_1;
40
 
  grub_uint16_t mtime_2;
41
 
  grub_uint16_t namesize;
42
 
  grub_uint16_t filesize_1;
43
 
  grub_uint16_t filesize_2;
44
 
} __attribute__ ((packed));
45
 
#else
46
 
/* tar support */
47
 
#define MAGIC_USTAR     "ustar"
48
 
struct head
49
 
{
50
 
  char name[100];
51
 
  char mode[8];
52
 
  char uid[8];
53
 
  char gid[8];
54
 
  char size[12];
55
 
  char mtime[12];
56
 
  char chksum[8];
57
 
  char typeflag;
58
 
  char linkname[100];
59
 
  char magic[6];
60
 
  char version[2];
61
 
  char uname[32];
62
 
  char gname[32];
63
 
  char devmajor[8];
64
 
  char devminor[8];
65
 
  char prefix[155];
66
 
} __attribute__ ((packed));
67
 
#endif
68
 
 
69
 
struct grub_cpio_data
70
 
{
71
 
  grub_disk_t disk;
72
 
  grub_uint32_t hofs;
73
 
  grub_uint32_t dofs;
74
 
  grub_uint32_t size;
75
 
};
76
 
 
77
 
static grub_dl_t my_mod;
78
 
 
79
 
static grub_err_t
80
 
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
81
 
                     grub_uint32_t * ofs)
82
 
{
83
 
#ifndef MODE_USTAR
84
 
      struct head hd;
85
 
 
86
 
      if (grub_disk_read
87
 
          (data->disk, 0, data->hofs, sizeof (hd), &hd))
88
 
        return grub_errno;
89
 
 
90
 
      if (hd.magic != MAGIC_BCPIO)
91
 
        return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
92
 
 
93
 
      data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
94
 
 
95
 
      if (hd.namesize & 1)
96
 
        hd.namesize++;
97
 
 
98
 
      if ((*name = grub_malloc (hd.namesize)) == NULL)
99
 
        return grub_errno;
100
 
 
101
 
      if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
102
 
                          hd.namesize, *name))
103
 
        {
104
 
          grub_free (*name);
105
 
          return grub_errno;
106
 
        }
107
 
 
108
 
      if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1
109
 
          && ! grub_memcmp(*name, "TRAILER!!!", 11))
110
 
        {
111
 
          *ofs = 0;
112
 
          return GRUB_ERR_NONE;
113
 
        }
114
 
 
115
 
      data->dofs = data->hofs + sizeof (hd) + hd.namesize;
116
 
      *ofs = data->dofs + data->size;
117
 
      if (data->size & 1)
118
 
        (*ofs)++;
119
 
#else
120
 
      struct head hd;
121
 
 
122
 
      if (grub_disk_read
123
 
          (data->disk, 0, data->hofs, sizeof (hd), &hd))
124
 
        return grub_errno;
125
 
 
126
 
      if (!hd.name[0])
127
 
        {
128
 
          *ofs = 0;
129
 
          return GRUB_ERR_NONE;
130
 
        }
131
 
 
132
 
      if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1))
133
 
        return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
134
 
 
135
 
      if ((*name = grub_strdup (hd.name)) == NULL)
136
 
        return grub_errno;
137
 
 
138
 
      data->size = grub_strtoul (hd.size, NULL, 8);
139
 
      data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
140
 
      *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
141
 
                           ~(GRUB_DISK_SECTOR_SIZE - 1));
142
 
#endif
143
 
  return GRUB_ERR_NONE;
144
 
}
145
 
 
146
 
static struct grub_cpio_data *
147
 
grub_cpio_mount (grub_disk_t disk)
148
 
{
149
 
  struct head hd;
150
 
  struct grub_cpio_data *data;
151
 
 
152
 
  if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd))
153
 
    goto fail;
154
 
 
155
 
#ifndef MODE_USTAR
156
 
  if (hd.magic != MAGIC_BCPIO)
157
 
#else
158
 
  if (grub_memcmp (hd.magic, MAGIC_USTAR,
159
 
                   sizeof (MAGIC_USTAR) - 1))
160
 
#endif
161
 
    goto fail;
162
 
 
163
 
  data = (struct grub_cpio_data *) grub_malloc (sizeof (*data));
164
 
  if (!data)
165
 
    goto fail;
166
 
 
167
 
  data->disk = disk;
168
 
 
169
 
  return data;
170
 
 
171
 
fail:
172
 
  grub_error (GRUB_ERR_BAD_FS, "not a "
173
 
#ifdef MODE_USTAR
174
 
              "tar"
175
 
#else
176
 
              "cpio"
177
 
#endif
178
 
              " filesystem");
179
 
  return 0;
180
 
}
181
 
 
182
 
static grub_err_t
183
 
grub_cpio_dir (grub_device_t device, const char *path,
184
 
               int (*hook) (const char *filename,
185
 
                            const struct grub_dirhook_info *info))
186
 
{
187
 
  struct grub_cpio_data *data;
188
 
  grub_uint32_t ofs;
189
 
  char *prev, *name;
190
 
  const char *np;
191
 
  int len;
192
 
 
193
 
  grub_dl_ref (my_mod);
194
 
 
195
 
  prev = 0;
196
 
 
197
 
  data = grub_cpio_mount (device->disk);
198
 
  if (!data)
199
 
    goto fail;
200
 
 
201
 
  np = path + 1;
202
 
  len = grub_strlen (path) - 1;
203
 
 
204
 
  data->hofs = 0;
205
 
  while (1)
206
 
    {
207
 
      if (grub_cpio_find_file (data, &name, &ofs))
208
 
        goto fail;
209
 
 
210
 
      if (!ofs)
211
 
        break;
212
 
 
213
 
      if (grub_memcmp (np, name, len) == 0)
214
 
        {
215
 
          char *p, *n;
216
 
 
217
 
          n = name + len;
218
 
          if (*n == '/')
219
 
            n++;
220
 
 
221
 
          p = grub_strchr (name + len, '/');
222
 
          if (p)
223
 
            *p = 0;
224
 
 
225
 
          if ((!prev) || (grub_strcmp (prev, name) != 0))
226
 
            {
227
 
              struct grub_dirhook_info info;
228
 
              grub_memset (&info, 0, sizeof (info));
229
 
              info.dir = (p != NULL);
230
 
 
231
 
              hook (name + len, &info);
232
 
              if (prev)
233
 
                grub_free (prev);
234
 
              prev = name;
235
 
            }
236
 
          else
237
 
            grub_free (name);
238
 
        }
239
 
      data->hofs = ofs;
240
 
    }
241
 
 
242
 
fail:
243
 
 
244
 
  if (prev)
245
 
    grub_free (prev);
246
 
 
247
 
  if (data)
248
 
    grub_free (data);
249
 
 
250
 
  grub_dl_unref (my_mod);
251
 
 
252
 
  return grub_errno;
253
 
}
254
 
 
255
 
static grub_err_t
256
 
grub_cpio_open (grub_file_t file, const char *name)
257
 
{
258
 
  struct grub_cpio_data *data;
259
 
  grub_uint32_t ofs;
260
 
  char *fn;
261
 
  int i, j;
262
 
 
263
 
  grub_dl_ref (my_mod);
264
 
 
265
 
  data = grub_cpio_mount (file->device->disk);
266
 
  if (!data)
267
 
    goto fail;
268
 
 
269
 
  data->hofs = 0;
270
 
  while (1)
271
 
    {
272
 
      if (grub_cpio_find_file (data, &fn, &ofs))
273
 
        goto fail;
274
 
 
275
 
      if (!ofs)
276
 
        {
277
 
          grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
278
 
          break;
279
 
        }
280
 
 
281
 
      /* Compare NAME and FN by hand in order to cope with duplicate
282
 
         slashes.  */
283
 
      i = 0;
284
 
      j = 0;
285
 
      while (name[i] == '/')
286
 
        i++;
287
 
      while (1)
288
 
        {
289
 
          if (name[i] != fn[j])
290
 
            goto no_match;
291
 
 
292
 
          if (name[i] == '\0')
293
 
            break;
294
 
 
295
 
          while (name[i] == '/' && name[i+1] == '/')
296
 
            i++;
297
 
 
298
 
          i++;
299
 
          j++;
300
 
        }
301
 
 
302
 
      if (name[i] != fn[j])
303
 
        goto no_match;
304
 
 
305
 
      file->data = data;
306
 
      file->size = data->size;
307
 
      grub_free (fn);
308
 
 
309
 
      return GRUB_ERR_NONE;
310
 
 
311
 
    no_match:
312
 
 
313
 
      grub_free (fn);
314
 
      data->hofs = ofs;
315
 
    }
316
 
 
317
 
fail:
318
 
 
319
 
  if (data)
320
 
    grub_free (data);
321
 
 
322
 
  grub_dl_unref (my_mod);
323
 
 
324
 
  return grub_errno;
325
 
}
326
 
 
327
 
static grub_ssize_t
328
 
grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
329
 
{
330
 
  struct grub_cpio_data *data;
331
 
 
332
 
  data = file->data;
333
 
  return (grub_disk_read (data->disk, 0, data->dofs + file->offset,
334
 
                          len, buf)) ? -1 : (grub_ssize_t) len;
335
 
}
336
 
 
337
 
static grub_err_t
338
 
grub_cpio_close (grub_file_t file)
339
 
{
340
 
  grub_free (file->data);
341
 
 
342
 
  grub_dl_unref (my_mod);
343
 
 
344
 
  return grub_errno;
345
 
}
346
 
 
347
 
static struct grub_fs grub_cpio_fs = {
348
 
#ifdef MODE_USTAR
349
 
  .name = "tarfs",
350
 
#else
351
 
  .name = "cpiofs",
352
 
#endif
353
 
  .dir = grub_cpio_dir,
354
 
  .open = grub_cpio_open,
355
 
  .read = grub_cpio_read,
356
 
  .close = grub_cpio_close,
357
 
};
358
 
 
359
 
#ifdef MODE_USTAR
360
 
GRUB_MOD_INIT (tar)
361
 
#else
362
 
GRUB_MOD_INIT (cpio)
363
 
#endif
364
 
{
365
 
  grub_fs_register (&grub_cpio_fs);
366
 
  my_mod = mod;
367
 
}
368
 
 
369
 
#ifdef MODE_USTAR
370
 
GRUB_MOD_FINI (tar)
371
 
#else
372
 
GRUB_MOD_FINI (cpio)
373
 
#endif
374
 
{
375
 
  grub_fs_unregister (&grub_cpio_fs);
376
 
}