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

« back to all changes in this revision

Viewing changes to grub-core/gettext/gettext.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
/* gettext.c - gettext module */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 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/list.h>
 
21
#include <grub/types.h>
 
22
#include <grub/misc.h>
 
23
#include <grub/mm.h>
 
24
#include <grub/err.h>
 
25
#include <grub/dl.h>
 
26
#include <grub/normal.h>
 
27
#include <grub/file.h>
 
28
#include <grub/kernel.h>
 
29
#include <grub/i18n.h>
 
30
 
 
31
/*
 
32
   .mo file information from:
 
33
   http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html .
 
34
*/
 
35
 
 
36
 
 
37
static grub_file_t fd_mo;
 
38
 
 
39
static int grub_gettext_offsetoriginal;
 
40
static int grub_gettext_max;
 
41
 
 
42
static const char *(*grub_gettext_original) (const char *s);
 
43
 
 
44
struct grub_gettext_msg
 
45
{
 
46
  struct grub_gettext_msg *next;
 
47
  const char *name;
 
48
 
 
49
  const char *translated;
 
50
};
 
51
 
 
52
struct grub_gettext_msg *grub_gettext_msg_list = NULL;
 
53
 
 
54
#define GETTEXT_MAGIC_NUMBER            0
 
55
#define GETTEXT_FILE_FORMAT             4
 
56
#define GETTEXT_NUMBER_OF_STRINGS       8
 
57
#define GETTEXT_OFFSET_ORIGINAL         12
 
58
#define GETTEXT_OFFSET_TRANSLATION      16
 
59
 
 
60
#define MO_MAGIC_NUMBER                 0x950412de
 
61
 
 
62
static grub_ssize_t
 
63
grub_gettext_pread (grub_file_t file, void *buf, grub_size_t len,
 
64
                    grub_off_t offset)
 
65
{
 
66
  if (grub_file_seek (file, offset) == (grub_off_t) - 1)
 
67
    {
 
68
      return -1;
 
69
    }
 
70
  return grub_file_read (file, buf, len);
 
71
}
 
72
 
 
73
static grub_uint32_t
 
74
grub_gettext_get_info (int offset)
 
75
{
 
76
  grub_uint32_t value;
 
77
 
 
78
  grub_gettext_pread (fd_mo, (char *) &value, 4, offset);
 
79
 
 
80
  value = grub_cpu_to_le32 (value);
 
81
  return value;
 
82
}
 
83
 
 
84
static void
 
85
grub_gettext_getstring_from_offset (grub_uint32_t offset,
 
86
                                    grub_uint32_t length, char *translation)
 
87
{
 
88
  grub_gettext_pread (fd_mo, translation, length, offset);
 
89
  translation[length] = '\0';
 
90
}
 
91
 
 
92
static const char *
 
93
grub_gettext_gettranslation_from_position (int position)
 
94
{
 
95
  int offsettranslation;
 
96
  int internal_position;
 
97
  grub_uint32_t length, offset;
 
98
  char *translation;
 
99
 
 
100
  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
 
101
 
 
102
  internal_position = offsettranslation + position * 8;
 
103
 
 
104
  grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position);
 
105
  length = grub_cpu_to_le32 (length);
 
106
 
 
107
  grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4);
 
108
  offset = grub_cpu_to_le32 (offset);
 
109
 
 
110
  translation = grub_malloc (length + 1);
 
111
  grub_gettext_getstring_from_offset (offset, length, translation);
 
112
 
 
113
  return translation;
 
114
}
 
115
 
 
116
static char *
 
117
grub_gettext_getstring_from_position (int position)
 
118
{
 
119
  int internal_position;
 
120
  int length, offset;
 
121
  char *original;
 
122
 
 
123
  /* Get position for string i.  */
 
124
  internal_position = grub_gettext_offsetoriginal + (position * 8);
 
125
 
 
126
  /* Get the length of the string i.  */
 
127
  grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position);
 
128
 
 
129
  /* Get the offset of the string i.  */
 
130
  grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4);
 
131
 
 
132
  /* Get the string i.  */
 
133
  original = grub_malloc (length + 1);
 
134
  grub_gettext_getstring_from_offset (offset, length, original);
 
135
 
 
136
  return original;
 
137
}
 
138
 
 
139
static const char *
 
140
grub_gettext_translate (const char *orig)
 
141
{
 
142
  char *current_string;
 
143
  const char *ret;
 
144
 
 
145
  int min, max, current;
 
146
  int found = 0;
 
147
 
 
148
  struct grub_gettext_msg *cur;
 
149
 
 
150
  /* Make sure we can use grub_gettext_translate for error messages.  Push
 
151
     active error message to error stack and reset error message.  */
 
152
  grub_error_push ();
 
153
 
 
154
  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_gettext_msg_list),
 
155
                              orig);
 
156
 
 
157
  if (cur)
 
158
    {
 
159
      grub_error_pop ();
 
160
      return cur->translated;
 
161
    }
 
162
 
 
163
  if (fd_mo == 0)
 
164
    {
 
165
      grub_error_pop ();
 
166
      return orig;
 
167
    }
 
168
 
 
169
  min = 0;
 
170
  max = grub_gettext_max;
 
171
 
 
172
  current = (max + min) / 2;
 
173
 
 
174
  while (current != min && current != max && found == 0)
 
175
    {
 
176
      current_string = grub_gettext_getstring_from_position (current);
 
177
 
 
178
      /* Search by bisection.  */
 
179
      if (grub_strcmp (current_string, orig) < 0)
 
180
        {
 
181
          grub_free (current_string);
 
182
          min = current;
 
183
        }
 
184
      else if (grub_strcmp (current_string, orig) > 0)
 
185
        {
 
186
          grub_free (current_string);
 
187
          max = current;
 
188
        }
 
189
      else if (grub_strcmp (current_string, orig) == 0)
 
190
        {
 
191
          grub_free (current_string);
 
192
          found = 1;
 
193
        }
 
194
      current = (max + min) / 2;
 
195
    }
 
196
 
 
197
  ret = found ? grub_gettext_gettranslation_from_position (current) : orig;
 
198
 
 
199
  if (found)
 
200
    {
 
201
      cur = grub_zalloc (sizeof (*cur));
 
202
 
 
203
      if (cur)
 
204
        {
 
205
          cur->name = grub_strdup (orig);
 
206
          if (cur->name)
 
207
            {
 
208
              cur->translated = ret;
 
209
              grub_list_push (GRUB_AS_LIST_P (&grub_gettext_msg_list),
 
210
                              GRUB_AS_LIST (cur));
 
211
            }
 
212
        }
 
213
      else
 
214
        grub_errno = GRUB_ERR_NONE;
 
215
    }
 
216
 
 
217
  grub_error_pop ();
 
218
  return ret;
 
219
}
 
220
 
 
221
/* This is similar to grub_file_open. */
 
222
static grub_file_t
 
223
grub_mofile_open (const char *filename)
 
224
{
 
225
  int unsigned magic;
 
226
  int version;
 
227
 
 
228
  /* Using fd_mo and not another variable because
 
229
     it's needed for grub_gettext_get_info.  */
 
230
 
 
231
  fd_mo = grub_file_open (filename);
 
232
  grub_errno = GRUB_ERR_NONE;
 
233
 
 
234
  if (!fd_mo)
 
235
    {
 
236
      grub_dprintf ("gettext", "Cannot read %s\n", filename);
 
237
      return 0;
 
238
    }
 
239
 
 
240
  magic = grub_gettext_get_info (GETTEXT_MAGIC_NUMBER);
 
241
 
 
242
  if (magic != MO_MAGIC_NUMBER)
 
243
    {
 
244
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo file: %s",
 
245
                  filename);
 
246
      grub_file_close (fd_mo);
 
247
      fd_mo = 0;
 
248
      return 0;
 
249
    }
 
250
 
 
251
  version = grub_gettext_get_info (GETTEXT_FILE_FORMAT);
 
252
 
 
253
  if (version != 0)
 
254
    {
 
255
      grub_error (GRUB_ERR_BAD_FILE_TYPE,
 
256
                  "mo: invalid mo version in file: %s", filename);
 
257
      fd_mo = 0;
 
258
      return 0;
 
259
    }
 
260
 
 
261
  return fd_mo;
 
262
}
 
263
 
 
264
static void
 
265
grub_gettext_init_ext (const char *lang)
 
266
{
 
267
  char *mo_file;
 
268
  char *locale_dir;
 
269
 
 
270
  locale_dir = grub_env_get ("locale_dir");
 
271
  if (locale_dir == NULL)
 
272
    {
 
273
      grub_dprintf ("gettext", "locale_dir variable is not set up.\n");
 
274
      return;
 
275
    }
 
276
 
 
277
  fd_mo = NULL;
 
278
 
 
279
  /* mo_file e.g.: /boot/grub/locale/ca.mo   */
 
280
 
 
281
  mo_file = grub_xasprintf ("%s/%s.mo", locale_dir, lang);
 
282
  if (!mo_file)
 
283
    return;
 
284
 
 
285
  fd_mo = grub_mofile_open (mo_file);
 
286
 
 
287
  /* Will try adding .gz as well.  */
 
288
  if (fd_mo == NULL)
 
289
    {
 
290
      char *mo_file_old;
 
291
      mo_file_old = mo_file;
 
292
      mo_file = grub_xasprintf ("%s.gz", mo_file);
 
293
      grub_free (mo_file_old);
 
294
      if (!mo_file)
 
295
        return;
 
296
      fd_mo = grub_mofile_open (mo_file);
 
297
    }
 
298
 
 
299
  if (fd_mo)
 
300
    {
 
301
      grub_gettext_offsetoriginal =
 
302
        grub_gettext_get_info (GETTEXT_OFFSET_ORIGINAL);
 
303
      grub_gettext_max = grub_gettext_get_info (GETTEXT_NUMBER_OF_STRINGS);
 
304
 
 
305
      grub_gettext_original = grub_gettext;
 
306
      grub_gettext = grub_gettext_translate;
 
307
    }
 
308
}
 
309
 
 
310
static void
 
311
grub_gettext_delete_list (void)
 
312
{
 
313
  while (grub_gettext_msg_list)
 
314
    {
 
315
      grub_free ((char *) grub_gettext_msg_list->name);
 
316
      grub_gettext_msg_list = grub_gettext_msg_list->next;
 
317
      /* Don't delete the translated message because could be in use.  */
 
318
    }
 
319
}
 
320
 
 
321
static char *
 
322
grub_gettext_env_write_lang (struct grub_env_var *var
 
323
                             __attribute__ ((unused)), const char *val)
 
324
{
 
325
  grub_gettext_init_ext (val);
 
326
 
 
327
  grub_gettext_delete_list ();
 
328
 
 
329
  return grub_strdup (val);
 
330
}
 
331
 
 
332
static grub_err_t
 
333
grub_cmd_translate (grub_command_t cmd __attribute__ ((unused)),
 
334
                    int argc, char **args)
 
335
{
 
336
  if (argc != 1)
 
337
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
 
338
 
 
339
  const char *translation;
 
340
  translation = grub_gettext_translate (args[0]);
 
341
  grub_printf ("%s\n", translation);
 
342
  return 0;
 
343
}
 
344
 
 
345
GRUB_MOD_INIT (gettext)
 
346
{
 
347
  (void) mod;                   /* To stop warning.  */
 
348
 
 
349
  const char *lang;
 
350
 
 
351
  lang = grub_env_get ("lang");
 
352
 
 
353
  grub_gettext_init_ext (lang);
 
354
 
 
355
  grub_register_command_p1 ("gettext", grub_cmd_translate,
 
356
                            N_("STRING"),
 
357
                            N_("Translates the string with the current settings."));
 
358
 
 
359
  /* Reload .mo file information if lang changes.  */
 
360
  grub_register_variable_hook ("lang", NULL, grub_gettext_env_write_lang);
 
361
 
 
362
  /* Preserve hooks after context changes.  */
 
363
  grub_env_export ("lang");
 
364
}
 
365
 
 
366
GRUB_MOD_FINI (gettext)
 
367
{
 
368
  if (fd_mo != 0)
 
369
    grub_file_close (fd_mo);
 
370
 
 
371
  grub_gettext_delete_list ();
 
372
 
 
373
  grub_gettext = grub_gettext_original;
 
374
}