]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/grub-0.97/grub-0.97-wildcards.patch
HinzugefĆ¼gt:
[ipfire-2.x.git] / src / patches / grub-0.97 / grub-0.97-wildcards.patch
1 diff -Nur grub-0.97-dirs/docs/grub.texi grub-0.97-wildcards/docs/grub.texi
2 --- grub-0.97-dirs/docs/grub.texi 2005-08-21 20:31:12.000000000 +0300
3 +++ grub-0.97-wildcards/docs/grub.texi 2005-08-21 20:32:45.000000000 +0300
4 @@ -2121,6 +2121,7 @@
5 * gfxmenu:: Use graphical menu interface
6 * timeout:: Set the timeout
7 * title:: Start a menu entry
8 +* wildcard:: Define a wildcard boot entry
9 @end menu
10
11
12 @@ -2190,6 +2191,42 @@
13 @end deffn
14
15
16 +@node wildcard
17 +@subsection wildcard
18 +
19 +@deffn Command wildcard pathname
20 +Treat this boot entry as a wildcard entry: The
21 +wildcard, title, kernel, and initrd commands (see @ref{Menu-specific
22 +commands} and @ref{Command-line and menu entry commands}) each have an
23 +asterisk (*) in their value. A filename match is performed on the
24 +@var{pathname} of the wildcard command. For each match, the entire boot
25 +entry is duplicated. The part of the filename whcih matches the asterisk
26 +in the wildcard command replaces the asterisks in the title, kernel, and
27 +initrd commands. For example, with the files vmlinuz-2.6.5-1 and
28 +vmlinuz-2.6.8-8 below (hd0,7)/boot, the following entry in the stage 2
29 +configuration file:
30 +
31 +@example
32 +title Linux-*
33 + wildcard (hd0,7)/boot/vmlinuz-*
34 + kernel (hd0,7)/boot/vmlinuz-* root=/dev/hda8
35 + initrd (hd0,7)/boot/initrd-*
36 +@end example
37 +
38 +would expand as follows:
39 +
40 +@example
41 +title Linux-2.6.5-1
42 + wildcard (hd0,7)/boot/vmlinuz-2.6.5-1
43 + kernel (hd0,7)/boot/vmlinuz-2.6.5-1 root=/dev/hda8
44 + initrd (hd0,7)/boot/initrd-2.6.5-1
45 +title Linux-2.6.8-8
46 + wildcard (hd0,7)/boot/vmlinuz-2.6.8-8
47 + kernel (hd0,7)/boot/vmlinuz-2.6.8-8 root=/dev/hda8
48 + initrd (hd0,7)/boot/initrd-2.6.8-8
49 +@end example
50 +@end deffn
51 +
52 @node General commands
53 @section The list of general commands
54
55 diff -Nur grub-0.97-dirs/netboot/fsys_tftp.c grub-0.97-wildcards/netboot/fsys_tftp.c
56 --- grub-0.97-dirs/netboot/fsys_tftp.c 2005-08-21 20:31:02.000000000 +0300
57 +++ grub-0.97-wildcards/netboot/fsys_tftp.c 2005-08-21 20:32:45.000000000 +0300
58 @@ -409,7 +409,7 @@
59 /* Check if the file DIRNAME really exists. Get the size and save it in
60 FILEMAX. */
61 int
62 -tftp_dir (char *dirname)
63 +tftp_dir (char *dirname, void (*handle)(char *))
64 {
65 int ch;
66
67 @@ -418,7 +418,7 @@
68 #endif
69
70 /* In TFTP, there is no way to know what files exist. */
71 - if (print_possibilities)
72 + if (handle)
73 return 1;
74
75 /* Don't know the size yet. */
76 diff -Nur grub-0.97-dirs/stage2/builtins.c grub-0.97-wildcards/stage2/builtins.c
77 --- grub-0.97-dirs/stage2/builtins.c 2005-08-21 20:31:02.000000000 +0300
78 +++ grub-0.97-wildcards/stage2/builtins.c 2005-08-21 20:32:45.000000000 +0300
79 @@ -4828,6 +4828,49 @@
80 };
81
82 \f
83 +/* wildcard */
84 + static int
85 +wildcard_func (char *arg, int flags)
86 +{
87 +#ifdef DEBUG_WILDCARD
88 + char *w = wildcard (arg);
89 +
90 + if (w)
91 + {
92 + while (*w)
93 + {
94 + grub_printf("%s ", w);
95 + w += strlen (w) + 1;
96 + }
97 + grub_printf("\n");
98 + return 1;
99 + }
100 + else
101 + print_error();
102 +#endif
103 +
104 + /* This special command is interpreted in the config file parser. */
105 + return 0;
106 +}
107 +
108 +static struct builtin builtin_wildcard =
109 + {
110 + "wildcard",
111 + wildcard_func,
112 +#ifndef DEBUG_WILDCARD
113 + BUILTIN_MENU,
114 +#else
115 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
116 + "wildcard GLOB",
117 + "Declare this menu entry as a wildcard entry. GLOB is a path containing"
118 + " one asterisk. All files matching this expression are looked up; the"
119 + " menu entry is duplicated for each match with asterisks in other"
120 + " commands replaced by the string matching the asterisk in the wildcard"
121 + " command."
122 +#endif
123 +};
124 +
125 +\f
126 /* The table of builtin commands. Sorted in dictionary order. */
127 struct builtin *builtin_table[] =
128 {
129 @@ -4917,5 +4960,6 @@
130 &builtin_unhide,
131 &builtin_uppermem,
132 &builtin_vbeprobe,
133 + &builtin_wildcard,
134 0
135 };
136 diff -Nur grub-0.97-dirs/stage2/disk_io.c grub-0.97-wildcards/stage2/disk_io.c
137 --- grub-0.97-dirs/stage2/disk_io.c 2005-08-21 20:31:02.000000000 +0300
138 +++ grub-0.97-wildcards/stage2/disk_io.c 2005-08-21 20:32:45.000000000 +0300
139 @@ -36,7 +36,6 @@
140 void (*disk_read_func) (int, int, int) = NULL;
141
142 #ifndef STAGE1_5
143 -int print_possibilities;
144
145 static int do_completion;
146 static int unique;
147 @@ -1479,7 +1478,7 @@
148 if (! is_completion)
149 grub_printf (" Possible files are:");
150
151 - dir (buf);
152 + dir (buf, print_a_completion);
153
154 if (is_completion && *unique_string)
155 {
156 @@ -1498,7 +1497,7 @@
157 *ptr = '/';
158 *(ptr + 1) = 0;
159
160 - dir (buf);
161 + dir (buf, print_a_completion);
162
163 /* Restore the original unique value. */
164 unique = 1;
165 @@ -1626,12 +1625,7 @@
166 if (!errnum && fsys_type == NUM_FSYS)
167 errnum = ERR_FSYS_MOUNT;
168
169 -# ifndef STAGE1_5
170 - /* set "dir" function to open a file */
171 - print_possibilities = 0;
172 -# endif
173 -
174 - if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename))
175 + if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename, NULL))
176 {
177 #ifndef NO_DECOMPRESSION
178 return gunzip_test_header ();
179 @@ -1752,7 +1746,7 @@
180 }
181
182 int
183 -dir (char *dirname)
184 +dir (char *dirname, void (*handle)(char *))
185 {
186 #ifndef NO_DECOMPRESSION
187 compressed_file = 0;
188 @@ -1761,19 +1755,18 @@
189 if (!(dirname = setup_part (dirname)))
190 return 0;
191
192 + errnum = 0;
193 if (*dirname != '/')
194 errnum = ERR_BAD_FILENAME;
195 -
196 - if (fsys_type == NUM_FSYS)
197 + else if (fsys_type == NUM_FSYS)
198 errnum = ERR_FSYS_MOUNT;
199 -
200 - if (errnum)
201 - return 0;
202 -
203 - /* set "dir" function to list completions */
204 - print_possibilities = 1;
205 -
206 - return (*(fsys_table[fsys_type].dir_func)) (dirname);
207 + else
208 + {
209 + fsys_table[fsys_type].dir_func (dirname, handle);
210 + if (errnum == ERR_FILE_NOT_FOUND)
211 + errnum = 0;
212 + }
213 + return errnum == 0;
214 }
215 #endif /* STAGE1_5 */
216
217 diff -Nur grub-0.97-dirs/stage2/filesys.h grub-0.97-wildcards/stage2/filesys.h
218 --- grub-0.97-dirs/stage2/filesys.h 2005-08-21 20:31:02.000000000 +0300
219 +++ grub-0.97-wildcards/stage2/filesys.h 2005-08-21 20:32:45.000000000 +0300
220 @@ -24,7 +24,7 @@
221 #define FSYS_FFS_NUM 1
222 int ffs_mount (void);
223 int ffs_read (char *buf, int len);
224 -int ffs_dir (char *dirname);
225 +int ffs_dir (char *dirname, void (*handle)(char *));
226 int ffs_embed (int *start_sector, int needed_sectors);
227 #else
228 #define FSYS_FFS_NUM 0
229 @@ -34,7 +34,7 @@
230 #define FSYS_UFS2_NUM 1
231 int ufs2_mount (void);
232 int ufs2_read (char *buf, int len);
233 -int ufs2_dir (char *dirname);
234 +int ufs2_dir (char *dirname, void (*handle)(char *));
235 int ufs2_embed (int *start_sector, int needed_sectors);
236 #else
237 #define FSYS_UFS2_NUM 0
238 @@ -44,7 +44,7 @@
239 #define FSYS_FAT_NUM 1
240 int fat_mount (void);
241 int fat_read (char *buf, int len);
242 -int fat_dir (char *dirname);
243 +int fat_dir (char *dirname, void (*handle)(char *));
244 #else
245 #define FSYS_FAT_NUM 0
246 #endif
247 @@ -53,7 +53,7 @@
248 #define FSYS_EXT2FS_NUM 1
249 int ext2fs_mount (void);
250 int ext2fs_read (char *buf, int len);
251 -int ext2fs_dir (char *dirname);
252 +int ext2fs_dir (char *dirname, void (*handle)(char *));
253 #else
254 #define FSYS_EXT2FS_NUM 0
255 #endif
256 @@ -62,7 +62,7 @@
257 #define FSYS_MINIX_NUM 1
258 int minix_mount (void);
259 int minix_read (char *buf, int len);
260 -int minix_dir (char *dirname);
261 +int minix_dir (char *dirname, void (*handle)(char *));
262 #else
263 #define FSYS_MINIX_NUM 0
264 #endif
265 @@ -71,7 +71,7 @@
266 #define FSYS_REISERFS_NUM 1
267 int reiserfs_mount (void);
268 int reiserfs_read (char *buf, int len);
269 -int reiserfs_dir (char *dirname);
270 +int reiserfs_dir (char *dirname, void (*handle)(char *));
271 int reiserfs_embed (int *start_sector, int needed_sectors);
272 #if defined(__linux__) && defined (GRUB_UTIL)
273 #include <sys/types.h>
274 @@ -91,7 +91,7 @@
275 #define FSYS_VSTAFS_NUM 1
276 int vstafs_mount (void);
277 int vstafs_read (char *buf, int len);
278 -int vstafs_dir (char *dirname);
279 +int vstafs_dir (char *dirname, void (*handle)(char *));
280 #else
281 #define FSYS_VSTAFS_NUM 0
282 #endif
283 @@ -100,7 +100,7 @@
284 #define FSYS_JFS_NUM 1
285 int jfs_mount (void);
286 int jfs_read (char *buf, int len);
287 -int jfs_dir (char *dirname);
288 +int jfs_dir (char *dirname, void (*handle)(char *));
289 int jfs_embed (int *start_sector, int needed_sectors);
290 #else
291 #define FSYS_JFS_NUM 0
292 @@ -110,7 +110,7 @@
293 #define FSYS_XFS_NUM 1
294 int xfs_mount (void);
295 int xfs_read (char *buf, int len);
296 -int xfs_dir (char *dirname);
297 +int xfs_dir (char *dirname, void (*handle)(char *));
298 #else
299 #define FSYS_XFS_NUM 0
300 #endif
301 @@ -119,7 +119,7 @@
302 #define FSYS_TFTP_NUM 1
303 int tftp_mount (void);
304 int tftp_read (char *buf, int len);
305 -int tftp_dir (char *dirname);
306 +int tftp_dir (char *dirname, void (*handle)(char *));
307 void tftp_close (void);
308 #else
309 #define FSYS_TFTP_NUM 0
310 @@ -129,7 +129,7 @@
311 #define FSYS_ISO9660_NUM 1
312 int iso9660_mount (void);
313 int iso9660_read (char *buf, int len);
314 -int iso9660_dir (char *dirname);
315 +int iso9660_dir (char *dirname, void (*handle)(char *));
316 #else
317 #define FSYS_ISO9660_NUM 0
318 #endif
319 @@ -160,16 +160,10 @@
320 char *name;
321 int (*mount_func) (void);
322 int (*read_func) (char *buf, int len);
323 - int (*dir_func) (char *dirname);
324 + int (*dir_func) (char *dirname, void (*print_one)(char *));
325 void (*close_func) (void);
326 int (*embed_func) (int *start_sector, int needed_sectors);
327 };
328
329 -#ifdef STAGE1_5
330 -# define print_possibilities 0
331 -#else
332 -extern int print_possibilities;
333 -#endif
334 -
335 extern int fsmax;
336 extern struct fsys_entry fsys_table[NUM_FSYS + 1];
337 diff -Nur grub-0.97-dirs/stage2/fsys_ext2fs.c grub-0.97-wildcards/stage2/fsys_ext2fs.c
338 --- grub-0.97-dirs/stage2/fsys_ext2fs.c 2005-08-21 20:31:02.000000000 +0300
339 +++ grub-0.97-wildcards/stage2/fsys_ext2fs.c 2005-08-21 20:32:45.000000000 +0300
340 @@ -495,7 +495,7 @@
341 * side effects: messes up GROUP_DESC buffer area
342 */
343 int
344 -ext2fs_dir (char *dirname)
345 +ext2fs_dir (char *dirname, void (*handle)(char *))
346 {
347 int current_ino = EXT2_ROOT_INO; /* start at the root */
348 int updir_ino = current_ino; /* the parent of the current directory */
349 @@ -521,7 +521,6 @@
350 #ifdef E2DEBUG
351 unsigned char *i;
352 #endif /* E2DEBUG */
353 -
354 /* loop invariants:
355 current_ino = inode to lookup
356 dirname = pointer to filename component we are cur looking up within
357 @@ -713,18 +712,9 @@
358 give up */
359 if (loc >= INODE->i_size)
360 {
361 - if (print_possibilities < 0)
362 - {
363 -# if 0
364 - putchar ('\n');
365 -# endif
366 - }
367 - else
368 - {
369 - errnum = ERR_FILE_NOT_FOUND;
370 - *rest = ch;
371 - }
372 - return (print_possibilities < 0);
373 + errnum = ERR_FILE_NOT_FOUND;
374 + *rest = ch;
375 + return 0;
376 }
377
378 /* else, find the (logical) block component of our location */
379 @@ -765,20 +755,15 @@
380 str_chk = substring (dirname, dp->name);
381
382 # ifndef STAGE1_5
383 - if (print_possibilities && ch != '/'
384 - && (!*dirname || str_chk <= 0))
385 - {
386 - if (print_possibilities > 0)
387 - print_possibilities = -print_possibilities;
388 - print_a_completion (dp->name);
389 - }
390 + if (handle && ch != '/' && (!*dirname || str_chk <= 0))
391 + handle (dp->name);
392 # endif
393
394 dp->name[dp->name_len] = saved_c;
395 }
396
397 }
398 - while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
399 + while (!dp->inode || (str_chk || (handle && ch != '/')));
400
401 current_ino = dp->inode;
402 *(dirname = rest) = ch;
403 diff -Nur grub-0.97-dirs/stage2/fsys_fat.c grub-0.97-wildcards/stage2/fsys_fat.c
404 --- grub-0.97-dirs/stage2/fsys_fat.c 2005-08-21 20:31:02.000000000 +0300
405 +++ grub-0.97-wildcards/stage2/fsys_fat.c 2005-08-21 20:32:45.000000000 +0300
406 @@ -289,7 +289,7 @@
407 }
408
409 int
410 -fat_dir (char *dirname)
411 +fat_dir (char *dirname, void (*handle)(char *))
412 {
413 char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH];
414 char *filename = (char *) NAME_BUF;
415 @@ -345,7 +345,7 @@
416 *rest = 0;
417
418 # ifndef STAGE1_5
419 - if (print_possibilities && ch != '/')
420 + if (handle && ch != '/')
421 do_possibilities = 1;
422 # endif
423
424 @@ -356,16 +356,6 @@
425 {
426 if (!errnum)
427 {
428 -# ifndef STAGE1_5
429 - if (print_possibilities < 0)
430 - {
431 -#if 0
432 - putchar ('\n');
433 -#endif
434 - return 1;
435 - }
436 -# endif /* STAGE1_5 */
437 -
438 errnum = ERR_FILE_NOT_FOUND;
439 *rest = ch;
440 }
441 @@ -460,11 +450,7 @@
442 {
443 print_filename:
444 if (substring (dirname, filename) <= 0)
445 - {
446 - if (print_possibilities > 0)
447 - print_possibilities = -print_possibilities;
448 - print_a_completion (filename);
449 - }
450 + handle (filename);
451 continue;
452 }
453 # endif /* STAGE1_5 */
454 diff -Nur grub-0.97-dirs/stage2/fsys_ffs.c grub-0.97-wildcards/stage2/fsys_ffs.c
455 --- grub-0.97-dirs/stage2/fsys_ffs.c 2005-08-21 20:31:02.000000000 +0300
456 +++ grub-0.97-wildcards/stage2/fsys_ffs.c 2005-08-21 20:32:45.000000000 +0300
457 @@ -180,7 +180,7 @@
458
459
460 int
461 -ffs_dir (char *dirname)
462 +ffs_dir (char *dirname, void (*handle)(char *))
463 {
464 char *rest, ch;
465 int block, off, loc, map, ino = ROOTINO;
466 @@ -236,13 +236,6 @@
467 {
468 if (loc >= INODE->i_size)
469 {
470 -#if 0
471 - putchar ('\n');
472 -#endif
473 -
474 - if (print_possibilities < 0)
475 - return 1;
476 -
477 errnum = ERR_FILE_NOT_FOUND;
478 *rest = ch;
479 return 0;
480 @@ -267,18 +260,13 @@
481 loc += dp->d_reclen;
482
483 #ifndef STAGE1_5
484 - if (dp->d_ino && print_possibilities && ch != '/'
485 + if (dp->d_ino && handle && ch != '/'
486 && (!*dirname || substring (dirname, dp->d_name) <= 0))
487 - {
488 - if (print_possibilities > 0)
489 - print_possibilities = -print_possibilities;
490 -
491 - print_a_completion (dp->d_name);
492 - }
493 + handle (dp->d_name);
494 #endif /* STAGE1_5 */
495 }
496 while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
497 - || (print_possibilities && ch != '/')));
498 + || (handle && ch != '/')));
499
500 /* only get here if we have a matching directory entry */
501
502 diff -Nur grub-0.97-dirs/stage2/fsys_iso9660.c grub-0.97-wildcards/stage2/fsys_iso9660.c
503 --- grub-0.97-dirs/stage2/fsys_iso9660.c 2005-08-21 20:31:02.000000000 +0300
504 +++ grub-0.97-wildcards/stage2/fsys_iso9660.c 2005-08-21 20:32:45.000000000 +0300
505 @@ -133,7 +133,7 @@
506 }
507
508 int
509 -iso9660_dir (char *dirname)
510 +iso9660_dir (char *dirname, void (*handle)(char *))
511 {
512 struct iso_directory_record *idr;
513 RR_ptr_t rr_ptr;
514 @@ -346,7 +346,7 @@
515 if (name_len >= pathlen
516 && !memcmp(name, dirname, pathlen))
517 {
518 - if (dirname[pathlen] == '/' || !print_possibilities)
519 + if (dirname[pathlen] == '/' || !handle)
520 {
521 /*
522 * DIRNAME is directory component of pathname,
523 @@ -377,11 +377,9 @@
524 else /* Completion */
525 {
526 #ifndef STAGE1_5
527 - if (print_possibilities > 0)
528 - print_possibilities = -print_possibilities;
529 memcpy(NAME_BUF, name, name_len);
530 NAME_BUF[name_len] = '\0';
531 - print_a_completion (NAME_BUF);
532 + handle (NAME_BUF);
533 #endif
534 }
535 }
536 @@ -390,7 +388,7 @@
537 size -= ISO_SECTOR_SIZE;
538 } /* size>0 */
539
540 - if (dirname[pathlen] == '/' || print_possibilities >= 0)
541 + if (dirname[pathlen] == '/' || handle)
542 {
543 errnum = ERR_FILE_NOT_FOUND;
544 return 0;
545 diff -Nur grub-0.97-dirs/stage2/fsys_jfs.c grub-0.97-wildcards/stage2/fsys_jfs.c
546 --- grub-0.97-dirs/stage2/fsys_jfs.c 2005-08-21 20:31:02.000000000 +0300
547 +++ grub-0.97-wildcards/stage2/fsys_jfs.c 2005-08-21 20:32:45.000000000 +0300
548 @@ -270,7 +270,7 @@
549 }
550
551 int
552 -jfs_dir (char *dirname)
553 +jfs_dir (char *dirname, void (*handle)(char *))
554 {
555 char *ptr, *rest, ch;
556 ldtentry_t *de;
557 @@ -357,12 +357,9 @@
558
559 cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
560 #ifndef STAGE1_5
561 - if (print_possibilities && ch != '/'
562 - && cmp <= 0) {
563 - if (print_possibilities > 0)
564 - print_possibilities = -print_possibilities;
565 - print_a_completion (namebuf);
566 - } else
567 + if (handle && ch != '/' && cmp <= 0)
568 + handle (namebuf);
569 + else
570 #endif
571 if (cmp == 0) {
572 parent_inum = inum;
573 @@ -372,9 +369,6 @@
574 }
575 de = next_dentry ();
576 if (de == NULL) {
577 - if (print_possibilities < 0)
578 - return 1;
579 -
580 errnum = ERR_FILE_NOT_FOUND;
581 *rest = ch;
582 return 0;
583 diff -Nur grub-0.97-dirs/stage2/fsys_minix.c grub-0.97-wildcards/stage2/fsys_minix.c
584 --- grub-0.97-dirs/stage2/fsys_minix.c 2005-08-21 20:31:02.000000000 +0300
585 +++ grub-0.97-wildcards/stage2/fsys_minix.c 2005-08-21 20:32:45.000000000 +0300
586 @@ -294,7 +294,7 @@
587 inode of the file we were trying to look up
588 side effects: none yet */
589 int
590 -minix_dir (char *dirname)
591 +minix_dir (char *dirname, void (*handle)(char *))
592 {
593 int current_ino = MINIX_ROOT_INO; /* start at the root */
594 int updir_ino = current_ino; /* the parent of the current directory */
595 @@ -457,18 +457,9 @@
596 give up */
597 if (loc >= INODE->i_size)
598 {
599 - if (print_possibilities < 0)
600 - {
601 -#if 0
602 - putchar ('\n');
603 -#endif
604 - }
605 - else
606 - {
607 - errnum = ERR_FILE_NOT_FOUND;
608 - *rest = ch;
609 - }
610 - return (print_possibilities < 0);
611 + errnum = ERR_FILE_NOT_FOUND;
612 + *rest = ch;
613 + return 0;
614 }
615
616 /* else, find the (logical) block component of our location */
617 @@ -510,20 +501,15 @@
618 str_chk = substring (dirname, dp->name);
619
620 # ifndef STAGE1_5
621 - if (print_possibilities && ch != '/'
622 - && (!*dirname || str_chk <= 0))
623 - {
624 - if (print_possibilities > 0)
625 - print_possibilities = -print_possibilities;
626 - print_a_completion (dp->name);
627 - }
628 + if (handle && ch != '/' && (!*dirname || str_chk <= 0))
629 + handle (dp->name);
630 # endif
631
632 dp->name[namelen] = saved_c;
633 }
634
635 }
636 - while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
637 + while (!dp->inode || (str_chk || (handle && ch != '/')));
638
639 current_ino = dp->inode;
640 *(dirname = rest) = ch;
641 diff -Nur grub-0.97-dirs/stage2/fsys_reiserfs.c grub-0.97-wildcards/stage2/fsys_reiserfs.c
642 --- grub-0.97-dirs/stage2/fsys_reiserfs.c 2005-08-21 20:31:02.000000000 +0300
643 +++ grub-0.97-wildcards/stage2/fsys_reiserfs.c 2005-08-21 20:32:45.000000000 +0300
644 @@ -991,7 +991,7 @@
645 * the size of the file.
646 */
647 int
648 -reiserfs_dir (char *dirname)
649 +reiserfs_dir (char *dirname, void (*handle)(char *))
650 {
651 struct reiserfs_de_head *de_head;
652 char *rest, ch;
653 @@ -1123,7 +1123,7 @@
654 *rest = 0;
655
656 # ifndef STAGE1_5
657 - if (print_possibilities && ch != '/')
658 + if (handle && ch != '/')
659 do_possibilities = 1;
660 # endif /* ! STAGE1_5 */
661
662 @@ -1170,10 +1170,8 @@
663 {
664 if (cmp <= 0)
665 {
666 - if (print_possibilities > 0)
667 - print_possibilities = -print_possibilities;
668 *name_end = 0;
669 - print_a_completion (filename);
670 + handle (filename);
671 *name_end = tmp;
672 }
673 }
674 @@ -1189,12 +1187,6 @@
675 num_entries--;
676 }
677 }
678 -
679 -# ifndef STAGE1_5
680 - if (print_possibilities < 0)
681 - return 1;
682 -# endif /* ! STAGE1_5 */
683 -
684 errnum = ERR_FILE_NOT_FOUND;
685 *rest = ch;
686 return 0;
687 diff -Nur grub-0.97-dirs/stage2/fsys_ufs2.c grub-0.97-wildcards/stage2/fsys_ufs2.c
688 --- grub-0.97-dirs/stage2/fsys_ufs2.c 2005-08-21 20:31:02.000000000 +0300
689 +++ grub-0.97-wildcards/stage2/fsys_ufs2.c 2005-08-21 20:32:45.000000000 +0300
690 @@ -204,7 +204,7 @@
691 }
692
693 int
694 -ufs2_dir (char *dirname)
695 +ufs2_dir (char *dirname, void (*handle)(char *))
696 {
697 char *rest, ch;
698 int block, off, loc, ino = ROOTINO;
699 @@ -261,9 +261,6 @@
700 {
701 if (loc >= INODE_UFS2->di_size)
702 {
703 - if (print_possibilities < 0)
704 - return 1;
705 -
706 errnum = ERR_FILE_NOT_FOUND;
707 *rest = ch;
708 return 0;
709 @@ -288,18 +285,13 @@
710 loc += dp->d_reclen;
711
712 #ifndef STAGE1_5
713 - if (dp->d_ino && print_possibilities && ch != '/'
714 + if (dp->d_ino && handle && ch != '/'
715 && (!*dirname || substring (dirname, dp->d_name) <= 0))
716 - {
717 - if (print_possibilities > 0)
718 - print_possibilities = -print_possibilities;
719 -
720 - print_a_completion (dp->d_name);
721 - }
722 + handle (dp->d_name);
723 #endif /* STAGE1_5 */
724 }
725 while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
726 - || (print_possibilities && ch != '/')));
727 + || (handle && ch != '/')));
728
729 /* only get here if we have a matching directory entry */
730
731 diff -Nur grub-0.97-dirs/stage2/fsys_vstafs.c grub-0.97-wildcards/stage2/fsys_vstafs.c
732 --- grub-0.97-dirs/stage2/fsys_vstafs.c 2005-08-21 20:31:02.000000000 +0300
733 +++ grub-0.97-wildcards/stage2/fsys_vstafs.c 2005-08-21 20:32:45.000000000 +0300
734 @@ -115,7 +115,7 @@
735 }
736
737 int
738 -vstafs_dir (char *dirname)
739 +vstafs_dir (char *dirname, void (*handle)(char *))
740 {
741 char *fn, ch;
742 struct dir_entry *d;
743 @@ -146,14 +146,9 @@
744 continue;
745
746 #ifndef STAGE1_5
747 - if (print_possibilities && ch != '/'
748 + if (handle && ch != '/'
749 && (! *dirname || strcmp (dirname, d->name) <= 0))
750 - {
751 - if (print_possibilities > 0)
752 - print_possibilities = -print_possibilities;
753 -
754 - printf (" %s", d->name);
755 - }
756 + handle(d->name);
757 #endif
758 if (! grub_strcmp (dirname, d->name))
759 {
760 @@ -168,12 +163,6 @@
761 *(dirname = fn) = ch;
762 if (! d)
763 {
764 - if (print_possibilities < 0)
765 - {
766 - putchar ('\n');
767 - return 1;
768 - }
769 -
770 errnum = ERR_FILE_NOT_FOUND;
771 return 0;
772 }
773 diff -Nur grub-0.97-dirs/stage2/fsys_xfs.c grub-0.97-wildcards/stage2/fsys_xfs.c
774 --- grub-0.97-dirs/stage2/fsys_xfs.c 2005-08-21 20:31:02.000000000 +0300
775 +++ grub-0.97-wildcards/stage2/fsys_xfs.c 2005-08-21 20:32:45.000000000 +0300
776 @@ -534,7 +534,7 @@
777 }
778
779 int
780 -xfs_dir (char *dirname)
781 +xfs_dir (char *dirname, void (*handle)(char *))
782 {
783 xfs_ino_t ino, parent_ino, new_ino;
784 xfs_fsize_t di_size;
785 @@ -595,11 +595,9 @@
786 for (;;) {
787 cmp = (!*dirname) ? -1 : substring (dirname, name);
788 #ifndef STAGE1_5
789 - if (print_possibilities && ch != '/' && cmp <= 0) {
790 - if (print_possibilities > 0)
791 - print_possibilities = -print_possibilities;
792 - print_a_completion (name);
793 - } else
794 + if (handle && ch != '/' && cmp <= 0)
795 + handle (name);
796 + else
797 #endif
798 if (cmp == 0) {
799 parent_ino = ino;
800 @@ -610,9 +608,6 @@
801 }
802 name = next_dentry (&new_ino);
803 if (name == NULL) {
804 - if (print_possibilities < 0)
805 - return 1;
806 -
807 errnum = ERR_FILE_NOT_FOUND;
808 *rest = ch;
809 return 0;
810 diff -Nur grub-0.97-dirs/stage2/shared.h grub-0.97-wildcards/stage2/shared.h
811 --- grub-0.97-dirs/stage2/shared.h 2005-08-21 20:31:02.000000000 +0300
812 +++ grub-0.97-wildcards/stage2/shared.h 2005-08-21 20:32:45.000000000 +0300
813 @@ -1012,9 +1012,11 @@
814 /* Close a file. */
815 void grub_close (void);
816
817 -/* List the contents of the directory that was opened with GRUB_OPEN,
818 - printing all completions. */
819 -int dir (char *dirname);
820 +/* List the contents of DIRECTORY. */
821 +int dir (char *dirname, void (*handle)(char *));
822 +
823 +/* Wildcard expand the last pathname component of GLOB. */
824 +char *wildcard (char *glob, int *len);
825
826 int set_bootdev (int hdbias);
827
828 diff -Nur grub-0.97-dirs/stage2/stage2.c grub-0.97-wildcards/stage2/stage2.c
829 --- grub-0.97-dirs/stage2/stage2.c 2005-08-21 20:31:02.000000000 +0300
830 +++ grub-0.97-wildcards/stage2/stage2.c 2005-08-21 20:33:24.000000000 +0300
831 @@ -1243,6 +1243,230 @@
832 }
833
834
835 +char *wildcard_prefix, *wildcard_suffix;
836 +char wildcard_matches[1024], *end_wildcard_matches;
837 +
838 +static void wildcard_handler(char *name);
839 +
840 +/* Match one directory entry against the current wildcard. If the entry
841 + matches, store it in WILDCARD_MATCHES. Silently ignore entries that
842 + don't fit into WILDCARD_MATCHES anymore. */
843 +static void
844 +wildcard_handler(char *name)
845 +{
846 + char *n = name, *p = wildcard_prefix;
847 +
848 + while (*p && *p == *n)
849 + {
850 + p++;
851 + n++;
852 + }
853 + if (*p)
854 + return; /* prefix mismatch */
855 +
856 + p = name + grub_strlen (name) - grub_strlen (wildcard_suffix);
857 + /* [n .. p) is the part matching the asterisk */
858 +
859 + if (p < n || grub_strcmp (p, wildcard_suffix) != 0)
860 + return; /* suffix mismatch */
861 +
862 + /* store this match */
863 + if (p - n + 1 > sizeof (wildcard_matches) -
864 + (end_wildcard_matches - wildcard_matches))
865 + return; /* out of space */
866 + while (n < p)
867 + *end_wildcard_matches++ = *n++;
868 + *end_wildcard_matches++ = 0;
869 +}
870 +
871 +/* Wildcard expand the GLOB argument. Return NULL upon failure, or
872 + a list of 0-terminated expansions, terminated by a zero-length string. */
873 +char *
874 +wildcard (char *glob, int *len)
875 +{
876 + char path[128], *p;
877 + int ret;
878 +
879 + end_wildcard_matches = wildcard_matches;
880 + if (grub_strlen (glob) + 1 > sizeof (path)) {
881 + errnum = ERR_FILELENGTH;
882 + return NULL; /* cannot handle pathnames this long */
883 + }
884 + grub_strcpy (path, glob);
885 + p = path;
886 + while (*p)
887 + p++;
888 + wildcard_suffix = p;
889 + while (p > path && *p != '/')
890 + p--;
891 + if (*p != '/')
892 + {
893 + errnum = ERR_BAD_FILETYPE;
894 + return NULL; /* Cannot wildcard device names */
895 + }
896 + *(++p) = 0;
897 + wildcard_prefix = glob + (p - path);
898 + for (p = wildcard_prefix;; p++)
899 + {
900 + if (*p == 0)
901 + {
902 + /* We cannot do exact matches: this cannot be represented in the
903 + result list. */
904 + return NULL;
905 + }
906 + else if (*p == '*')
907 + {
908 + *p++ = 0;
909 + wildcard_suffix = p;
910 + break;
911 + }
912 + }
913 +
914 + ret = dir (path, wildcard_handler);
915 + /* restore original argument */
916 + wildcard_prefix[grub_strlen (wildcard_prefix)] = '*';
917 + if (!ret)
918 + return NULL;
919 + *len = end_wildcard_matches - wildcard_matches;
920 + return wildcard_matches;
921 +}
922 +
923 +static int inplace_sort_nextint(char **p);
924 +
925 +static int inplace_sort_nextint(char **p)
926 +{
927 + int i = 0;
928 +
929 + while (**p && **p < '0' && **p > '9') *p++;
930 + if (!**p) return -1;
931 + while (**p && **p >= '0' && **p <= '9')
932 + {
933 + i = i * 10 + **p - '0';
934 + *p++;
935 + }
936 + return i;
937 +}
938 +
939 +static int inplace_sort_strcmp(char *l, char *r);
940 +
941 +static int
942 +inplace_sort_strcmp(char *l, char *r)
943 +{
944 + char *lp = l;
945 + char *rp = r;
946 + int li, ri;
947 +
948 + do
949 + {
950 + li = inplace_sort_nextint(&lp);
951 + ri = inplace_sort_nextint(&rp);
952 + if (li > ri) return 1;
953 + if (ri > li) return -1;
954 + }
955 + while (li != -1 || ri != -1);
956 + return 0;
957 +}
958 +
959 +#define skip(str) ((str) + grub_strlen (str) + 1)
960 +
961 +static void inplace_sort (char *str, int len);
962 +
963 +static void
964 +inplace_sort (char *str, int len)
965 +{
966 + int m, n = 0;
967 + char *s, *t;
968 +
969 + /* we use x as temporary storage */
970 + char *x = str + len;
971 +
972 + for (s = str; s < x; s = skip (s))
973 + n++;
974 +
975 + for (; n >= 2; n--)
976 + {
977 + s = str;
978 + t = skip (s);
979 +
980 + for (m = n; m >= 2; m--)
981 + {
982 + if (inplace_sort_strcmp (s, t) < 0)
983 + {
984 + int ls = skip (s) - s;
985 + int lt = skip (t) - t;
986 +
987 + memcpy (x, s, ls);
988 + grub_memmove (s + ls, s + lt, t - (s + ls));
989 + memcpy (s, t, lt);
990 + t = t + lt - ls;
991 + memcpy (t, x, ls);
992 + }
993 + s = t;
994 + t = skip (t);
995 + }
996 + }
997 +}
998 +
999 +#undef skip
1000 +
1001 +static int this_config_len (const char *config);
1002 +static int
1003 +this_config_len (const char *config)
1004 +{
1005 + const char *c = config;
1006 + while (*c)
1007 + {
1008 + while (*c)
1009 + c++;
1010 + c++;
1011 + }
1012 + c++;
1013 + return c - config;
1014 +}
1015 +
1016 +static const char * expand_asterisks (const char *str, int *len,
1017 + const char *subst);
1018 +
1019 +/* Expand all asterisks (*) in a menu entry or commands section with its
1020 + substitution. Use a backslash as escape character. */
1021 +static const char *
1022 +expand_asterisks (const char *str, int *len, const char *subst)
1023 +{
1024 + static char buffer[1024];
1025 + char *b = buffer, escaped = 0;
1026 + const char *end = str + *len;
1027 +
1028 + while (str < end)
1029 + {
1030 + if (*str == '*' && !escaped)
1031 + {
1032 + if (b - buffer + grub_strlen (subst) > sizeof (buffer))
1033 + {
1034 + errnum = ERR_FILELENGTH;
1035 + return NULL;
1036 + }
1037 + grub_strcpy (b, subst);
1038 + b += grub_strlen (subst);
1039 + }
1040 + else if (*str == '\\' && !escaped)
1041 + escaped = 1;
1042 + else
1043 + {
1044 + escaped = 0;
1045 + if (b - buffer + 1 > sizeof (buffer))
1046 + {
1047 + errnum = ERR_FILELENGTH;
1048 + return NULL;
1049 + }
1050 + *b++ = *str;
1051 + }
1052 + str++;
1053 + }
1054 + *len = b - buffer;
1055 +
1056 + return buffer;
1057 +}
1058 +
1059 /* This is the starting function in C. */
1060 void
1061 cmain (void)
1062 @@ -1262,6 +1486,97 @@
1063 menu_entries = (char *) MENU_BUF;
1064 init_config ();
1065 }
1066 +
1067 + auto void expand_wildcard_entries (void);
1068 + void expand_wildcard_entries (void)
1069 + {
1070 + char *config_entry = config_entries;
1071 + char *menu_entry = menu_entries;
1072 +
1073 + while (*menu_entry)
1074 + {
1075 + char *command = config_entry;
1076 +
1077 + do
1078 + {
1079 + char *c = command;
1080 + const char *w = "wildcard";
1081 +
1082 + while (*w && *c == *w)
1083 + {
1084 + c++;
1085 + w++;
1086 + }
1087 + if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '='))
1088 + {
1089 + int len, wlen;
1090 +
1091 + /* This is a wildcard command. Advance to the argument. */
1092 + while (*c == ' ' || *c == '\t' || *c == '=')
1093 + c++;
1094 +
1095 + /* Expand wildcard entry. */
1096 + w = wildcard (c, &wlen);
1097 + if (w)
1098 + inplace_sort (w, wlen);
1099 +
1100 + /* Remove the wildcard command from the command section;
1101 + it has no meaning beyond the wildcard expansion just
1102 + performed. */
1103 + len = grub_strlen (command) + 1;
1104 + grub_memmove (command, command + len,
1105 + config_len - (command - config_entries));
1106 + config_len -= len;
1107 +
1108 + while (w && wlen)
1109 + {
1110 + /* Insert expansion before the wildcard entry in the
1111 + list of entry names. */
1112 + len = grub_strlen (menu_entry) + 1;
1113 + const char *x = expand_asterisks (menu_entry, &len, w);
1114 + grub_memmove (menu_entry + len, menu_entry,
1115 + menu_len - (menu_entry - menu_entries));
1116 + memcpy (menu_entry, x, len);
1117 + menu_entry += len;
1118 + menu_len += len;
1119 +
1120 + /* Insert expansion before the wildcard command section
1121 + in the list of command sections. */
1122 + len = this_config_len (config_entry);
1123 + x = expand_asterisks (config_entry, &len, w);
1124 + grub_memmove (config_entry + len, config_entry,
1125 + config_len - (config_entry -
1126 + config_entries));
1127 + memcpy (config_entry, x, len);
1128 + config_entry += len;
1129 + config_len += len;
1130 +
1131 + num_entries++;
1132 + wlen -= grub_strlen (w) + 1;
1133 + w += grub_strlen (w) + 1;
1134 + }
1135 +
1136 + /* Remove the wildcard command section; it has just
1137 + been expanded. */
1138 + len = grub_strlen (menu_entry) + 1;
1139 + grub_memmove (menu_entry, menu_entry + len,
1140 + menu_len - (menu_entry - menu_entries));
1141 + menu_len -= len;
1142 +
1143 + len = this_config_len(config_entry);
1144 + grub_memmove (config_entry, config_entry + len,
1145 + config_len - (config_entry - config_entries));
1146 + config_len -= len;
1147 +
1148 + num_entries--;
1149 + }
1150 + command += grub_strlen (command) + 1;
1151 + }
1152 + while (*command);
1153 + menu_entry += grub_strlen (menu_entry) + 1;
1154 + config_entry += this_config_len(config_entry);
1155 + }
1156 + }
1157
1158 /* Initialize the environment for restarting Stage 2. */
1159 grub_setjmp (restart_env);
1160 @@ -1414,8 +1729,16 @@
1161 config_len = prev_config_len;
1162 }
1163
1164 + if (is_preset)
1165 + close_preset_menu ();
1166 + else
1167 + grub_close ();
1168 +
1169 menu_entries[menu_len++] = 0;
1170 config_entries[config_len++] = 0;
1171 +
1172 + expand_wildcard_entries();
1173 +
1174 grub_memmove (config_entries + config_len, menu_entries,
1175 menu_len);
1176 menu_entries = config_entries + config_len;
1177 @@ -1456,11 +1779,6 @@
1178 else
1179 default_entry = 0;
1180 }
1181 -
1182 - if (is_preset)
1183 - close_preset_menu ();
1184 - else
1185 - grub_close ();
1186 }
1187 while (is_preset);
1188 }