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

« back to all changes in this revision

Viewing changes to commands/test.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
 
/* test.c -- The test command..  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
5
 
 *
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.
10
 
 *
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.
15
 
 *
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/>.
18
 
 */
19
 
 
20
 
#include <grub/dl.h>
21
 
#include <grub/misc.h>
22
 
#include <grub/mm.h>
23
 
#include <grub/env.h>
24
 
#include <grub/fs.h>
25
 
#include <grub/device.h>
26
 
#include <grub/file.h>
27
 
#include <grub/command.h>
28
 
#include <grub/i18n.h>
29
 
 
30
 
/* A simple implementation for signed numbers. */
31
 
static int
32
 
grub_strtosl (char *arg, char **end, int base)
33
 
{
34
 
  if (arg[0] == '-')
35
 
    return -grub_strtoul (arg + 1, end, base);
36
 
  return grub_strtoul (arg, end, base);
37
 
}
38
 
 
39
 
/* Parse a test expression starting from *argn. */
40
 
static int
41
 
test_parse (char **args, int *argn, int argc)
42
 
{
43
 
  int ret = 0, discard = 0, invert = 0;
44
 
  int file_exists;
45
 
  struct grub_dirhook_info file_info;
46
 
 
47
 
  auto void update_val (int val);
48
 
  auto void get_fileinfo (char *pathname);
49
 
 
50
 
  /* Take care of discarding and inverting. */
51
 
  void update_val (int val)
52
 
  {
53
 
    if (! discard)
54
 
      ret = invert ? ! val : val;
55
 
    invert = discard = 0;
56
 
  }
57
 
 
58
 
  /* Check if file exists and fetch its information. */
59
 
  void get_fileinfo (char *path)
60
 
  {
61
 
    char *filename, *pathname;
62
 
    char *device_name;
63
 
    grub_fs_t fs;
64
 
    grub_device_t dev;
65
 
 
66
 
    /* A hook for iterating directories. */
67
 
    auto int find_file (const char *cur_filename,
68
 
                        const struct grub_dirhook_info *info);
69
 
    int find_file (const char *cur_filename,
70
 
                   const struct grub_dirhook_info *info)
71
 
    {
72
 
      if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename)
73
 
           : grub_strcmp (cur_filename, filename)) == 0)
74
 
        {
75
 
          file_info = *info;
76
 
          file_exists = 1;
77
 
          return 1;
78
 
        }
79
 
      return 0;
80
 
    }
81
 
 
82
 
    file_exists = 0;
83
 
    device_name = grub_file_get_device_name (path);
84
 
    dev = grub_device_open (device_name);
85
 
    if (! dev)
86
 
      {
87
 
        grub_free (device_name);
88
 
        return;
89
 
      }
90
 
 
91
 
    fs = grub_fs_probe (dev);
92
 
    if (! fs)
93
 
      {
94
 
        grub_free (device_name);
95
 
        grub_device_close (dev);
96
 
        return;
97
 
      }
98
 
 
99
 
    pathname = grub_strchr (path, ')');
100
 
    if (! pathname)
101
 
      pathname = path;
102
 
    else
103
 
      pathname++;
104
 
 
105
 
    /* Remove trailing '/'. */
106
 
    while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
107
 
      pathname[grub_strlen (pathname) - 1] = 0;
108
 
 
109
 
    /* Split into path and filename. */
110
 
    filename = grub_strrchr (pathname, '/');
111
 
    if (! filename)
112
 
      {
113
 
        path = grub_strdup ("/");
114
 
        filename = pathname;
115
 
      }
116
 
    else
117
 
      {
118
 
        filename++;
119
 
        path = grub_strdup (pathname);
120
 
        path[filename - pathname] = 0;
121
 
      }
122
 
 
123
 
    /* It's the whole device. */
124
 
    if (! *pathname)
125
 
      {
126
 
        file_exists = 1;
127
 
        grub_memset (&file_info, 0, sizeof (file_info));
128
 
        /* Root is always a directory. */
129
 
        file_info.dir = 1;
130
 
 
131
 
        /* Fetch writing time. */
132
 
        file_info.mtimeset = 0;
133
 
        if (fs->mtime)
134
 
          {
135
 
            if (! fs->mtime (dev, &file_info.mtime))
136
 
              file_info.mtimeset = 1;
137
 
            grub_errno = GRUB_ERR_NONE;
138
 
          }
139
 
      }
140
 
    else
141
 
      (fs->dir) (dev, path, find_file);
142
 
 
143
 
    grub_device_close (dev);
144
 
    grub_free (path);
145
 
    grub_free (device_name);
146
 
  }
147
 
 
148
 
  /* Here we have the real parsing. */
149
 
  while (*argn < argc)
150
 
    {
151
 
      /* First try 3 argument tests. */
152
 
      if (*argn + 2 < argc)
153
 
        {
154
 
          /* String tests. */
155
 
          if (grub_strcmp (args[*argn + 1], "=") == 0
156
 
              || grub_strcmp (args[*argn + 1], "==") == 0)
157
 
            {
158
 
              update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0);
159
 
              (*argn) += 3;
160
 
              continue;
161
 
            }
162
 
 
163
 
          if (grub_strcmp (args[*argn + 1], "!=") == 0)
164
 
            {
165
 
              update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0);
166
 
              (*argn) += 3;
167
 
              continue;
168
 
            }
169
 
 
170
 
          /* GRUB extension: lexicographical sorting. */
171
 
          if (grub_strcmp (args[*argn + 1], "<") == 0)
172
 
            {
173
 
              update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0);
174
 
              (*argn) += 3;
175
 
              continue;
176
 
            }
177
 
 
178
 
          if (grub_strcmp (args[*argn + 1], "<=") == 0)
179
 
            {
180
 
              update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0);
181
 
              (*argn) += 3;
182
 
              continue;
183
 
            }
184
 
 
185
 
          if (grub_strcmp (args[*argn + 1], ">") == 0)
186
 
            {
187
 
              update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0);
188
 
              (*argn) += 3;
189
 
              continue;
190
 
            }
191
 
 
192
 
          if (grub_strcmp (args[*argn + 1], ">=") == 0)
193
 
            {
194
 
              update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0);
195
 
              (*argn) += 3;
196
 
              continue;
197
 
            }
198
 
 
199
 
          /* Number tests. */
200
 
          if (grub_strcmp (args[*argn + 1], "-eq") == 0)
201
 
            {
202
 
              update_val (grub_strtosl (args[*argn], 0, 0)
203
 
                          == grub_strtosl (args[*argn + 2], 0, 0));
204
 
              (*argn) += 3;
205
 
              continue;
206
 
            }
207
 
 
208
 
          if (grub_strcmp (args[*argn + 1], "-ge") == 0)
209
 
            {
210
 
              update_val (grub_strtosl (args[*argn], 0, 0)
211
 
                          >= grub_strtosl (args[*argn + 2], 0, 0));
212
 
              (*argn) += 3;
213
 
              continue;
214
 
            }
215
 
 
216
 
          if (grub_strcmp (args[*argn + 1], "-gt") == 0)
217
 
            {
218
 
              update_val (grub_strtosl (args[*argn], 0, 0)
219
 
                          > grub_strtosl (args[*argn + 2], 0, 0));
220
 
              (*argn) += 3;
221
 
              continue;
222
 
            }
223
 
 
224
 
          if (grub_strcmp (args[*argn + 1], "-le") == 0)
225
 
            {
226
 
              update_val (grub_strtosl (args[*argn], 0, 0)
227
 
                      <= grub_strtosl (args[*argn + 2], 0, 0));
228
 
              (*argn) += 3;
229
 
              continue;
230
 
            }
231
 
 
232
 
          if (grub_strcmp (args[*argn + 1], "-lt") == 0)
233
 
            {
234
 
              update_val (grub_strtosl (args[*argn], 0, 0)
235
 
                          < grub_strtosl (args[*argn + 2], 0, 0));
236
 
              (*argn) += 3;
237
 
              continue;
238
 
            }
239
 
 
240
 
          if (grub_strcmp (args[*argn + 1], "-ne") == 0)
241
 
            {
242
 
              update_val (grub_strtosl (args[*argn], 0, 0)
243
 
                          != grub_strtosl (args[*argn + 2], 0, 0));
244
 
              (*argn) += 3;
245
 
              continue;
246
 
            }
247
 
 
248
 
          /* GRUB extension: compare numbers skipping prefixes.
249
 
             Useful for comparing versions. E.g. vmlinuz-2 -plt vmlinuz-11. */
250
 
          if (grub_strcmp (args[*argn + 1], "-pgt") == 0
251
 
              || grub_strcmp (args[*argn + 1], "-plt") == 0)
252
 
            {
253
 
              int i;
254
 
              /* Skip common prefix. */
255
 
              for (i = 0; args[*argn][i] == args[*argn + 2][i]
256
 
                     && args[*argn][i]; i++);
257
 
 
258
 
              /* Go the digits back. */
259
 
              i--;
260
 
              while (grub_isdigit (args[*argn][i]) && i > 0)
261
 
                i--;
262
 
              i++;
263
 
 
264
 
              if (grub_strcmp (args[*argn + 1], "-pgt") == 0)
265
 
                update_val (grub_strtoul (args[*argn] + i, 0, 0)
266
 
                            > grub_strtoul (args[*argn + 2] + i, 0, 0));
267
 
              else
268
 
                update_val (grub_strtoul (args[*argn] + i, 0, 0)
269
 
                            < grub_strtoul (args[*argn + 2] + i, 0, 0));
270
 
              (*argn) += 3;
271
 
              continue;
272
 
            }
273
 
 
274
 
          /* -nt and -ot tests. GRUB extension: when doing -?t<bias> bias
275
 
             will be added to the first mtime. */
276
 
          if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0
277
 
              || grub_memcmp (args[*argn + 1], "-ot", 3) == 0)
278
 
            {
279
 
              struct grub_dirhook_info file1;
280
 
              int file1exists;
281
 
              int bias = 0;
282
 
 
283
 
              /* Fetch fileinfo. */
284
 
              get_fileinfo (args[*argn]);
285
 
              file1 = file_info;
286
 
              file1exists = file_exists;
287
 
              get_fileinfo (args[*argn + 2]);
288
 
 
289
 
              if (args[*argn + 1][3])
290
 
                bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
291
 
 
292
 
              if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
293
 
                update_val ((file1exists && ! file_exists)
294
 
                            || (file1.mtimeset && file_info.mtimeset
295
 
                                && file1.mtime + bias > file_info.mtime));
296
 
              else
297
 
                update_val ((! file1exists && file_exists)
298
 
                            || (file1.mtimeset && file_info.mtimeset
299
 
                                && file1.mtime + bias < file_info.mtime));
300
 
              (*argn) += 3;
301
 
              continue;
302
 
            }
303
 
        }
304
 
 
305
 
      /* Two-argument tests. */
306
 
      if (*argn + 1 < argc)
307
 
        {
308
 
          /* File tests. */
309
 
          if (grub_strcmp (args[*argn], "-d") == 0)
310
 
            {
311
 
              get_fileinfo (args[*argn + 1]);
312
 
              update_val (file_exists && file_info.dir);
313
 
              (*argn) += 2;
314
 
              return ret;
315
 
            }
316
 
 
317
 
          if (grub_strcmp (args[*argn], "-e") == 0)
318
 
            {
319
 
              get_fileinfo (args[*argn + 1]);
320
 
              update_val (file_exists);
321
 
              (*argn) += 2;
322
 
              return ret;
323
 
            }
324
 
 
325
 
          if (grub_strcmp (args[*argn], "-f") == 0)
326
 
            {
327
 
              get_fileinfo (args[*argn + 1]);
328
 
              /* FIXME: check for other types. */
329
 
              update_val (file_exists && ! file_info.dir);
330
 
              (*argn) += 2;
331
 
              return ret;
332
 
            }
333
 
 
334
 
          if (grub_strcmp (args[*argn], "-s") == 0)
335
 
            {
336
 
              grub_file_t file;
337
 
              file = grub_file_open (args[*argn + 1]);
338
 
              update_val (file && (grub_file_size (file) != 0));
339
 
              if (file)
340
 
                grub_file_close (file);
341
 
              grub_errno = GRUB_ERR_NONE;
342
 
              (*argn) += 2;
343
 
              return ret;
344
 
            }
345
 
 
346
 
          /* String tests. */
347
 
          if (grub_strcmp (args[*argn], "-n") == 0)
348
 
            {
349
 
              update_val (args[*argn + 1][0]);
350
 
 
351
 
              (*argn) += 2;
352
 
              continue;
353
 
            }
354
 
          if (grub_strcmp (args[*argn], "-z") == 0)
355
 
            {
356
 
              update_val (! args[*argn + 1][0]);
357
 
              (*argn) += 2;
358
 
              continue;
359
 
            }
360
 
        }
361
 
 
362
 
      /* Special modifiers. */
363
 
 
364
 
      /* End of expression. return to parent. */
365
 
      if (grub_strcmp (args[*argn], ")") == 0)
366
 
        {
367
 
          (*argn)++;
368
 
          return ret;
369
 
        }
370
 
      /* Recursively invoke if parenthesis. */
371
 
      if (grub_strcmp (args[*argn], "(") == 0)
372
 
        {
373
 
          (*argn)++;
374
 
          update_val (test_parse (args, argn, argc));
375
 
          continue;
376
 
        }
377
 
 
378
 
      if (grub_strcmp (args[*argn], "!") == 0)
379
 
        {
380
 
          invert = ! invert;
381
 
          (*argn)++;
382
 
          continue;
383
 
        }
384
 
      if (grub_strcmp (args[*argn], "-a") == 0)
385
 
        {
386
 
          /* If current value is 0 second value is to be discarded. */
387
 
          discard = ! ret;
388
 
          (*argn)++;
389
 
          continue;
390
 
        }
391
 
      if (grub_strcmp (args[*argn], "-o") == 0)
392
 
        {
393
 
          /* If current value is 1 second value is to be discarded. */
394
 
          discard = ret;
395
 
          (*argn)++;
396
 
          continue;
397
 
        }
398
 
 
399
 
      /* No test found. Interpret if as just a string. */
400
 
      update_val (args[*argn][0]);
401
 
      (*argn)++;
402
 
    }
403
 
  return ret;
404
 
}
405
 
 
406
 
static grub_err_t
407
 
grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
408
 
               int argc, char **args)
409
 
{
410
 
  int argn = 0;
411
 
 
412
 
  if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
413
 
    argc--;
414
 
 
415
 
  return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
416
 
    : grub_error (GRUB_ERR_TEST_FAILURE, "false");
417
 
}
418
 
 
419
 
static grub_command_t cmd_1, cmd_2;
420
 
 
421
 
GRUB_MOD_INIT(test)
422
 
{
423
 
  cmd_1 = grub_register_command ("[", grub_cmd_test,
424
 
                                 N_("EXPRESSION ]"), N_("Evaluate an expression."));
425
 
  cmd_2 = grub_register_command ("test", grub_cmd_test,
426
 
                                 N_("EXPRESSION"), N_("Evaluate an expression."));
427
 
}
428
 
 
429
 
GRUB_MOD_FINI(test)
430
 
{
431
 
  grub_unregister_command (cmd_1);
432
 
  grub_unregister_command (cmd_2);
433
 
}