20
20
#include <grub/env.h>
21
#include <grub/env_private.h>
21
22
#include <grub/misc.h>
22
23
#include <grub/mm.h>
24
/* The size of the hash table. */
27
/* A hashtable for quick lookup of variables. */
28
struct grub_env_context
30
/* A hash table for variables. */
31
struct grub_env_var *vars[HASHSZ];
33
/* One level deeper on the stack. */
34
struct grub_env_context *prev;
37
/* This is used for sorting only. */
38
struct grub_env_sorted_var
40
struct grub_env_var *var;
41
struct grub_env_sorted_var *next;
44
25
/* The initial context. */
45
26
static struct grub_env_context initial_context;
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;
50
31
/* Return the hash representation of the string S. */
51
32
static unsigned int
63
static struct grub_env_var *
64
45
grub_env_find (const char *name)
66
47
struct grub_env_var *var;
67
48
int idx = grub_env_hashval (name);
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)
78
grub_env_context_open (int export)
80
struct grub_env_context *context;
83
context = grub_zalloc (sizeof (*context));
87
context->prev = current_context;
88
current_context = context;
90
/* Copy exported variables. */
91
for (i = 0; i < HASHSZ; i++)
93
struct grub_env_var *var;
95
for (var = context->prev->vars[i]; var; var = var->next)
97
if (export && var->type == GRUB_ENV_VAR_GLOBAL)
99
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
101
grub_env_context_close ();
104
grub_env_export (var->name);
105
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
110
return GRUB_ERR_NONE;
114
grub_env_context_close (void)
116
struct grub_env_context *context;
119
if (! current_context->prev)
120
grub_fatal ("cannot close the initial context");
122
/* Free the variables associated with this context. */
123
for (i = 0; i < HASHSZ; i++)
125
struct grub_env_var *p, *q;
127
for (p = current_context->vars[i]; p; p = q)
131
if (p->type != GRUB_ENV_VAR_DATA)
132
grub_free (p->value);
137
/* Restore the previous context. */
138
context = current_context->prev;
139
grub_free (current_context);
140
current_context = context;
142
return GRUB_ERR_NONE;
146
59
grub_env_insert (struct grub_env_context *context,
147
60
struct grub_env_var *var)
169
grub_env_export (const char *name)
171
struct grub_env_var *var;
173
var = grub_env_find (name);
178
err = grub_env_set (name, "");
181
var = grub_env_find (name);
183
var->type = GRUB_ENV_VAR_GLOBAL;
185
return GRUB_ERR_NONE;
189
82
grub_env_set (const char *name, const char *val)
191
84
struct grub_env_var *var;
217
110
return grub_errno;
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. */
223
115
var->name = grub_strdup (name);
291
182
struct grub_env_var *var;
293
for (var = current_context->vars[i]; var; var = var->next)
184
for (var = grub_current_context->vars[i]; var; var = var->next)
295
186
struct grub_env_sorted_var *p, **q;
297
/* Ignore data slots. */
298
if (var->type == GRUB_ENV_VAR_DATA)
301
188
sorted_var = grub_malloc (sizeof (*sorted_var));
302
189
if (! sorted_var)
354
241
return GRUB_ERR_NONE;
358
mangle_data_slot_name (const char *name)
362
mangled_name = grub_malloc (grub_strlen (name) + 2);
366
grub_sprintf (mangled_name, "\e%s", name);
371
grub_env_set_data_slot (const char *name, const void *ptr)
374
struct grub_env_var *var;
376
mangled_name = mangle_data_slot_name (name);
380
/* If the variable does already exist, just update the variable. */
381
var = grub_env_find (mangled_name);
384
var->value = (char *) ptr;
385
return GRUB_ERR_NONE;
388
/* The variable does not exist, so create a new one. */
389
var = grub_zalloc (sizeof (*var));
393
var->type = GRUB_ENV_VAR_DATA;
394
var->name = mangled_name;
395
var->value = (char *) ptr;
397
grub_env_insert (current_context, var);
399
return GRUB_ERR_NONE;
403
grub_free (mangled_name);
408
grub_env_get_data_slot (const char *name)
413
mangled_name = mangle_data_slot_name (name);
417
ptr = grub_env_get (mangled_name);
418
grub_free (mangled_name);
426
grub_env_unset_data_slot (const char *name)
430
mangled_name = mangle_data_slot_name (name);
434
grub_env_unset (mangled_name);
435
grub_free (mangled_name);