Hi,

Back from my holidays I hacked some code into GRUB and finally merged
the stuff which todays (1999-07-16) CVS rep. 

What the stuff does:

1) Bug fix: `gzip' is working on /sbin/grub (HACK yet but its in the
   /sbin/grub tradition).

2) Completed the completion (Commands & filenames work, directories are
   completed like bash does - See ChangeLog & NEWS).

3) Minix V1 - 14 char filenames is working.
   To create such a thing on Linux use:
   mkfs.minix  -c -n14 DEVICE 

Keep on hacking folks,
KR

BTW: OKUJI, tell us what `diff SWITCHES PREFIX' is preferred.
--
Klaus Reichl @ HOME     email: [EMAIL PROTECTED] 

Here's the patch:

diff -ruN -X grub.ignore grub-1999-07-16/src/grub/ChangeLog grub/src/grub/ChangeLog
--- grub-1999-07-16/src/grub/ChangeLog  Fri Jul 16 21:28:10 1999
+++ grub/src/grub/ChangeLog     Fri Jul 16 22:58:10 1999
@@ -1,3 +1,55 @@
+1999-07-09  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * stage2/cmdline.c (commands): Change layout to make
+       COMPLETE_COMMANDS prettier.
+
+       * stage2/char_io.c (complete_commands): New function doing command
+       completion. 
+       stage2/char_io.c (get_cmdline): Use it.
+
+       * stage2/disk_io.c (print_a_completion): add LEADING parameter to
+       give the caller the chance to specifiy what LEADING char has to be
+       printed (this is for command completion vs. file completion).
+       stage2/shared.h: update prototype
+       (print_completions): use it passing ' '
+       stage2/fsys_minix.c (minix_dir): ditto
+       stage2/fsys_ffs.c (ffs_dir): ditto
+       stage2/fsys_fat.c (fat_dir): ditto
+       stage2/fsys_ext2fs.c (ext2fs_dir): ditto
+
+1999-07-08  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * stage2/gunzip.c (reset_linalloc): Add missing RAW_ADDR.
+       (gunzip_slide): make public to check in `memcheck'.
+       (gunzip_inbuf): ditto.
+       
+       * stage2/char_io.c (memcheck): check for globals GUNZIP_INBUF and
+       GUNZIP_SLIDE being memcpy'd to. 
+
+       * stage2/fsys_minix.c: new file.
+       
+       * stage2/disk_io.c (fsys_table): minix stuff added
+       * stage2/filesys.h: ditto
+       * stage2/pc_slice.h: ditto
+       * stage2/shared.h: ditto
+       * stage2/Makefile.am: ditto
+
+1999-07-03  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * Finish completion stuff to work almost like bash: ' 's in
+       filenames don't work yet, however.  
+       stage2/disk_io.c (print_completions): If the completion is
+       unique, add '/' for directories and ' ' for files.
+       (print_a_completion): leave out "." and "..", this makes
+       completion much nicer.
+       stage2/char_io.c (get_cmdline): Save rest of CMDLINE if we're
+       completing.  This enables completing in the middle of the line. 
+
+       * grub/main.c (main): Use printf instead of grub_printf when
+       announcing gdb string (grub_printf doesn't print at this point in
+       time).  If HOLD is given, print in any case, the person debugging
+       the stuff needs to find out the pid in any case.
+
 1999-07-15  OKUJI Yoshinori  <[EMAIL PROTECTED]>
 
        * stage2/cmdline.c (skip_to): Don't increase CMDLINE if the
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/NEWS grub/src/grub/NEWS
--- grub-1999-07-16/src/grub/NEWS       Fri Jul 16 21:28:10 1999
+++ grub/src/grub/NEWS  Fri Jul 16 21:29:26 1999
@@ -1,11 +1,13 @@
 NEWS - list of user-visible changes between releases of GRUB
 
 New:
+* Minix filesystems (V1 - 14 char filenames yet) added.
 * Bug fixes (i.e. Stage 1.5 can work fine again).
 * The /sbin/grub stage2 simulator now works at least on GNU/Linux, and
   uses the Linux HDIO_GETGEO ioctl to determine hard disk geometry.
-* TAB not only lists filenames, but also completes a filename when the
-  filename is unique.
+* TAB not only lists filenames and commands, but also completes the
+  unique part of  them.
+  If a filename is unique, a '/' is added for directories, a ' ' otherwise.
 * Password is not echoed back, put an asterisk for each of input
   characters.
 * stage2_debug is removed, and the debugging features are added into
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/grub/main.c grub/src/grub/grub/main.c
--- grub-1999-07-16/src/grub/grub/main.c        Sat Jul  3 08:20:27 1999
+++ grub/src/grub/grub/main.c   Sat Jul  3 23:03:52 1999
@@ -195,10 +195,14 @@
     }
   while (c != EOF);
 
-  /* Wait until the HOLD variable is cleared by an attached debugger. */
-  if (hold && verbose)
-    grub_printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
-                program_name, (int) getpid ());
+  /* Wait until the HOLD variable is cleared by an attached debugger. 
+     Don't depend on VERBOSE here - only people using the debugger need 
+     that and they have to find out the pid  */
+  if (hold)
+    /* Use printf (not grub_printf which is not working at this point in 
+       time */
+    printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
+           program_name, (int) getpid ());
   while (hold)
     sleep (1);
 
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/Makefile.am 
grub/src/grub/stage2/Makefile.am
--- grub-1999-07-16/src/grub/stage2/Makefile.am Fri Jul 16 21:28:11 1999
+++ grub/src/grub/stage2/Makefile.am    Fri Jul 16 21:32:30 1999
@@ -14,15 +14,16 @@
 # The library for /sbin/grub.
 noinst_LIBRARIES = libgrub.a
 libgrub_a_SOURCES = boot.c common.c char_io.c cmdline.c disk_io.c \
-       gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c stage2.c
+       gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c fsys_minix.c stage2.c
 libgrub_a_CFLAGS = @GRUB_CFLAGS@ -DGRUB_UTIL=1 -fwritable-strings
 
 # Stage 2 and Stage 1.5's.
 pkgdatadir = $(datadir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-nodist_pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 ffs_stage1_5
+nodist_pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 \
+                     ffs_stage1_5 minix_stage1_5
 CLEANFILES = $(pkgdata_DATA)
 noinst_PROGRAMS = stage2.exec e2fs_stage1_5.exec fat_stage1_5.exec \
-       ffs_stage1_5.exec
+       ffs_stage1_5.exec minix_stage1_5.exec
 MOSTLYCLEANFILES = $(noinst_PROGRAMS)
 
 STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
@@ -35,8 +36,8 @@
 # asm.S absolutely needs to come first!
 # For stage2 target.
 stage2_exec_SOURCES = asm.S boot.c common.c char_io.c cmdline.c \
-       disk_io.c gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c stage2.c \
-       bios.c smp-imps.c
+       disk_io.c gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c fsys_minix.c \
+       stage2.c bios.c smp-imps.c
 stage2_exec_CFLAGS = $(STAGE2_COMPILE)
 stage2_exec_LDFLAGS = $(STAGE2_LINK)
 
@@ -60,6 +61,14 @@
 ffs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
        -DNO_BLOCK_FILES=1
 ffs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
+
+# For minix_stage1_5 target.
+minix_stage1_5_exec_SOURCES = asm.S common.c char_io.c disk_io.c \
+       stage1_5.c fsys_minix.c bios.c
+
+minix_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
+       -DNO_BLOCK_FILES=1
+minix_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
 
 # General rule for making a raw binary.
 %: %.exec
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/char_io.c 
grub/src/grub/stage2/char_io.c
--- grub-1999-07-16/src/grub/stage2/char_io.c   Fri Jul 16 21:28:11 1999
+++ grub/src/grub/stage2/char_io.c      Fri Jul 16 21:29:27 1999
@@ -137,6 +137,94 @@
          version_string, mbi.mem_lower, mbi.mem_upper);
 }
 
+/* COMMANDS is expected to start of with something like:
+   "Possible commands are:"
+   The a list of "\"COMMAND= parm\"" strings which we try to complete */
+
+static void
+complete_commands (char * cmdline, char * commands)
+{
+  char * p = commands;
+  char save;
+  int  have_a_completion = 0;
+
+  reset_completion ();
+
+  while (*cmdline == ' ' || *cmdline == '\t')
+    cmdline++;
+
+  while (*p && *p != '"')
+    p++;
+
+  save = *p, *p = '\0';
+  printf (commands);
+  *p = save;
+
+  /* p on '\0' or '"' */
+  while (*p)
+    {
+      char * q;
+      int completed = 0;
+
+      /* advance p over '"' */
+      p++;
+
+      /* prepare command field */
+      q = p;
+      while (*q && *q != '"' && *q != ' ' && *q != '\t')
+       q++;
+      if (*q == ' ' || *q == '\t')
+       q++;
+
+      /* check if its a candidate and complete if so */ 
+      if (substring (cmdline, p) <= 0)
+       {
+         completed++;
+         have_a_completion++;
+         save = *q, *q = '\0';
+         print_a_completion (p, '"');
+         *q = save;
+       }
+
+      /* finish up command field */
+      p = q;
+      while (*q && *q != '"')
+       q++;
+      if (*q)
+       q++;
+      while (*q && *q != '"')
+       q++;
+
+      /* if something was completed, print parameters for help text */
+      if (completed)
+       {
+         save = *q, *q = '\0';
+         printf (p);
+         *q = save;
+       }
+
+      p = q;
+    }
+
+  if (! have_a_completion)
+    {
+      printf ("Invalid command\n\n");
+      printf (commands);
+    }
+  else
+    {
+      char *u = unique_string;
+
+      if (*u)
+       {
+         p = cmdline;
+         while ((*p++ = *u++))
+           ;
+       }
+    }
+
+  printf ("\n");
+}
 
 /* Don't use this with a MAXLEN greater than 1600 or so!  The problem
    is that GET_CMDLINE depends on the everything fitting on the screen
@@ -261,41 +349,50 @@
        case 9:         /* TAB lists completions */
          {
            int i, j = 0, llen_old = llen;
-
-           while (cmdline[j] && cmdline[j] != '=')
-             j++;
-
-           /* since the command line cannot have a '\n', we're OK to use c */
-           c = cmdline[lpos];
-
-           cl_kill_to_end ();
-
-           /* goto part after line here */
-           yend = ((llen + plen) / 79) + ystart;
-           putchar ('\n');
-           gotoxy (0, getxy () & 0xff);
-
-           if (lpos > j)
+           /* rest of cmdline to be saved
+              XXX is 512 apropriate for the stack? XXX  */
+           char cmdline_save [512];
+           int  rest_of_line = llen - lpos + 1;
+
+           /* only to completion, if saving the rest of the line
+              is possible  */
+           if (rest_of_line < sizeof (cmdline_save))
              {
-               for (i = lpos; i > 0 && cmdline[i - 1] != ' '; i--);
-               if (i <= j)
-                 i = j + 1;
-               /* print possible completions */
-               print_completions (cmdline + i);
-               /* if somebody in print_completions has added something, 
-                  account for that */
+               while (cmdline[j] && cmdline[j] != '=')
+                 j++;
+               
+               memcpy (cmdline_save, &(cmdline[lpos]), rest_of_line);
+
+               cl_kill_to_end ();
+
+               /* goto part after line here */
+               yend = ((llen + plen) / 79) + ystart;
+               putchar ('\n');
+               gotoxy (0, getxy () & 0xff);
+               
+               if (lpos > j)
+                 {
+                   for (i = lpos; i > 0 && cmdline[i - 1] != ' '; i--);
+                   if (i <= j)
+                     i = j + 1;
+                   /* print possible completions */
+                   print_completions (cmdline + i);
+                 }
+               else if (commands)
+                 complete_commands (cmdline, commands);
+               else
+                 break;
+
+               /* if somebody in PRINT_COMPLETIONS or COMPLETE_COMMANDS has 
+                  added something, account for that */
                while (cmdline[lpos])
                  lpos++, llen_old++;
-             }
-           else if (commands)
-             printf (commands);
-           else
-             break;
 
-           /* restore command-line */
-           cmdline[lpos] = c;
-           llen = llen_old;
-           cl_init ();
+               /* restore command-line */
+               memcpy (&(cmdline[lpos]), cmdline_save, rest_of_line);
+               llen = llen_old;
+               cl_init ();
+             }
          }
          break;
        case 1:         /* C-a go to beginning of line */
@@ -606,6 +703,17 @@
   extern char cur_part_desc[];
   if (start >= (int) cur_part_desc && start + len <= (int) cur_part_desc + 16)
     return ! errnum;
+  /* FIXME: same applies to GUNZIP_INBUF and GUNZIP_SLIDE from gunzip.c */
+  {
+    extern char gunzip_inbuf[];
+    extern char gunzip_slide[];
+
+    if ((start >= (int) gunzip_inbuf 
+        && start + len <= (int) gunzip_inbuf + 0x2000)
+       || (start >= (int) gunzip_slide
+           && start + len <= (int) gunzip_slide + 0x8000))
+      return !errnum;
+  }
 #endif /* GRUB_UTIL */
 
   if ((start < RAW_ADDR (0x1000)) ||
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/cmdline.c 
grub/src/grub/stage2/cmdline.c
--- grub-1999-07-16/src/grub/stage2/cmdline.c   Fri Jul 16 21:28:12 1999
+++ grub/src/grub/stage2/cmdline.c      Fri Jul 16 21:36:44 1999
@@ -65,12 +65,13 @@
 }
 
 char commands[] =
-" Possible commands are: \"pause= ...\", \"uppermem= <kbytes>\", \"root= <device>\",
+ " Possible commands are:
+  \"pause= ...\", \"uppermem= <kbytes>\", \"root= <device>\",
   \"rootnoverify= <device>\", \"chainloader= <file>\", \"kernel= <file> ...\",
   \"testload= <file>\", \"read= <addr>\", \"displaymem\", \"impsprobe\",
   \"fstest\", \"debug\", \"module= <file> ...\", \"modulenounzip= <file> ...\",
   \"color= <normal> [<highlight>]\", \"makeactive\", \"boot\", \"quit\" and
-  \"install= <stage1_file> [d] <dest_dev> <file> <addr> [p] [<config_file>]\"\n";
+  \"install= <stage1_file> [d] <dest_dev> <file> <addr> [p] [<config_file>]\"";
 
 static void
 debug_fs_print_func (int sector)
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/disk_io.c 
grub/src/grub/stage2/disk_io.c
--- grub-1999-07-16/src/grub/stage2/disk_io.c   Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/disk_io.c      Fri Jul 16 23:12:20 1999
@@ -46,6 +46,9 @@
 # ifdef FSYS_FFS
   {"ffs", ffs_mount, ffs_read, ffs_dir},
 # endif
+# ifdef FSYS_MINIX
+  {"minix", minix_mount, minix_read, minix_dir},
+# endif
   {0, 0, 0, 0}
 };
 
@@ -584,7 +587,8 @@
 static int incomplete, disk_choice;
 #ifndef STAGE1_5
 static int unique;
-static char unique_string[128];        /* XXX Don't know yet */ 
+char unique_string[128];       /* XXX Don't know yet about size*/ 
+static int complete_silently;
 #endif
 static enum
   {
@@ -915,16 +919,34 @@
 
 #ifndef STAGE1_5
 /*
- *  print_a_completion saves what has been printed to unique_string
- *  printf's with a leading ' '.
+ * call RESET_COMPLETION to start new PRINT_A_COMPLETION series
  */
 
 void
-print_a_completion (char *filename)
+reset_completion (void)
+{
+  *unique_string = '\0';
+  unique = 0;
+}
+
+/*
+ *  PRINT_A_COMPLETION saves the unique part of what has been printed
+ *  to UNIQUE_STRING.  
+ *  printf's with a leading char LEADING, unless COMPLETE_SILENTLY is set.
+ *  UNIQUE is incremented on every file considered.
+ */
+
+void
+print_a_completion (char *filename, char leading)
 {
   char *f = filename;
   char *u = unique_string;
-  
+
+  /* leave "." and ".." out of completions */
+  if ((f[0] == '.' && f[1] == '\0')
+      || (f[0] == '.' && f[1] == '.' && f[2] =='\0'))
+    return;
+
   if (! *u && unique == 0)
     {
       /* copy first string, this is unique.  */
@@ -939,8 +961,9 @@
       *u = '\0';
     }
   unique++;
-  
-  printf (" %s", filename);
+
+  if (!complete_silently)
+    printf ("%c%s", leading, filename);
 }
 
 /*
@@ -953,9 +976,8 @@
 {
   char *ptr = filename;
 
-  *unique_string = '\0';
-  unique = 0;
-  
+  reset_completion ();
+
   if (*filename == '/' || (ptr = set_device (filename)) || incomplete)
     {
       errnum = 0;
@@ -986,7 +1008,7 @@
                          dev_name[1] = 'd';
                          dev_name[2] = '0' + j;
                          dev_name[3] = '\0';
-                         print_a_completion (dev_name);
+                         print_a_completion (dev_name, ' ');
                        }
                    }
                }
@@ -1042,18 +1064,40 @@
          /* filename completions */
          printf (" Possible files are:");
          dir (filename);
+
+         if (!errnum)
          {
            char *u = unique_string;
            
            if (*u)
              {
-               while (*ptr++)
-                 ;
-               while (*ptr != '/')
+               while (*ptr)
+                 ptr++;
+               while (ptr[-1] != '/')
                  ptr--;
-               ptr++;
                while ((*ptr++ = *u++))
                  ;
+               ptr--;
+
+               if (unique == 1)
+                 {
+                   printf (" Unique expansion");
+                   /* try to add '/' to find out if its a directory */
+                   ptr[0] = '/';
+                   ptr[1] = '\0';
+                   complete_silently = 1;
+                   dir (filename);
+                   complete_silently = 0;
+                   if (errnum)
+                     {
+                       /* Not a directory, ... */
+                       errnum = 0;
+                       /* ... however, its unique so add a ' ' */
+                       ptr[0] = ' ';
+                       /* this \n makes the picture consistend */
+                       putchar ('\n');
+                     }
+                 }
              }
          }
        }
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/filesys.h 
grub/src/grub/stage2/filesys.h
--- grub-1999-07-16/src/grub/stage2/filesys.h   Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/filesys.h      Sun Jul  4 00:14:00 1999
@@ -25,10 +25,12 @@
  *  Default to all functioning filesystems enabled
  */
 
-#if !( defined(FSYS_FFS) || defined(FSYS_FAT) || defined(FSYS_EXT2FS) )
+#if !( defined(FSYS_FFS) || defined(FSYS_FAT) \
+       || defined(FSYS_EXT2FS) || defined(FSYS_MINIX) )
 #define FSYS_FFS
 #define FSYS_FAT
 #define FSYS_EXT2FS
+#define FSYS_MINIX
 #endif
 
 #ifdef FSYS_FFS
@@ -61,8 +63,18 @@
 #define FSYS_EXT2FS_NUM 0
 #endif
 
+#ifdef FSYS_MINIX
+#define FSYS_MINIX_NUM 1
+int minix_mount (void);
+int minix_read (char *buf, int len);
+int minix_dir (char *dirname);
+#else
+#define FSYS_MINIX_NUM 0
+#endif
+
 #ifndef NUM_FSYS
-#define NUM_FSYS  ( FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM )
+#define NUM_FSYS  ( FSYS_FFS_NUM + FSYS_FAT_NUM \
+                    + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM )
 #endif
 
 /* defines for the block filesystem info area */
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/fsys_ext2fs.c 
grub/src/grub/stage2/fsys_ext2fs.c
--- grub-1999-07-16/src/grub/stage2/fsys_ext2fs.c       Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/fsys_ext2fs.c  Thu Jul  8 23:54:54 1999
@@ -757,7 +757,7 @@
                {
                  if (print_possibilities > 0)
                    print_possibilities = -print_possibilities;
-                 print_a_completion (dp->name);
+                 print_a_completion (dp->name, ' ');
                }
 # endif
 
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/fsys_fat.c 
grub/src/grub/stage2/fsys_fat.c
--- grub-1999-07-16/src/grub/stage2/fsys_fat.c  Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/fsys_fat.c     Thu Jul  8 23:54:54 1999
@@ -240,7 +240,7 @@
        {
          if (print_possibilities > 0)
            print_possibilities = -print_possibilities;
-         print_a_completion (filename);
+         print_a_completion (filename, ' ');
        }
 # endif /* STAGE1_5 */
     }
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/fsys_ffs.c 
grub/src/grub/stage2/fsys_ffs.c
--- grub-1999-07-16/src/grub/stage2/fsys_ffs.c  Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/fsys_ffs.c     Thu Jul  8 23:54:53 1999
@@ -252,7 +252,7 @@
          if (print_possibilities > 0)
            print_possibilities = -print_possibilities;
 
-         print_a_completion (dp->d_name);
+         print_a_completion (dp->d_name, ' ');
        }
 #endif /* STAGE1_5 */
     }
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/fsys_minix.c 
grub/src/grub/stage2/fsys_minix.c
--- grub-1999-07-16/src/grub/stage2/fsys_minix.c        Thu Jan  1 01:00:00 1970
+++ grub/src/grub/stage2/fsys_minix.c   Fri Jul 16 22:56:50 1999
@@ -0,0 +1,523 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999  Klaus Reichl <[EMAIL PROTECTED]>
+ *  Copyright (C) 1999  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Restrictions:
+   This is MINIX V1 only (yet)
+   Disk creation is like:
+   mkfs.minix  -c -n14 DEVICE 
+*/
+   
+#include "shared.h"
+#include "filesys.h"
+
+/* #define DEBUG_MINIX */
+
+/* indirect blocks */
+static int mapblock1, mapblock2;
+
+/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
+#define DEV_BSIZE 512
+
+/* include/linux/fs.h */
+#define BLOCK_SIZE_BITS 10
+#define BLOCK_SIZE     (1<<BLOCK_SIZE_BITS)
+
+/* made up, defaults to 1 but can be passed via mount_opts */
+#define WHICH_SUPER 1
+/* kind of from fs/ext2/super.c (is OK for minix) */
+#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)  /* = 2 */
+
+/* include/asm-i386/type.h */
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/* include/linux/minix_fs.h */
+#define MINIX_ROOT_INO 1
+
+/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
+#define MINIX_LINK_MAX  250
+#define MINIX2_LINK_MAX 65530
+
+#define MINIX_I_MAP_SLOTS       8
+#define MINIX_Z_MAP_SLOTS       64
+#define MINIX_SUPER_MAGIC       0x137F          /* original minix fs */
+#define MINIX_SUPER_MAGIC2      0x138F          /* minix fs, 30 char names */
+#define MINIX2_SUPER_MAGIC      0x2468          /* minix V2 fs */
+#define MINIX2_SUPER_MAGIC2     0x2478          /* minix V2 fs, 30 char names */
+#define MINIX_VALID_FS          0x0001          /* Clean fs. */
+#define MINIX_ERROR_FS          0x0002          /* fs has errors. */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
+#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
+
+#define MINIX_V1                0x0001          /* original minix fs */
+#define MINIX_V2                0x0002          /* minix V2 fs */
+
+/* originally this is : 
+#define INODE_VERSION(inode)    inode->i_sb->u.minix_sb.s_version
+   here we have */
+#define INODE_VERSION(inode)   (SUPERBLOCK->s_version)
+
+#define MINIX_NAME_LEN         14 /* XXX depend on version */
+
+/*
+ * This is the original minix inode layout on disk.
+ * Note the 8-bit gid and atime and ctime.
+ */
+struct minix_inode {
+       __u16 i_mode;
+       __u16 i_uid;
+       __u32 i_size;
+       __u32 i_time;
+       __u8  i_gid;
+       __u8  i_nlinks;
+       __u16 i_zone[9];
+};
+
+/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct minix2_inode {
+       __u16 i_mode;
+       __u16 i_nlinks;
+       __u16 i_uid;
+       __u16 i_gid;
+       __u32 i_size;
+       __u32 i_atime;
+       __u32 i_mtime;
+       __u32 i_ctime;
+       __u32 i_zone[10];
+};
+
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+        __u16 s_ninodes;
+        __u16 s_nzones;
+        __u16 s_imap_blocks;
+        __u16 s_zmap_blocks;
+        __u16 s_firstdatazone;
+        __u16 s_log_zone_size;
+        __u32 s_max_size;
+        __u16 s_magic;
+        __u16 s_state;
+        __u32 s_zones;
+};
+
+struct minix_dir_entry {
+        __u16 inode;
+        char name[0];
+};
+
+/* made up, these are pointers into FSYS_BUF */
+/* read once, always stays there: */
+#define SUPERBLOCK \
+    ((struct minix_super_block *)(FSYS_BUF))
+#define INODE \
+    ((struct minix_inode *)((int) SUPERBLOCK + BLOCK_SIZE))
+#define DATABLOCK1 \
+    ((int)((int)INODE + sizeof(struct minix_inode)))
+#define DATABLOCK2 \
+    ((int)((int)DATABLOCK1 + BLOCK_SIZE))
+
+/* linux/stat.h */
+#define S_IFMT  00170000
+#define S_IFLNK  0120000
+#define S_IFREG  0100000
+#define S_IFDIR  0040000
+#define S_ISLNK(m)     (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
+
+#define PATH_MAX                1024   /* include/linux/limits.h */
+#define MAX_LINK_COUNT             5   /* number of symbolic links to follow */
+
+/* check filesystem types and read superblock into memory buffer */
+int
+minix_mount (void)
+{
+  int retval = 1;
+
+  if ((((current_drive & 0x80 || current_slice != 0))
+       && (current_slice != PC_SLICE_TYPE_MINIX)
+       && (current_slice != (PC_SLICE_TYPE_BSD | (FS_OTHER << 8))))
+      || part_length < (SBLOCK + 
+                       (sizeof (struct minix_super_block) / DEV_BSIZE))
+      || !devread (SBLOCK, 0, sizeof (struct minix_super_block),
+                  (char *) SUPERBLOCK)
+      || SUPERBLOCK->s_magic != MINIX_SUPER_MAGIC)
+    retval = 0;
+
+  return retval;
+}
+
+/* Takes a file system block number and reads it into BUFFER. */
+static int
+minix_rdfsb (int fsblock, int buffer)
+{
+  return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0,
+                 BLOCK_SIZE, (char *) buffer);
+}
+
+/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
+   a physical block (the location in the file system) via an inode. */
+static int
+minix_block_map (int logical_block)
+{
+  int i;
+
+  if (logical_block < 7)
+    return INODE->i_zone[logical_block];
+
+  logical_block -= 7;
+  if (logical_block < 512)
+    {
+      i = INODE->i_zone[7];
+      
+      if (!i || ((mapblock1 != 1)
+                && !minix_rdfsb (i, DATABLOCK1)))
+       {
+         errnum = ERR_FSYS_CORRUPT;
+         return -1;
+       }
+      mapblock1 = 1;
+      return ((__u16 *) DATABLOCK1) [logical_block];
+    }
+
+  logical_block -= 512;
+  i = INODE->i_zone[8];
+  if (!i || ((mapblock1 != 2)
+            && !minix_rdfsb (i, DATABLOCK1)))
+    {
+      errnum = ERR_FSYS_CORRUPT;
+      return -1;
+    }
+  mapblock1 = 2;
+  i = ((__u16 *) DATABLOCK1)[logical_block >> 9];
+  if (!i || ((mapblock2 != i)
+            && !minix_rdfsb (i, DATABLOCK2)))
+    {
+      errnum = ERR_FSYS_CORRUPT;
+      return -1;
+    }
+  mapblock2 = i;
+  return ((__u16 *) DATABLOCK2)[logical_block & 511];
+}
+
+/* read from INODE into BUF */
+int
+minix_read (char *buf, int len)
+{
+  int logical_block;
+  int offset;
+  int map;
+  int ret = 0;
+  int size = 0;
+
+  while (len > 0)
+    {
+      /* find the (logical) block component of our location */
+      logical_block = filepos >> BLOCK_SIZE_BITS;
+      offset = filepos & (BLOCK_SIZE - 1);
+      map = minix_block_map (logical_block);
+#ifdef DEBUG_MINIX
+      printf ("map=%d\n", map);
+#endif
+      if (map < 0)
+       break;
+
+      size = BLOCK_SIZE;
+      size -= offset;
+      if (size > len)
+       size = len;
+
+#ifndef STAGE1_5
+      debug_fs_func = debug_fs;
+#endif /* STAGE1_5 */
+
+      devread (map * (BLOCK_SIZE / DEV_BSIZE),
+              offset, size, buf);
+
+#ifndef STAGE1_5
+      debug_fs_func = NULL;
+#endif /* STAGE1_5 */
+
+      buf += size;
+      len -= size;
+      filepos += size;
+      ret += size;
+    }
+
+  if (errnum)
+    ret = 0;
+
+  return ret;
+}
+
+/* preconditions: minix_mount already executed, therefore supblk in buffer
+     known as SUPERBLOCK
+   returns: 0 if error, nonzero iff we were able to find the file successfully
+   postconditions: on a nonzero return, buffer known as INODE contains the
+     inode of the file we were trying to look up
+   side effects: none yet  */
+int
+minix_dir (char *dirname)
+{
+  int current_ino = MINIX_ROOT_INO;  /* start at the root */
+  int updir_ino = current_ino;      /* the parent of the current directory */
+  int ino_blk;                      /* fs pointer of the inode's info */
+
+  int str_chk;                      /* used ot hold the results of a string
+                                       compare */
+
+  struct minix_inode * raw_inode;    /* inode info for current_ino */
+
+  char linkbuf[PATH_MAX];           /* buffer for following sym-links */
+  int link_count = 0;
+
+  char * rest;
+  char ch;
+
+  int off;                          /* offset within block of directory 
+                                       entry */
+  int loc;                          /* location within a directory */
+  int blk;                          /* which data blk within dir entry */
+  long map;                         /* fs pointer of a particular block from
+                                       dir entry */
+  struct minix_dir_entry * dp;      /* pointer to directory entry */
+
+  /* loop invariants:
+     current_ino = inode to lookup
+     dirname = pointer to filename component we are cur looking up within
+     the directory known pointed to by current_ino (if any) */
+
+#ifdef DEBUG_MINIX
+  printf ("\n");
+#endif  
+
+  while (1)
+    {
+#ifdef DEBUG_MINIX
+      printf ("inode %d, dirname %s\n", current_ino, dirname);
+#endif
+
+      ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks
+                + (current_ino - 1) / MINIX_INODES_PER_BLOCK);
+      if (! minix_rdfsb (ino_blk, (int) INODE))
+       return 0;
+
+      /* reset indirect blocks! */
+      mapblock2 = mapblock1 = -1;
+
+      raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK);
+
+      /* copy inode to fixed location */
+      memmove ((void *) INODE, (void *) raw_inode, 
+              sizeof (struct minix_inode));
+
+      /* If we've got a symbolic link, then chase it. */
+      if (S_ISLNK (INODE->i_mode))
+       {
+         int len;
+
+         if (++link_count > MAX_LINK_COUNT)
+           {
+             errnum = ERR_SYMLINK_LOOP;
+             return 0;
+           }
+#ifdef DEBUG_MINIX
+         printf ("S_ISLNK (%s)\n", dirname);
+#endif
+
+         /* Find out how long our remaining name is. */
+         len = 0;
+         while (dirname[len] && !isspace (dirname[len]))
+           len++;
+
+         /* Get the symlink size. */
+         filemax = (INODE->i_size);
+         if (filemax + len > sizeof (linkbuf) - 2)
+           {
+             errnum = ERR_FILELENGTH;
+             return 0;
+           }
+
+         if (len)
+           {
+             /* Copy the remaining name to the end of the symlink data.
+                Note that DIRNAME and LINKBUF may overlap! */
+             memmove (linkbuf + filemax, dirname, len);
+           }
+         linkbuf[filemax + len] = '\0';
+
+         /* Read the necessary blocks, and reset the file pointer. */
+         len = grub_read (linkbuf, filemax);
+         filepos = 0;
+         if (!len)
+           return 0;
+
+#ifdef DEBUG_MINIX
+         printf ("symlink=%s\n", linkbuf);
+#endif
+
+         dirname = linkbuf;
+         if (*dirname == '/')
+           {
+             /* It's an absolute link, so look it up in root. */
+             current_ino = MINIX_ROOT_INO;
+             updir_ino = current_ino;
+           }
+         else
+           {
+             /* Relative, so look it up in our parent directory. */
+             current_ino = updir_ino;
+           }
+
+         /* Try again using the new name. */
+         continue;
+       }
+
+      /* If end of filename, INODE points to the file's inode */
+      if (!*dirname || isspace (*dirname))
+       {
+         if (!S_ISREG (INODE->i_mode))
+           {
+             errnum = ERR_BAD_FILETYPE;
+             return 0;
+           }
+
+         filemax = (INODE->i_size);
+         return 1;
+       }
+
+      /* else we have to traverse a directory */
+      updir_ino = current_ino;
+
+      /* skip over slashes */
+      while (*dirname == '/')
+       dirname++;
+
+      /* if this isn't a directory of sufficient size to hold our file, 
+        abort */
+      if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
+       {
+         errnum = ERR_BAD_FILETYPE;
+         return 0;
+       }
+
+      /* skip to next slash or end of filename (space) */
+      for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
+          rest++);
+
+      /* look through this directory and find the next filename component */
+      /* invariant: rest points to slash after the next filename component */
+      *rest = 0;
+      loc = 0;
+
+      do
+       {
+#ifdef DEBUG_MINIX
+         printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc);
+#endif
+
+         /* if our location/byte offset into the directory exceeds the size,
+            give up */
+         if (loc >= INODE->i_size)
+           {
+             if (print_possibilities < 0)
+               {
+                 putchar ('\n');
+               }
+             else
+               {
+                 errnum = ERR_FILE_NOT_FOUND;
+                 *rest = ch;
+               }
+             return (print_possibilities < 0);
+           }
+
+         /* else, find the (logical) block component of our location */
+         blk = loc >> BLOCK_SIZE_BITS;
+
+         /* we know which logical block of the directory entry we are looking
+            for, now we have to translate that to the physical (fs) block on
+            the disk */
+         map = minix_block_map (blk);
+#ifdef DEBUG_MINIX
+         printf ("fs block=%d\n", map);
+#endif
+         mapblock2 = -1;
+         if ((map < 0) || !minix_rdfsb (map, DATABLOCK2))
+           {
+             errnum = ERR_FSYS_CORRUPT;
+             *rest = ch;
+             return 0;
+           }
+         off = loc & (BLOCK_SIZE - 1);
+         dp = (struct minix_dir_entry *) (DATABLOCK2 + off);
+         /* advance loc prematurely to next on-disk directory entry  */
+         loc += sizeof (dp->inode) + 14; /* XXX */
+
+         /* NOTE: minix filenames are NULL terminated if < 14 else exact */
+
+#ifdef DEBUG_MINIX
+         printf ("directory entry ino=%d\n", dp->inode);
+         if (dp->inode)
+           printf ("entry=%s\n", dp->name);
+#endif
+
+         if (dp->inode)
+           {
+             int saved_c = dp->name[MINIX_NAME_LEN+1];
+
+             dp->name[MINIX_NAME_LEN+1] = 0;
+             str_chk = substring (dirname, dp->name);
+
+# ifndef STAGE1_5
+             if (print_possibilities && ch != '/'
+                 && (!*dirname || str_chk <= 0))
+               {
+                 if (print_possibilities > 0)
+                   print_possibilities = -print_possibilities;
+                 print_a_completion (dp->name, ' ');
+               }
+# endif
+
+             dp->name[MINIX_NAME_LEN+1] = saved_c;
+           }
+
+       }
+      while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
+
+      current_ino = dp->inode;
+      *(dirname = rest) = ch;
+    }
+  /* never get here */
+}
+
+/* End of fsys_minix.c */
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/gunzip.c 
grub/src/grub/stage2/gunzip.c
--- grub-1999-07-16/src/grub/stage2/gunzip.c    Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/gunzip.c       Thu Jul  8 22:32:07 1999
@@ -169,7 +169,7 @@
 static void
 reset_linalloc (void)
 {
-  linalloc_topaddr = (mbi.mem_upper << 10) + 0x100000;
+  linalloc_topaddr = RAW_ADDR ((mbi.mem_upper << 10) + 0x100000);
 }
 
 
@@ -352,7 +352,8 @@
 
 
 /* sliding window in uncompressed data */
-static uch slide[WSIZE];
+uch gunzip_slide[WSIZE];
+#define slide gunzip_slide
 
 /* current position in slide */
 static unsigned wp;
@@ -473,7 +474,8 @@
 
 #define INBUFSIZ  0x2000
 
-static uch inbuf[INBUFSIZ];
+uch gunzip_inbuf[INBUFSIZ];
+#define inbuf gunzip_inbuf
 static int bufloc;
 
 static int
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/pc_slice.h 
grub/src/grub/stage2/pc_slice.h
--- grub-1999-07-16/src/grub/stage2/pc_slice.h  Sun Jun 27 13:35:37 1999
+++ grub/src/grub/stage2/pc_slice.h     Sun Jul  4 00:47:52 1999
@@ -104,6 +104,7 @@
 #define PC_SLICE_TYPE_FAT16_GT32M      6
 #define PC_SLICE_TYPE_WIN95_EXTENDED   0xf
 #define PC_SLICE_TYPE_EXT2FS           0x83
+#define PC_SLICE_TYPE_MINIX            0x80
 
  /* this next one is special, as it uses it's own partitioning scheme
     to subdivide the PC partition from there */
diff -ruN -X grub.ignore grub-1999-07-16/src/grub/stage2/shared.h 
grub/src/grub/stage2/shared.h
--- grub-1999-07-16/src/grub/stage2/shared.h    Fri Jul 16 21:28:12 1999
+++ grub/src/grub/stage2/shared.h       Fri Jul 16 21:29:27 1999
@@ -134,6 +134,7 @@
 #define STAGE2_ID_FFS_STAGE1_5 1
 #define STAGE2_ID_E2FS_STAGE1_5        2
 #define STAGE2_ID_FAT_STAGE1_5 3
+#define STAGE2_ID_MINIX_STAGE1_5 4
 
 #ifndef STAGE1_5
 #define STAGE2_ID      STAGE2_ID_STAGE2
@@ -144,7 +145,9 @@
 #define STAGE2_ID      STAGE2_ID_E2FS_STAGE1_5
 #elif defined(FSYS_FAT)
 #define STAGE2_ID      STAGE2_ID_FAT_STAGE1_5
-#else
+#elif defined(FSYS_MINIX)
+#define STAGE2_ID      STAGE2_ID_MINIX_STAGE1_5
+#else 
 #error "unknown Stage 2"
 #endif
 #endif
@@ -558,8 +561,11 @@
 /* Display statistics on the current active device. */
 void print_fsys_type (void);
 
-/* Display device and filename completions. */
-void print_a_completion (char *filename);
+/* Display command, device, and filename completions. */
+
+extern char unique_string [];
+void reset_completion (void);
+void print_a_completion (char *filename, char leading);
 void print_completions (char *filename);
 
 /* Copies the current partition data to the desired address. */

Reply via email to