]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/SuSE10.2/stage2-wildcard.diff
Hinzugefuegt:
[ipfire-2.x.git] / src / patches / SuSE10.2 / stage2-wildcard.diff
CommitLineData
73276c91
HS
1Index: grub-0.95/stage2/shared.h
2===================================================================
3--- grub-0.95.orig/stage2/shared.h
4+++ grub-0.95/stage2/shared.h
5@@ -1008,9 +1008,11 @@ int grub_seek (int offset);
6 /* Close a file. */
7 void grub_close (void);
8
9-/* List the contents of the directory that was opened with GRUB_OPEN,
10- printing all completions. */
11-int dir (char *dirname);
12+/* List the contents of DIRECTORY. */
13+int dir (char *dirname, void (*handle)(char *));
14+
15+/* Wildcard expand the last pathname component of GLOB. */
16+char *wildcard (char *glob);
17
18 int set_bootdev (int hdbias);
19
20Index: grub-0.95/stage2/stage2.c
21===================================================================
22--- grub-0.95.orig/stage2/stage2.c
23+++ grub-0.95/stage2/stage2.c
24@@ -1240,6 +1240,192 @@ get_line_from_config (char *cmdline, int
25 }
26
27
28+char *wildcard_prefix, *wildcard_suffix;
29+char wildcard_matches[1024], *end_wildcard_matches;
30+
31+static void wildcard_handler(char *name);
32+
33+/* Match one directory entry against the current wildcard. If the entry
34+ matches, store it in WILDCARD_MATCHES. Silently ignore entries that
35+ don't fit into WILDCARD_MATCHES anymore. */
36+static void
37+wildcard_handler(char *name)
38+{
39+ char *n = name, *p = wildcard_prefix;
40+
41+ while (*p && *p == *n)
42+ {
43+ p++;
44+ n++;
45+ }
46+ if (*p)
47+ return; /* prefix mismatch */
48+
49+ p = name + grub_strlen (name) - grub_strlen (wildcard_suffix);
50+ /* [n .. p) is the part matching the asterisk */
51+
52+ if (p <= n || grub_strcmp (p, wildcard_suffix) != 0)
53+ return; /* zero-length match or suffix mismatch */
54+
55+ /* store this match */
56+ if (p - n + 2 > sizeof (wildcard_matches) -
57+ (end_wildcard_matches - wildcard_matches))
58+ return; /* out of space */
59+ while (n < p)
60+ *end_wildcard_matches++ = *n++;
61+ *end_wildcard_matches++ = 0;
62+}
63+
64+/* Wildcard expand the GLOB argument. Return NULL upon failure, or
65+ a list of 0-terminated expansions, terminated by a zero-length string. */
66+char *
67+wildcard (char *glob)
68+{
69+ char path[128], *p;
70+ int ret;
71+
72+ end_wildcard_matches = wildcard_matches;
73+ if (grub_strlen (glob) + 1 > sizeof (path)) {
74+ errnum = ERR_FILELENGTH;
75+ return NULL; /* cannot handle pathnames this long */
76+ }
77+ grub_strcpy (path, glob);
78+ p = path;
79+ while (*p)
80+ p++;
81+ wildcard_suffix = p;
82+ while (p > path && *p != '/')
83+ p--;
84+ if (*p != '/')
85+ {
86+ errnum = ERR_BAD_FILETYPE;
87+ return NULL; /* Cannot wildcard device names */
88+ }
89+ *(++p) = 0;
90+ wildcard_prefix = glob + (p - path);
91+ for (p = wildcard_prefix;; p++)
92+ {
93+ if (*p == 0)
94+ {
95+ /* We cannot do exact matches: this cannot be represented in the
96+ result list. */
97+ return NULL;
98+ }
99+ else if (*p == '*')
100+ {
101+ *p++ = 0;
102+ wildcard_suffix = p;
103+ break;
104+ }
105+ }
106+
107+ ret = dir (path, wildcard_handler);
108+ /* restore original argument */
109+ wildcard_prefix[grub_strlen (wildcard_prefix)] = '*';
110+ if (!ret)
111+ return NULL;
112+ *end_wildcard_matches++ = 0;
113+ return wildcard_matches;
114+}
115+
116+#define skip(str) ((str) + grub_strlen (str) + 1)
117+
118+static void inplace_sort (char *str);
119+
120+static void
121+inplace_sort (char *str)
122+{
123+ int m, n = 0;
124+ char *s, *t, *x;
125+
126+ for (s = str; *s; s = skip (s))
127+ n++;
128+
129+ /* we use x as temporary storage */
130+ x = s + 1;
131+
132+ for (; n >= 2; n--)
133+ {
134+ s = str;
135+ t = skip (s);
136+
137+ for (m = n; m >= 2; m--)
138+ {
139+ if (grub_strcmp (s, t) > 0)
140+ {
141+ int ls = skip (s) - s;
142+ int lt = skip (t) - t;
143+
144+ memcpy (x, s, ls);
145+ grub_memmove (s + ls, s + lt, t - (s + ls));
146+ memcpy (s, t, lt);
147+ t = t + lt - ls;
148+ memcpy (t, x, ls);
149+ }
150+ s = t;
151+ t = skip (t);
152+ }
153+ }
154+}
155+
156+static int this_config_len (const char *config);
157+static int
158+this_config_len (const char *config)
159+{
160+ const char *c = config;
161+ while (*c)
162+ {
163+ while (*c)
164+ c++;
165+ c++;
166+ }
167+ c++;
168+ return c - config;
169+}
170+
171+static const char * expand_asterisks (const char *str, int *len,
172+ const char *subst);
173+
174+/* Expand all asterisks (*) in a menu entry or commands section with its
175+ substitution. Use a backslash as escape character. */
176+static const char *
177+expand_asterisks (const char *str, int *len, const char *subst)
178+{
179+ static char buffer[1024];
180+ char *b = buffer, escaped = 0;
181+ const char *end = str + *len;
182+
183+ while (str < end)
184+ {
185+ if (*str == '*' && !escaped)
186+ {
187+ if (b - buffer + grub_strlen (subst) > sizeof (buffer))
188+ {
189+ errnum = ERR_FILELENGTH;
190+ return NULL;
191+ }
192+ grub_strcpy (b, subst);
193+ b += grub_strlen (subst);
194+ }
195+ else if (*str == '\\' && !escaped)
196+ escaped = 1;
197+ else
198+ {
199+ escaped = 0;
200+ if (b - buffer + 1 > sizeof (buffer))
201+ {
202+ errnum = ERR_FILELENGTH;
203+ return NULL;
204+ }
205+ *b++ = *str;
206+ }
207+ str++;
208+ }
209+ *len = b - buffer;
210+
211+ return buffer;
212+}
213+
214 /* This is the starting function in C. */
215 void
216 cmain (void)
217@@ -1260,6 +1446,96 @@ cmain (void)
218 init_config ();
219 }
220
221+ auto void expand_wildcard_entries (void);
222+ void expand_wildcard_entries (void)
223+ {
224+ char *config_entry = config_entries;
225+ char *menu_entry = menu_entries;
226+
227+ while (*menu_entry)
228+ {
229+ char *command = config_entry;
230+
231+ do
232+ {
233+ char *c = command;
234+ const char *w = "wildcard";
235+
236+ while (*w && *c == *w)
237+ {
238+ c++;
239+ w++;
240+ }
241+ if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '='))
242+ {
243+ int len;
244+
245+ /* This is a wildcard command. Advance to the argument. */
246+ while (*c == ' ' || *c == '\t' || *c == '=')
247+ c++;
248+
249+ /* Expand wildcard entry. */
250+ w = wildcard (c);
251+ if (w)
252+ inplace_sort (w);
253+
254+ /* Remove the wildcard command from the command section;
255+ it has no meaning beyond the wildcard expansion just
256+ performed. */
257+ len = grub_strlen (command) + 1;
258+ grub_memmove (command, command + len,
259+ config_len - (command - config_entries));
260+ config_len -= len;
261+
262+ while (w && *w)
263+ {
264+ /* Insert expansion before the wildcard entry in the
265+ list of entry names. */
266+ len = grub_strlen (menu_entry) + 1;
267+ const char *x = expand_asterisks (menu_entry, &len, w);
268+ grub_memmove (menu_entry + len, menu_entry,
269+ menu_len - (menu_entry - menu_entries));
270+ memcpy (menu_entry, x, len);
271+ menu_entry += len;
272+ menu_len += len;
273+
274+ /* Insert expansion before the wildcard command section
275+ in the list of command sections. */
276+ len = this_config_len (config_entry);
277+ x = expand_asterisks (config_entry, &len, w);
278+ grub_memmove (config_entry + len, config_entry,
279+ config_len - (config_entry -
280+ config_entries));
281+ memcpy (config_entry, x, len);
282+ config_entry += len;
283+ config_len += len;
284+
285+ num_entries++;
286+ w += grub_strlen (w) + 1;
287+ }
288+
289+ /* Remove the wildcard command section; it has just
290+ been expanded. */
291+ len = grub_strlen (menu_entry) + 1;
292+ grub_memmove (menu_entry, menu_entry + len,
293+ menu_len - (menu_entry - menu_entries));
294+ menu_len -= len;
295+
296+ len = this_config_len(config_entry);
297+ grub_memmove (config_entry, config_entry + len,
298+ config_len - (config_entry - config_entries));
299+ config_len -= len;
300+
301+ num_entries--;
302+ }
303+ command += grub_strlen (command) + 1;
304+ }
305+ while (*command);
306+ menu_entry += grub_strlen (menu_entry) + 1;
307+ config_entry += this_config_len(config_entry);
308+ }
309+ }
310+
311 /* Initialize the environment for restarting Stage 2. */
312 grub_setjmp (restart_env);
313
314@@ -1379,8 +1655,16 @@ cmain (void)
315 config_len = prev_config_len;
316 }
317
318+ if (is_preset)
319+ close_preset_menu ();
320+ else
321+ grub_close ();
322+
323 menu_entries[menu_len++] = 0;
324 config_entries[config_len++] = 0;
325+
326+ expand_wildcard_entries();
327+
328 grub_memmove (config_entries + config_len, menu_entries,
329 menu_len);
330 menu_entries = config_entries + config_len;
331@@ -1395,11 +1679,6 @@ cmain (void)
332 else
333 default_entry = fallback_entry;
334 }
335-
336- if (is_preset)
337- close_preset_menu ();
338- else
339- grub_close ();
340 }
341 while (is_preset);
342 }
343Index: grub-0.95/stage2/builtins.c
344===================================================================
345--- grub-0.95.orig/stage2/builtins.c
346+++ grub-0.95/stage2/builtins.c
347@@ -4831,6 +4831,49 @@ static struct builtin builtin_vbeprobe =
348 };
349
350 \f
351+/* wildcard */
352+ static int
353+wildcard_func (char *arg, int flags)
354+{
355+#ifdef DEBUG_WILDCARD
356+ char *w = wildcard (arg);
357+
358+ if (w)
359+ {
360+ while (*w)
361+ {
362+ grub_printf("%s ", w);
363+ w += strlen (w) + 1;
364+ }
365+ grub_printf("\n");
366+ return 1;
367+ }
368+ else
369+ print_error();
370+#endif
371+
372+ /* This special command is interpreted in the config file parser. */
373+ return 0;
374+}
375+
376+static struct builtin builtin_wildcard =
377+ {
378+ "wildcard",
379+ wildcard_func,
380+#ifndef DEBUG_WILDCARD
381+ BUILTIN_MENU,
382+#else
383+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
384+ "wildcard GLOB",
385+ "Declare this menu entry as a wildcard entry. GLOB is a path containing"
386+ " one asterisk. All files matching this expression are looked up; the"
387+ " menu entry is duplicated for each match with asterisks in other"
388+ " commands replaced by the string matching the asterisk in the wildcard"
389+ " command."
390+#endif
391+};
392+
393+\f
394 /* The table of builtin commands. Sorted in dictionary order. */
395 struct builtin *builtin_table[] =
396 {
397@@ -4920,5 +4963,6 @@ struct builtin *builtin_table[] =
398 &builtin_unhide,
399 &builtin_uppermem,
400 &builtin_vbeprobe,
401+ &builtin_wildcard,
402 0
403 };