~ubuntu-branches/ubuntu/wily/grub2/wily-proposed

« back to all changes in this revision

Viewing changes to kern/env.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Zielcke, Robert Millan, Felix Zielcke
  • Date: 2010-01-26 19:26:25 UTC
  • mfrom: (1.13.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20100126192625-coq6czap2ofjollf
Tags: 1.98~20100126-1
* New Bazaar snapshot.
  - Includes mipsel-yeeloong port.

[ Robert Millan ]
* config.in: Lower priority of grub2/linux_cmdline_default.

[ Felix Zielcke ]
* Drop `CFLAGS=-O0' workaround on powerpc. Should be fixed correctly now.
* Ship grub-bin2h and grub-script-check in grub-common.
* Terminate NEWS.Debian with a blank line like lintian would suggest
  if that check would be working correctly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
#include <grub/env.h>
 
21
#include <grub/env_private.h>
21
22
#include <grub/misc.h>
22
23
#include <grub/mm.h>
23
24
 
24
 
/* The size of the hash table.  */
25
 
#define HASHSZ  13
26
 
 
27
 
/* A hashtable for quick lookup of variables.  */
28
 
struct grub_env_context
29
 
{
30
 
  /* A hash table for variables.  */
31
 
  struct grub_env_var *vars[HASHSZ];
32
 
 
33
 
  /* One level deeper on the stack.  */
34
 
  struct grub_env_context *prev;
35
 
};
36
 
 
37
 
/* This is used for sorting only.  */
38
 
struct grub_env_sorted_var
39
 
{
40
 
  struct grub_env_var *var;
41
 
  struct grub_env_sorted_var *next;
42
 
};
43
 
 
44
25
/* The initial context.  */
45
26
static struct grub_env_context initial_context;
46
27
 
47
28
/* The current context.  */
48
 
static struct grub_env_context *current_context = &initial_context;
 
29
struct grub_env_context *grub_current_context = &initial_context;
49
30
 
50
31
/* Return the hash representation of the string S.  */
51
32
static unsigned int
60
41
  return i % HASHSZ;
61
42
}
62
43
 
63
 
static struct grub_env_var *
 
44
struct grub_env_var *
64
45
grub_env_find (const char *name)
65
46
{
66
47
  struct grub_env_var *var;
67
48
  int idx = grub_env_hashval (name);
68
49
 
69
50
  /* Look for the variable in the current context.  */
70
 
  for (var = current_context->vars[idx]; var; var = var->next)
 
51
  for (var = grub_current_context->vars[idx]; var; var = var->next)
71
52
    if (grub_strcmp (var->name, name) == 0)
72
53
      return var;
73
54
 
74
55
  return 0;
75
56
}
76
57
 
77
 
grub_err_t
78
 
grub_env_context_open (int export)
79
 
{
80
 
  struct grub_env_context *context;
81
 
  int i;
82
 
 
83
 
  context = grub_zalloc (sizeof (*context));
84
 
  if (! context)
85
 
    return grub_errno;
86
 
 
87
 
  context->prev = current_context;
88
 
  current_context = context;
89
 
 
90
 
  /* Copy exported variables.  */
91
 
  for (i = 0; i < HASHSZ; i++)
92
 
    {
93
 
      struct grub_env_var *var;
94
 
 
95
 
      for (var = context->prev->vars[i]; var; var = var->next)
96
 
        {
97
 
          if (export && var->type == GRUB_ENV_VAR_GLOBAL)
98
 
            {
99
 
              if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
100
 
                {
101
 
                  grub_env_context_close ();
102
 
                  return grub_errno;
103
 
                }
104
 
              grub_env_export (var->name);
105
 
              grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
106
 
            }
107
 
        }
108
 
    }
109
 
 
110
 
  return GRUB_ERR_NONE;
111
 
}
112
 
 
113
 
grub_err_t
114
 
grub_env_context_close (void)
115
 
{
116
 
  struct grub_env_context *context;
117
 
  int i;
118
 
 
119
 
  if (! current_context->prev)
120
 
    grub_fatal ("cannot close the initial context");
121
 
 
122
 
  /* Free the variables associated with this context.  */
123
 
  for (i = 0; i < HASHSZ; i++)
124
 
    {
125
 
      struct grub_env_var *p, *q;
126
 
 
127
 
      for (p = current_context->vars[i]; p; p = q)
128
 
        {
129
 
          q = p->next;
130
 
          grub_free (p->name);
131
 
          if (p->type != GRUB_ENV_VAR_DATA)
132
 
            grub_free (p->value);
133
 
          grub_free (p);
134
 
        }
135
 
    }
136
 
 
137
 
  /* Restore the previous context.  */
138
 
  context = current_context->prev;
139
 
  grub_free (current_context);
140
 
  current_context = context;
141
 
 
142
 
  return GRUB_ERR_NONE;
143
 
}
144
 
 
145
58
static void
146
59
grub_env_insert (struct grub_env_context *context,
147
60
                 struct grub_env_var *var)
166
79
}
167
80
 
168
81
grub_err_t
169
 
grub_env_export (const char *name)
170
 
{
171
 
  struct grub_env_var *var;
172
 
 
173
 
  var = grub_env_find (name);
174
 
  if (! var)
175
 
    {
176
 
      grub_err_t err;
177
 
     
178
 
      err = grub_env_set (name, "");
179
 
      if (err)
180
 
        return err;
181
 
      var = grub_env_find (name);
182
 
    }   
183
 
  var->type = GRUB_ENV_VAR_GLOBAL;
184
 
 
185
 
  return GRUB_ERR_NONE;
186
 
}
187
 
 
188
 
grub_err_t
189
82
grub_env_set (const char *name, const char *val)
190
83
{
191
84
  struct grub_env_var *var;
216
109
  if (! var)
217
110
    return grub_errno;
218
111
 
219
 
  /* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave
220
 
     this for readability.  */
221
 
  var->type = GRUB_ENV_VAR_LOCAL;
 
112
  /* This is not necessary. But leave this for readability.  */
 
113
  var->global = 0;
222
114
 
223
115
  var->name = grub_strdup (name);
224
116
  if (! var->name)
228
120
  if (! var->value)
229
121
    goto fail;
230
122
 
231
 
  grub_env_insert (current_context, var);
 
123
  grub_env_insert (grub_current_context, var);
232
124
 
233
125
  return GRUB_ERR_NONE;
234
126
 
273
165
  grub_env_remove (var);
274
166
 
275
167
  grub_free (var->name);
276
 
  if (var->type != GRUB_ENV_VAR_DATA)
277
 
    grub_free (var->value);
 
168
  grub_free (var->value);
278
169
  grub_free (var);
279
170
}
280
171
 
290
181
    {
291
182
      struct grub_env_var *var;
292
183
 
293
 
      for (var = current_context->vars[i]; var; var = var->next)
 
184
      for (var = grub_current_context->vars[i]; var; var = var->next)
294
185
        {
295
186
          struct grub_env_sorted_var *p, **q;
296
187
 
297
 
          /* Ignore data slots.  */
298
 
          if (var->type == GRUB_ENV_VAR_DATA)
299
 
            continue;
300
 
 
301
188
          sorted_var = grub_malloc (sizeof (*sorted_var));
302
189
          if (! sorted_var)
303
190
            goto fail;
353
240
 
354
241
  return GRUB_ERR_NONE;
355
242
}
356
 
 
357
 
static char *
358
 
mangle_data_slot_name (const char *name)
359
 
{
360
 
  char *mangled_name;
361
 
 
362
 
  mangled_name = grub_malloc (grub_strlen (name) + 2);
363
 
  if (! mangled_name)
364
 
    return 0;
365
 
 
366
 
  grub_sprintf (mangled_name, "\e%s", name);
367
 
  return mangled_name;
368
 
}
369
 
 
370
 
grub_err_t
371
 
grub_env_set_data_slot (const char *name, const void *ptr)
372
 
{
373
 
  char *mangled_name;
374
 
  struct grub_env_var *var;
375
 
 
376
 
  mangled_name = mangle_data_slot_name (name);
377
 
  if (! mangled_name)
378
 
    goto fail;
379
 
 
380
 
  /* If the variable does already exist, just update the variable.  */
381
 
  var = grub_env_find (mangled_name);
382
 
  if (var)
383
 
    {
384
 
      var->value = (char *) ptr;
385
 
      return GRUB_ERR_NONE;
386
 
    }
387
 
 
388
 
  /* The variable does not exist, so create a new one.  */
389
 
  var = grub_zalloc (sizeof (*var));
390
 
  if (! var)
391
 
    goto fail;
392
 
 
393
 
  var->type = GRUB_ENV_VAR_DATA;
394
 
  var->name = mangled_name;
395
 
  var->value = (char *) ptr;
396
 
 
397
 
  grub_env_insert (current_context, var);
398
 
 
399
 
  return GRUB_ERR_NONE;
400
 
 
401
 
 fail:
402
 
 
403
 
  grub_free (mangled_name);
404
 
  return grub_errno;
405
 
}
406
 
 
407
 
void *
408
 
grub_env_get_data_slot (const char *name)
409
 
{
410
 
  char *mangled_name;
411
 
  void *ptr = 0;
412
 
 
413
 
  mangled_name = mangle_data_slot_name (name);
414
 
  if (! mangled_name)
415
 
    goto fail;
416
 
 
417
 
  ptr = grub_env_get (mangled_name);
418
 
  grub_free (mangled_name);
419
 
 
420
 
 fail:
421
 
 
422
 
  return ptr;
423
 
}
424
 
 
425
 
void
426
 
grub_env_unset_data_slot (const char *name)
427
 
{
428
 
  char *mangled_name;
429
 
 
430
 
  mangled_name = mangle_data_slot_name (name);
431
 
  if (! mangled_name)
432
 
    return;
433
 
 
434
 
  grub_env_unset (mangled_name);
435
 
  grub_free (mangled_name);
436
 
}