1 /* envblk.c - Common functions for environment block. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
24 #include <grub/lib/envblk.h>
27 grub_envblk_open (char *buf
, grub_size_t size
)
31 if (size
< sizeof (GRUB_ENVBLK_SIGNATURE
)
32 || grub_memcmp (buf
, GRUB_ENVBLK_SIGNATURE
,
33 sizeof (GRUB_ENVBLK_SIGNATURE
) - 1))
35 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "invalid environment block");
39 envblk
= grub_malloc (sizeof (*envblk
));
50 grub_envblk_close (grub_envblk_t envblk
)
52 grub_free (envblk
->buf
);
57 escaped_value_len (const char *value
)
62 for (p
= (char *) value
; *p
; p
++)
64 if (*p
== '\\' || *p
== '\n')
74 find_next_line (char *p
, const char *pend
)
90 grub_envblk_set (grub_envblk_t envblk
, const char *name
, const char *value
)
99 nl
= grub_strlen (name
);
100 vl
= escaped_value_len (value
);
101 p
= envblk
->buf
+ sizeof (GRUB_ENVBLK_SIGNATURE
) - 1;
102 pend
= envblk
->buf
+ envblk
->size
;
104 /* First, look at free space. */
105 for (space
= pend
- 1; *space
== '#'; space
--)
114 while (p
+ nl
+ 1 < space
)
116 if (grub_memcmp (p
, name
, nl
) == 0 && p
[nl
] == '=')
120 /* Found the same name. */
123 /* Check the length of the current value. */
125 while (p
+ len
< pend
&& p
[len
] != '\n')
137 if (pend
- space
< vl
- len
)
143 /* Move the following characters backward, and fill the new
144 space with harmless characters. */
145 grub_memmove (p
+ vl
, p
+ len
, pend
- (p
+ len
));
146 grub_memset (space
+ len
- vl
, '#', len
- vl
);
149 /* Move the following characters forward. */
150 grub_memmove (p
+ vl
, p
+ len
, pend
- (p
+ vl
));
156 p
= find_next_line (p
, pend
);
161 /* Append a new variable. */
163 if (pend
- space
< nl
+ 1 + vl
+ 1)
167 grub_memcpy (space
, name
, nl
);
172 /* Write the value. */
173 for (i
= 0; value
[i
]; i
++)
175 if (value
[i
] == '\\' || value
[i
] == '\n')
186 grub_envblk_delete (grub_envblk_t envblk
, const char *name
)
191 nl
= grub_strlen (name
);
192 p
= envblk
->buf
+ sizeof (GRUB_ENVBLK_SIGNATURE
) - 1;
193 pend
= envblk
->buf
+ envblk
->size
;
195 while (p
+ nl
+ 1 < pend
)
197 if (grub_memcmp (p
, name
, nl
) == 0 && p
[nl
] == '=')
202 while (p
+ len
< pend
)
206 else if (p
[len
] == '\\')
217 grub_memmove (p
, p
+ len
, pend
- (p
+ len
));
218 grub_memset (pend
- len
, '#', len
);
222 p
= find_next_line (p
, pend
);
227 grub_envblk_iterate (grub_envblk_t envblk
,
228 int hook (const char *name
, const char *value
))
232 p
= envblk
->buf
+ sizeof (GRUB_ENVBLK_SIGNATURE
) - 1;
233 pend
= envblk
->buf
+ envblk
->size
;
241 char *name_start
, *name_end
, *value_start
;
246 while (p
< pend
&& *p
!= '=')
269 name
= grub_malloc (p
- name_start
+ 1);
274 value
= name
+ (value_start
- name_start
);
276 grub_memcpy (name
, name_start
, name_end
- name_start
);
277 name
[name_end
- name_start
] = '\0';
279 for (p
= value_start
, q
= value
; *p
!= '\n'; ++p
)
288 ret
= hook (name
, value
);
294 p
= find_next_line (p
, pend
);