bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] diskpart


From: Neal H Walfield
Subject: [PATCH] diskpart
Date: Mon, 15 Jan 2001 22:48:17 -0500
User-agent: Mutt/1.2.5i

This adds the diskpart library and translator to the hurd along with
the partinfo utility.  This patch relies on my previous libnetfs patch.

I have tested this on both FreeBSD UFS partitions and Linux ext2
partitions.  This will not work with OpenBSD; someone else might want to
add this.

Diskpart suffers from a limitation inherent in the store remap class
in that it cannot access partitions beyond the 4 GB offset.  This can
be seen in some output.  Keep in mind that hd0 is a 7.9GB drive and
sd0 is an 8.5GB drive.  The sizes end up loosing a few bits and we
end up with SIZE % 2^32.

neal@hurd:~ (0)$ sudo settrans -ac temp /hurd/diskpart hd0
Password:
neal@hurd:~ (0)$ sudo partinfo hd0
hd0:
  record size: 512 bytes
  device size: 3967 megabytes
Drive   Offset  Size    Major   Minor
        (MB)    (MB)    Type    Type
hd0s1   0       941     0x0     0x83
hd0s2   941     941     0x0     0x83
hd0s3   1882    941     0x0     0x83
        2823    996     0x0     0xa5
hd0s5   2823    50      0x1     0x7
hd0s6   2873    192     0x1     0x1
        2823    0       0x1     0x0
hd0s7   3327    5       0x1     0x7
hd0s8   3262    20      0x1     0x7
hd0s9   3282    5       0x1     0x7
hd0s10  3287    20      0x1     0x7
hd0s11  3307    20      0x1     0x7
neal@hurd:~ (0)$ settrans -ac foo /hurd/ufs temp/5
neal@hurd:~ (0)$ ls temp/5
temp/5
neal@hurd:~ (0)$ ls foo
a  bin   c  dev  etc  mnt      proc  sbin   tmp  var
b  boot  d  e    f    modules  root  stand  usr
neal@hurd:~ (0)$ settrans -g foo
neal@hurd:~ (0)$ ps -A | grep disk
root      8535  - So    0:00.01 /hurd/diskpart hd0
neal      8544 p1 S     0:00.01 grep disk
neal@hurd:~ (0)$ sudo bash -c "kill 8535"
neal@hurd:~ (0)$ sudo settrans -ac temp /hurd/diskpart sd0
neal@hurd:~ (0)$ sudo partinfo sd0
sd0:
  record size: 512 bytes
  device size: 489 megabytes
Drive   Offset  Size    Major   Minor
        (MB)    (MB)    Type    Type
sd0s1   0       243     0x0     0x82
sd0s2   243     1427    0x0     0x83
sd0s3   1670    4149    0x0     0x83
        5820    2855    0x0     0x5
sd0s5   5820    956     0x0     0x83
        6777    956     0x0     0x5
sd0s6   6777    956     0x0     0x83
        7734    941     0x0     0x5
sd0s7   7734    941     0x0     0x83
neal@hurd:~ (0)$ settrans -ac temp /hurd/diskpart sd0
/hurd/diskpart: get_privileged_ports: Operation not permitted
settrans: /hurd/diskpart: Translator died
neal@hurd:~ (4)$ settrans -ac foo /hurd/ext2fs temp/5
ext2fs: temp/5: panic: main: device too small for superblock (0 bytes)
settrans: /hurd/ext2fs: Translator died
neal@hurd:~ (4)$ storeinfo temp/1
device: sd0: 512: 497952: 254951424: 63+497952
neal@hurd:~ (0)$ storeinfo temp/*
device: sd0: 512: 497952: 254951424: 63+497952
device: sd0: 512: 504827: 258471424: 498015+504827
device: sd0: 512: 0: 0: 
device: sd0: 512: 0: 0: 
device: sd0: 512: 0: 0: 
device: sd0: 512: 0: 0: 

-Neal


--- hurd/ChangeLog      Thu May 25 15:23:28 2000
+++ hurd-nfs/ChangeLog  Mon Jan 15 22:44:54 2001
@@ -1,3 +1,7 @@
+2001-01-15  Neal H Walfield   <neal@cs.uml.edu>
+
+       * Makefile:  Add support for building libdiskpart and dispart.
+
 2000-05-20  Mark Kettenis  <kettenis@gnu.org>
 
        * configure.in: Add check for libio.  Only enable versioning if we
--- hurd/Makefile       Thu Nov 18 01:31:24 1999
+++ hurd-nfs/Makefile   Mon Jan 15 20:56:31 2001
@@ -30,7 +30,7 @@
 # Hurd libraries
 lib-subdirs = libshouldbeinlibc libihash libiohelp libports libthreads \
              libpager libfshelp libdiskfs libtrivfs libps \
-             libnetfs libpipe libstore libhurdbugaddr libftpconn
+             libnetfs libpipe libstore libhurdbugaddr libftpconn libdiskpart
 
 # Hurd programs
 prog-subdirs = auth proc exec init term \
@@ -39,7 +39,7 @@
               login daemons nfsd boot serverboot \
               hostmux usermux ftpfs trans \
               utils sutils ufs-fsck ufs-utils \
-              benchmarks fstests
+              benchmarks fstests diskpart
 
 # Other directories
 other-subdirs = hurd doc config release include debian
diff --exclude=CVS -ur --new-file hurd/libdiskpart/ChangeLog 
hurd-new/libdiskpart/ChangeLog
--- hurd/libdiskpart/ChangeLog  Wed Dec 31 19:00:00 1969
+++ hurd-new/libdiskpart/ChangeLog      Mon Jan 15 20:21:57 2001
@@ -0,0 +1,6 @@
+2001-01-15  Neal H Walfield   <neal@cs.uml.edu>
+
+       * diskpart.h: New file.
+       * diskpart.c: New file.
+       * pc_slice.h: New file imported from Grub and heavily modified.
+
diff --exclude=CVS -ur --new-file hurd/libdiskpart/Makefile 
hurd-new/libdiskpart/Makefile
--- hurd/libdiskpart/Makefile   Wed Dec 31 19:00:00 1969
+++ hurd-new/libdiskpart/Makefile       Mon Jan 15 17:42:37 2001
@@ -0,0 +1,31 @@
+# 
+#   Copyright (C) 2001 Free Software Foundation, Inc.
+# 
+#   This file is part of the GNU Hurd.
+# 
+#   The GNU Hurd 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, or (at
+#   your option) any later version.
+# 
+#   The GNU Hurd 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.
+
+dir := libdiskpart
+makemode := library
+
+libname := libdiskpart
+SRCS = diskpart.c
+LCLHDRS = diskpart.h pc_slice.h
+installhdrs = diskpart.h
+
+OBJS = $(SRCS:.c=.o)
+
+include ../Makeconf
+
diff --exclude=CVS -ur --new-file hurd/libdiskpart/diskpart.c 
hurd-new/libdiskpart/diskpart.c
--- hurd/libdiskpart/diskpart.c Wed Dec 31 19:00:00 1969
+++ hurd-new/libdiskpart/diskpart.c     Mon Jan 15 20:21:40 2001
@@ -0,0 +1,417 @@
+/*  Partition table frobbing routines.
+  
+    Copyright (C) 2001 Free Software Foundation, Inc.
+
+    Written by Neal H Walfield <neal@cs.uml.edu>
+  
+    This file is part of the GNU Hurd.
+  
+    The GNU Hurd 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, or (at
+    your option) any later version.
+  
+    The GNU Hurd 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.  */
+
+#include <stdlib.h>
+#include <error.h>
+#include <stdarg.h>
+#include <hurd.h>
+
+#include "diskpart.h"
+#include "pc_slice.h"
+
+/* Convert X blocks of size BLOCK_SIZE to Megabytes.  */
+#define BLOCK_TO_MB(x, block_size) ((((x) / 1024) * block_size) / 1024)
+
+#define SECTOR_SIZE (512)
+
+/* A partition table structure.  */
+struct partition_table
+{
+  struct partition **partition; /* An array of partitions.  */
+  int count;                    /* Number of used slots is partition.  */
+  int space;                    /* Amount of slots allocated in partition.  */
+
+  /* Used to filling parition->id when registering a partitin.  */
+  int next_primary_id;         /* The next primary id to hand out.  */
+  int next_extended_id;                /* The next extended id to hand out.  */
+};
+
+/* Allocate an emtpy partition table in P_TABLE.  */
+error_t
+partition_table_new (struct partition_table **table)
+{
+  *table = calloc (1, sizeof (struct partition_table));
+  if (! *table)
+    return ENOMEM;
+
+  (*table)->next_primary_id = 1;
+  /* 4 and 5 are the same partition.  If there are four primary
+     partitions, then 4 is used for the last primary partition.
+     If there is a primary extended partition, then that partition
+     is labeled 5.  */
+  (*table)->next_extended_id = 5;
+
+  return 0;
+}
+
+/* Release the resources associated with P_TABLE.  */
+error_t
+partition_table_free (struct partition_table *table)
+{
+  int i;
+  for (i = 0; i < table->count; i ++)
+    free (table->partition[i]);
+  free (table);
+
+  return 0;
+}
+
+/* Add a partition to P_TABLE; this is normally done automatically by
+   partition_table_scan.  */
+error_t
+partition_register (struct partition_table *table, int primary,
+                   size_t size, off_t offset, int do_export,
+                   int major_type, int minor_type)
+{
+  struct partition *p;
+
+  p = malloc (sizeof (struct partition));
+  if (! p)
+    return ENOMEM;
+
+  if (table->space == table->count)
+    {
+      table->space += 10;
+      table->partition = realloc (table->partition,
+                                 sizeof (struct partition *) * table->space);
+      if (! table->partition)
+       return ENOMEM;
+    }
+
+  table->partition[table->count ++] = p;
+
+  p->primary = primary;
+  p->size = size;
+  p->offset = offset;
+  p->do_export = do_export;
+  p->major_type = major_type;
+  p->minor_type = minor_type;
+
+  if (p->do_export)
+    if (p->primary)
+      p->id = table->next_primary_id ++;
+    else
+      p->id = table->next_extended_id ++;
+  else
+    p->id = 0;
+
+  return 0;
+}
+
+/* Iterate over a partition table calling func on each partition.  If
+   the function ever returns non-zero, the iteration stops immediately
+   and returns that value.  */
+error_t
+partition_table_iterate (struct partition_table *p_table,
+                         int (*func)(struct partition *, void *),
+                        void *cookie)
+{
+  int i;
+  error_t rt;
+
+  for (i = 0; i < p_table->count; i ++)
+    {
+      rt = func (p_table->partition[i], cookie);
+      if (rt)
+       return rt;
+    }
+
+  return 0;
+}
+
+/* PC BIOS Partition Tables
+   ------------------------
+   
+   Partition tables have the following makeup:
+
+   Primary and logical partitions contain either a real
+   partition or a BSD disk label.
+
+   Extended partitions contain logical and extended partitions.
+
+   The primary partition table (that contained in the master
+   boot record) can contain either 0-4 primary partitions or 0-3
+   primary partitions and 1 extended partition.
+
+   The extended partition in the MBR marks the start of the
+   extended drive.  This partition may contain 0-1 logical
+   partitions and 0-1 extended partitions; It _must_ have at
+   least two unused (type == 0) partition slots.
+
+   All extended partitions nested within an extended partition
+   are offset from the _first_ extended partition.  All logical
+   partitions are offset from their containing extended
+   partition.
+
+   Example drive consisting of 6 one gigabyte partitions:
+
+                     Primary   Logical   Logical   Logical
+    Primary           Partition Partition Partition Partition
+    Partition 1       3         1         2         3
+    v                 v         v         v         v
+   [(PRIMARY)(PRIMARY)(PRIMARY){(LOGICAL){(LOGICAL){(LOGICAL)}}}]
+   ^         ^                 ^         ^         ^
+   Drive     Primary           Extended  Extended  Extended
+   Start     Partition 2       Partition Partition Partition
+                              1         2         3
+
+     Partition  | Size |  Relative | To   | Absolute | Linux
+     Type       |      |  Offset   | What | Offset   | ID
+   ---------+---+------+-----------+------+----------+-------
+   Primary  | 1 |  1GB |    0GB    |  DS  |   0GB    | hda1
+   Primary  | 2 |  1GB |    1GB    |  DS  |   1GB    | hda2
+   Primary  | 3 |  1GB |    2GB    |  DS  |   2GB    | hda3
+   Extended | 1 |  1GB |    3GB    |  DS  |   3GB    | ---
+   Logical  | 1 |  1GB |    0GB    | Ext1 |   3GB    | hda5
+   Extended | 2 |  1GB |    1GB    | Ext1 |   3GB    | ---
+   Logical  | 2 |  1GB |    0GB    | Ext2 |   4GB    | hda6
+   Extended | 3 |  1GB |    2GB    | Ext1 |   4GB    | ---
+   Logical  | 3 |  1GB |    0GB    | Ext3 |   5GB    | hda7
+
+   Note hda4 is not assigned, this would go to the fourth
+   primary partition (if there was no extended partition).
+
+   Here the partitions are nicely laid out, however, there is
+   no guarantee that Primary 1 points to the partition closest
+   to the start of the disk.  There is nothing stipulating which
+   two slots in the extended partitions are used, only that up
+   to two are used.  There can be extended partitions with less
+   then three primary partitions.
+   
+   Also note that an extended partition cannot contain a
+   primary partition.  */
+
+/* Scan DEVICE for a partition table.  Generate a partition
+   table list in P_TABLE.  */
+error_t
+partition_table_scan (struct partition_table **p_table,
+                     error_t (*read_block) (off_t offset, void **data,
+                                            void *cookie),
+                     void *cookie,
+                     void (*free_block) (void *data))
+{
+#define MBR() (offset == 0)
+
+  auto error_t pcbios_table_scan (struct pcbios_table *, size_t offset);
+  auto error_t bsd_table_scan (struct bsd_table *, size_t offset);
+
+  error_t
+  table_scan (size_t offset)
+    {
+      error_t err;
+      void *mbr;
+
+      err = read_block (offset, &mbr, cookie);
+      if (err)
+        return err;
+
+      err = bsd_table_scan (mbr, offset);
+      if (err == 0)
+       goto out;
+
+      err = pcbios_table_scan (mbr, offset);
+      if (err == 0)
+       goto out;
+
+      if (MBR ())
+       error (0, err = EINVAL, "MBR has a bad signature.\n");
+      else
+       {
+         error (0, EINVAL, "Warning: invalid extended partition table "
+                "signature at sector %d (%dMB).\n", offset,
+                BLOCK_TO_MB (offset, SECTOR_SIZE));
+         err = 0;
+       }
+
+     out:
+      free_block (mbr);
+
+      return err;
+    }
+
+  size_t primary_extended_offset = 0;
+
+  error_t
+  pcbios_table_scan (struct pcbios_table *table, size_t offset)
+    {
+      error_t err;
+      int i;
+      int extended_count = 0;
+      int logical_count = 0;
+      int valid_partitions = 0;
+
+      int found_extended = 0;
+      size_t extended_offset = 0;
+
+      if (! PC_MBR_CHECK_SIG (table))
+       return EINVAL;
+
+      for (i = 0; i < 4; i ++)
+       {
+         int type = PC_SLICE_TYPE (table, i);
+         int extended = IS_PC_SLICE_TYPE_EXTENDED (type)
+                        || IS_PC_SLICE_TYPE_BSD (type);
+         /* A non-valid_type would be free space (any patition with
+            a type of zero.  */
+         int valid_type = ((type & ~PC_SLICE_TYPE_HIDDEN_FLAG)
+                           != PC_SLICE_TYPE_NONE);
+
+         if (valid_type)
+           {
+             valid_partitions ++;
+             if (extended)
+               extended_count ++;
+             else
+               logical_count ++;
+           }
+
+
+         if (extended_count > 1)
+           {
+             error (0, EINVAL, "Multiple extended partitions in the "
+                               "same partition table record.\n");
+             return EINVAL;
+           }
+
+         if (! MBR () && logical_count > 1)
+           {
+             error (0, EINVAL, "Multiple logical partitions in the "
+                               "same partition table record.\n");
+             return EINVAL;
+           }
+
+         if (! MBR () && PC_SLICE_LENGTH (table, i) == 0)
+           /* One of the two unused slots in an extended partition.  */
+           continue;
+
+         err = partition_register (*p_table, MBR (),
+                                   PC_SLICE_LENGTH (table, i),
+                                   PC_SLICE_START (table, i)
+                                   + (extended ? primary_extended_offset
+                                     : offset),
+                                   ! extended && valid_type,
+                                   DISKPART_TYPE_PCBIOS, type);
+         if (err)
+           return err;
+
+         /* If this is an extended partition, then we save its offset
+            and recurse at the end of the scan.  */
+         if (extended)
+           {
+             found_extended = 1;
+
+             if (MBR ())
+               extended_offset = primary_extended_offset
+                 = PC_SLICE_START (table, i);
+             else
+               extended_offset = primary_extended_offset
+                                 + PC_SLICE_START (table, i);
+
+             if (IS_PC_SLICE_TYPE_BSD (type))
+               extended_offset += BSD_LABEL_SECTOR;
+           }
+       }
+
+      if (found_extended)
+       table_scan (extended_offset);
+
+      return 0;
+    }
+
+  error_t
+  bsd_table_scan (struct bsd_table *table, size_t offset)
+    {
+      int i;
+      error_t err;
+
+      if (! BSD_LABEL_CHECK_MAG (table))
+       return EINVAL;
+
+      for (i = 0; i < BSD_LABEL_NPARTS (table); i ++)
+       {
+         int type = BSD_PART_TYPE (table, i);
+
+         err = partition_register (*p_table, MBR (),
+                                   (type == FS_UNUSED ? 0
+                                    : BSD_PART_LENGTH (table, i)),
+                                   BSD_PART_START (table, i),
+                                   type != FS_UNUSED,
+                                   DISKPART_TYPE_BSD, type);
+         if (err)
+           return err;
+       }
+
+      return 0;
+    }
+
+  error_t err;
+
+  err = partition_table_new (p_table);
+  if (err)
+    return err;
+
+  /* Start with the MBR.  */
+  return table_scan (0);
+}
+
+/* Determine what the partition thinks the geomentry is.  All partitions
+   should have the same ending head and sector (in fact, they should
+   also have the same starting head and sector);  The start and end of a
+   partition is really measured by the cylinder.
+
+   Thus, scan PARTITION_RECORD and compare the ending head and sector
+   for all valid partitions.  If they match, we have what the partition
+   table thinks the drives geomentry is.  The data is returned in a
+   malloced chs (with the cylinders set to zero), otherwise, NULL is
+   returned.  */
+error_t
+partition_table_geometry (void *block,
+                         struct chs *global_part)
+{
+  int i;
+  struct chs local_part = {0, 0, 0};
+  int found_one = 0;
+  int invalid = 0;
+  struct pcbios_table *partition_table = block;
+
+  for (i = 0; i < 4; i ++)
+    {
+      if (PC_SLICE_TYPE (partition_table, i) != PC_SLICE_TYPE_NONE)
+       {
+         local_part.heads = PC_SLICE_EHEAD (partition_table, i) + 1;
+         local_part.sectors = PC_SLICE_ESEC (partition_table, i);
+         if (! found_one)
+           {
+             found_one = 1;
+             memcpy (global_part, &local_part, sizeof (struct chs));
+           }
+         else if (memcmp (&local_part, global_part,
+                  sizeof (struct chs)) != 0)
+           invalid = 1;
+       }
+    }
+
+  if (found_one && ! invalid)
+    return 0;
+  else
+    return EINVAL;
+}
diff --exclude=CVS -ur --new-file hurd/libdiskpart/diskpart.h 
hurd-new/libdiskpart/diskpart.h
--- hurd/libdiskpart/diskpart.h Wed Dec 31 19:00:00 1969
+++ hurd-new/libdiskpart/diskpart.h     Mon Jan 15 20:15:13 2001
@@ -0,0 +1,144 @@
+/* Partition table frobbing routines.
+
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+ 
+   This file is part of the GNU Hurd.
+ 
+   The GNU Hurd 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, or (at
+   your option) any later version.
+ 
+   The GNU Hurd 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.  */
+
+#ifndef HURD_DISKPART_H
+#define HURD_DISKPART_H
+
+#include <error.h>
+
+/* cylinder/head/sector triples.  */
+struct chs
+{
+  int cylinders;
+  int heads;
+  int sectors;
+};
+
+/* Normally filled in via partition_table_scan.  */
+struct partition
+{
+  int primary;         /* Primary partition (i.e. in the MBR). */
+  size_t size;         /* Size in blocks.  */
+  size_t offset;       /* Offset in blocks.  */
+  int do_export;       /* If we should export the partition.  */
+  int major_type;      /* Partition type.  */
+  int minor_type;
+
+  int id;              /* The slice number.  This is filled in
+                          automatically when the partition is
+                          registered via partition_register.  */
+};
+
+/* Partition major types.  */
+#define DISKPART_TYPE_PCBIOS   0
+#define DISKPART_TYPE_BSD      1
+
+/* PC BIOS minor types.  */
+#define DISKPART_TYPE_PCBIOS_NONE              0
+#define DISKPART_TYPE_PCBIOS_FAT12             1
+#define DISKPART_TYPE_PCBIOS_FAT16_LT32M       4
+#define DISKPART_TYPE_PCBIOS_EXTENDED          5
+#define DISKPART_TYPE_PCBIOS_FAT16_GT32M       6
+#define DISKPART_TYPE_PCBIOS_FAT32             0xb
+#define DISKPART_TYPE_PCBIOS_FAT32_LBA         0xc
+#define DISKPART_TYPE_PCBIOS_FAT16_LBA         0xe
+#define DISKPART_TYPE_PCBIOS_WIN95_EXTENDED    0xf
+#define DISKPART_TYPE_PCBIOS_EZD               0x55
+#define DISKPART_TYPE_PCBIOS_MINIX             0x80
+#define DISKPART_TYPE_PCBIOS_LINUX_MINIX       0x81
+#define DISKPART_TYPE_PCBIOS_EXT2FS            0x83
+#define DISKPART_TYPE_PCBIOS_LINUX_EXTENDED    0x85
+
+/* If the partition is hidden.  Or'ed with any of the above
+   types.  */
+#define DISKPART_TYPE_PCBIOS_HIDDEN_FLAG       0x10
+
+/* BSD minor types.  */
+#define        DISKPART_TYPE_BSD_UNUSED     0  /* unused */
+#define        DISKPART_TYPE_BSD_SWAP       1  /* swap */
+#define        DISKPART_TYPE_BSD_V6         2  /* Sixth Edition */
+#define        DISKPART_TYPE_BSD_V7         3  /* Seventh Edition */
+#define        DISKPART_TYPE_BSD_SYSV       4  /* System V */
+#define        DISKPART_TYPE_BSD_V71K       5  /* V7 with 1K blocks (4.1, 2.9) 
*/
+#define        DISKPART_TYPE_BSD_V8         6  /* Eighth Edition, 4K blocks */
+#define        DISKPART_TYPE_BSD_BSDFFS     7  /* 4.2BSD fast file system */
+#define        DISKPART_TYPE_BSD_MSDOS      8  /* MSDOS file system */
+#define        DISKPART_TYPE_BSD_BSDLFS     9  /* 4.4BSD log-structured file 
system */
+#define        DISKPART_TYPE_BSD_OTHER     10  /* in use, but 
unknown/unsupported */
+#define        DISKPART_TYPE_BSD_HPFS      11  /* OS/2 high-performance file 
system */
+#define        DISKPART_TYPE_BSD_ISO9660   12  /* ISO 9660, normally CD-ROM */
+#define        DISKPART_TYPE_BSD_BOOT      13  /* partition contains bootstrap 
*/
+#define        DISKPART_TYPE_BSD_ADOS      14  /* AmigaDOS fast file system */
+#define        DISKPART_TYPE_BSD_HFS       15  /* Macintosh HFS */
+#define        DISKPART_TYPE_BSD_FILECORE  16  /* Acorn Filecore Filing System 
*/
+#define        DISKPART_TYPE_BSD_EXT2FS    17  /* Linux Extended 2 file system 
*/
+
+/* Forward declaration.  */
+struct partition_table;
+
+/* Allocate an emtpy partition table in P_TABLE.  */
+error_t
+partition_table_new (struct partition_table **p_table);
+
+/* Release the resources associated with P_TABLE.  */
+error_t
+partition_table_free (struct partition_table *p_table);
+
+/* Add a partition to P_TABLE; this is normally done automatically by
+   partition_table_scan.  */
+error_t
+partition_register (struct partition_table *p_table, int primary,
+                   size_t size, off_t offset, int do_export,
+                   int major_type, int minor_type);
+
+/* Iterate over P_TABLE calling func on each partition.  If the function
+   ever returns non-zero, the iteration stops immediately and returns
+   that value.  */
+error_t
+partition_table_iterate (struct partition_table *p_table,
+                        error_t (*func)(struct partition *, void *),
+                        void *cookie);
+
+/* Scan a device and fill P_TABLE with what is found.  READ_BLOCK
+   is used to read a block at the given offset.  The block size
+   must be 512 bytes.  The block will be deallocated by FREE_BLOCK.  */
+error_t
+partition_table_scan (struct partition_table **p_table,
+                     error_t (*read_block) (off_t offset, void **data,
+                                            void *cookie),
+                     void *cookie,
+                     void (*free_block) (void *data));
+
+/* Determine what a partition thinks the geomentry is.  By definition,
+   All partitions should have the same ending head and sector (in fact,
+   they should also have the same starting head and sector);  The start
+   and end of a partition is really measured by the cylinder.
+ 
+   Thus, scan PARTITION_RECORD and compare the ending head and sector for
+   all valid partitions.  If they match, we have what the partition table
+   thinks the drives geomentry is.  The heads and sectors are returned
+   in via GEOMETRY (cylinders is set to zero).  */
+error_t
+partition_table_geometry (void *partition_record,
+                         struct chs *geometry);
+
+#endif /* HURD_DISKPART_H */
diff --exclude=CVS -ur --new-file hurd/libdiskpart/pc_slice.h 
hurd-new/libdiskpart/pc_slice.h
--- hurd/libdiskpart/pc_slice.h Wed Dec 31 19:00:00 1969
+++ hurd-new/libdiskpart/pc_slice.h     Mon Jan 15 18:11:43 2001
@@ -0,0 +1,278 @@
+/*
+ *  Copyright (C) 1996   Erich Boleyn  <erich@uruk.org>
+ *  Copyright (C) 1999, 2000, 2001   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.
+ */
+
+#ifndef PC_SLICE_H
+#define PC_SLICE_H
+
+#include <sys/types.h>
+
+/* These define the basic PC MBR sector characteristics.  The data
+   structures should not be accessed directly, rather, only throught
+   the macros as one must consider endianness (which we do not yet
+   do).  */
+
+/* A partition table is exactly 512 bytes and has the following structual
+   layout (values are in bytes):
+ 
+   Offset:  0                     446                         510  512
+   Size:    |        446          | 16     16     16     16   | 2  |
+   Layout:  [        CODE        ][PART1][PART2][PART3][PART4][SIG]  */
+
+struct pcbios_partition                /* Layout of a partition.  An entry is 
16
+                                  bytes long.  */
+{
+  u_int8_t active;             /* When bit 7 is set, the is partition is
+                                  active (i.e. the boot partition).  */
+  u_int8_t start_head;         /* Starting head of the partition.  */
+  u_int16_t start_cyl_sect;    /* Starting sector/cylinder of the partition.
+                                  Recall, this is packed.
+                                  [111111          ]
+                                  [5432109876543210]
+                                  Cylinder: Bits 7-6,15-8
+                                  Sector: Bits 6-0 */
+  u_int8_t type;               /* The partition type (e.g. fat, ext2, etc) */
+  u_int8_t end_head;           /* The ending head of the partition.  */
+  u_int16_t end_cyl_sect;      /* Ending sector/cylinder of the partition.
+                                  C.f. start_cyl_sect */
+  u_int32_t start_lba;         /* The start in LBA format.  */
+  u_int32_t size;              /* Size of partition in sectors.  */
+} __attribute__ ((packed));
+
+struct pcbios_table
+{
+  u_int8_t program[446];       /* Boot code. Starts at offset 0.  */
+  struct pcbios_partition partition[4];        /* The 4 partition table 
entries.
+                                  Starts at offset 446.  */
+  u_int16_t sig;               /* Signature (0x55AA). Starts at offset 510. */
+} __attribute__ ((packed));    /* Be very sure of the structure. */
+
+#define PC_MBR_SECTOR  0
+
+#define PC_MBR_SIG_OFFSET  510
+#define PC_MBR_SIGNATURE   0xaa55
+
+#define PC_SLICE_OFFSET 446
+#define PC_SLICE_MAX    4
+
+/* Defines as this structure should not be exposed (there are endian
+   problems).  */
+
+#define PC_MBR_CHECK_SIG(mbr) \
+  ((mbr)->sig == PC_MBR_SIGNATURE )
+
+#define PC_MBR_SIG(mbr) \
+  ((mbr)->sig)
+
+#define PC_SLICE_FLAG(mbr, part) \
+  ((mbr)->partition[(part)].active)
+
+#define PC_SLICE_HEAD(mbr, part) \
+  ((mbr)->partition[(part)].start_head)
+
+#define PC_SLICE_SEC(mbr, part) \
+  ((mbr)->partition[(part)].start_cyl_sect & 0x3F)
+
+#define PC_SLICE_CYL(mbr, part) \
+  ((((mbr)->partition[(part)].start_cyl_sect & 0xC0) << 2) \
+   | (((mbr)->partition[(part)].start_cyl_sect & 0xFF00) >> 8))
+
+#define PC_SLICE_TYPE(mbr, part) \
+  ((mbr)->partition[(part)].type)
+
+#define PC_SLICE_EHEAD(mbr, part) \
+  ((mbr)->partition[(part)].end_head)
+
+#define PC_SLICE_ESEC(mbr, part) \
+  ((mbr)->partition[(part)].end_cyl_sect & 0x3F)
+
+#define PC_SLICE_ECYL(mbr, part) \
+  ((((mbr)->partition[(part)].end_cyl_sect & 0xC0) << 2) \
+   | (((mbr)->partition[(part)].end_cyl_sect & 0xFF00) >> 8))
+
+#define PC_SLICE_START(mbr, part) \
+  ((mbr)->partition[(part)].start_lba)
+
+#define PC_SLICE_LENGTH(mbr, part) \
+  ((mbr)->partition[(part)].size)
+
+/* PC flag types are defined here.  */
+
+#define PC_SLICE_FLAG_NONE      0
+#define PC_SLICE_FLAG_BOOTABLE  0x80
+
+/* Known PC partition types are defined here.  */
+
+/* This is not a flag actually, but used as if it were a flag.  */
+#define PC_SLICE_TYPE_HIDDEN_FLAG      0x10
+
+#define PC_SLICE_TYPE_NONE             0
+#define PC_SLICE_TYPE_FAT12            1
+#define PC_SLICE_TYPE_FAT16_LT32M      4
+#define PC_SLICE_TYPE_EXTENDED         5
+#define PC_SLICE_TYPE_FAT16_GT32M      6
+#define PC_SLICE_TYPE_FAT32            0xb
+#define PC_SLICE_TYPE_FAT32_LBA                0xc
+#define PC_SLICE_TYPE_FAT16_LBA                0xe
+#define PC_SLICE_TYPE_WIN95_EXTENDED   0xf
+#define PC_SLICE_TYPE_EZD              0x55
+#define PC_SLICE_TYPE_MINIX            0x80
+#define PC_SLICE_TYPE_LINUX_MINIX      0x81
+#define PC_SLICE_TYPE_EXT2FS           0x83
+#define PC_SLICE_TYPE_LINUX_EXTENDED   0x85
+
+/* For convinience.  */
+/* Check if TYPE is a FAT partition type. Clear the hidden flag before
+   the check, to allow the user to mount a hidden partition in GRUB.  */
+#define IS_PC_SLICE_TYPE_FAT(type)     \
+  ({ int _type = (type) & ~PC_SLICE_TYPE_HIDDEN_FLAG; \
+     _type == PC_SLICE_TYPE_FAT12 \
+     || _type == PC_SLICE_TYPE_FAT16_LT32M \
+     || _type == PC_SLICE_TYPE_FAT16_GT32M \
+     || _type == PC_SLICE_TYPE_FAT16_LBA \
+     || _type == PC_SLICE_TYPE_FAT32 \
+     || _type == PC_SLICE_TYPE_FAT32_LBA; })
+
+#define IS_PC_SLICE_TYPE_EXTENDED(type)        \
+  (((type) == PC_SLICE_TYPE_EXTENDED)  \
+   || ((type) == PC_SLICE_TYPE_WIN95_EXTENDED) \
+   || ((type) == PC_SLICE_TYPE_LINUX_EXTENDED))
+
+#define IS_PC_SLICE_TYPE_MINIX(type) \
+  (((type) == PC_SLICE_TYPE_MINIX)     \
+   || ((type) == PC_SLICE_TYPE_LINUX_MINIX))
+
+/* these ones are special, as they use their own partitioning scheme
+   to subdivide the PC partitions from there.  */
+#define PC_SLICE_TYPE_FREEBSD          0xa5
+#define PC_SLICE_TYPE_OPENBSD          0xa6
+#define PC_SLICE_TYPE_NETBSD           0xa9
+
+/* For convenience.  */
+#define IS_PC_SLICE_TYPE_BSD_WITH_FS(type,fs)  \
+  ((type) == (PC_SLICE_TYPE_FREEBSD | ((fs) << 8)) \
+   || (type) == (PC_SLICE_TYPE_OPENBSD | ((fs) << 8)) \
+   || (type) == (PC_SLICE_TYPE_NETBSD | (fs) << 8))
+
+#define IS_PC_SLICE_TYPE_BSD(type)     IS_PC_SLICE_TYPE_BSD_WITH_FS(type,0)
+
+/* *BSD-style disklabel and partition definitions.
+
+   This is a subdivided slice of type 'PC_SLICE_TYPE_BSD', so all of
+   these, except where noted, are relative to the slice in question.  */
+
+#define BSD_LABEL_SECTOR 1
+#define BSD_LABEL_MAGIC  0x82564557
+
+#define BSD_LABEL_MAG_OFFSET 0
+#define BSD_LABEL_MAG2_OFFSET 132
+#define BSD_LABEL_NPARTS_OFFSET 138
+
+#define BSD_PART_OFFSET 148
+#define BSD_LABEL_NPARTS_MAX 8
+
+struct bsd_partition
+{
+  u_int32_t size;              /* Number of sectors in the partition . */
+  u_int32_t start;             /* Starting sector.  */
+  u_int32_t fsize;             /* Filesystem fragment size.  */
+  u_int8_t fstype;             /* Filesystem type, see below.  */
+  u_int8_t frag;               /* Filesystem fragments per block.  */
+  union {
+    u_int16_t cpg;             /* UFS: FS cylinders per group.  */
+    u_int16_t sgs;             /* LFS: FS segment shift.  */
+  } __attribute__ ((packed)) __partition_u1;
+} __attribute__ ((packed));
+
+struct bsd_table
+{
+  u_int32_t magic;             /* Disklabel signature.  */
+  u_int16_t d_type;            /* Drive type.  */
+  u_int16_t d_subtype;
+  char dummy[124];
+  u_int32_t magic2;            /* Signature again.  */
+  char dummy2[2];
+  u_int16_t partition_count;   /* Number of partitions in the label.  */
+  char dummy3[8];
+  struct bsd_partition partition[BSD_LABEL_NPARTS_MAX];
+} __attribute__ ((packed));
+
+/* Defines as this structure should not be exposed (there are endian
+   problems).  */
+
+#define BSD_LABEL_CHECK_MAG(table) \
+  ((table)->magic == BSD_LABEL_MAGIC && (table)->magic2 == BSD_LABEL_MAGIC)
+
+#define BSD_LABEL_DTYPE(table) \
+  ((table)->d_type)
+
+#define BSD_LABEL_NPARTS(table) \
+  ((table)->partition_count)
+
+#define BSD_PART_LENGTH(table, part) \
+  ((table)->partition[(part)].size)
+
+#define BSD_PART_START(table, part) \
+  ((table)->partition[(part)].start)
+
+#define BSD_PART_FRAG_SIZE(table, part) \
+  ((table)->partition[(part)].fsize)
+
+#define BSD_PART_TYPE(table, part) \
+  ((table)->partition[(part)].fstype)
+
+#define BSD_PART_FRAGS_PER_BLOCK(table, part) \
+  ((table)->partition[(part)].frag)
+
+#define BSD_PART_EXTRA(table, part) \
+  ((table)->partition[(part)].__partition_u1)
+
+/* possible values for the "DISKTYPE"... all essentially irrelevant
+   except for DTYPE_SCSI */
+#define DTYPE_SMD               1      /* SMD, XSMD; VAX hp/up */
+#define DTYPE_MSCP              2      /* MSCP */
+#define DTYPE_DEC               3      /* other DEC (rk, rl) */
+#define DTYPE_SCSI              4      /* SCSI */
+#define DTYPE_ESDI              5      /* ESDI interface */
+#define DTYPE_ST506             6      /* ST506 etc. */
+#define DTYPE_HPIB              7      /* CS/80 on HP-IB */
+#define DTYPE_HPFL              8      /* HP Fiber-link */
+#define DTYPE_FLOPPY            10     /* floppy */
+
+/* possible values for the *BSD-style partition type */
+#define FS_UNUSED       0       /* unused */
+#define FS_SWAP         1       /* swap */
+#define FS_V6           2       /* Sixth Edition */
+#define FS_V7           3       /* Seventh Edition */
+#define FS_SYSV         4       /* System V */
+#define FS_V71K         5       /* V7 with 1K blocks (4.1, 2.9) */
+#define FS_V8           6       /* Eighth Edition, 4K blocks */
+#define FS_BSDFFS       7       /* 4.2BSD fast file system */
+#define FS_MSDOS        8       /* MSDOS file system */
+#define FS_BSDLFS       9       /* 4.4BSD log-structured file system */
+#define FS_OTHER        10      /* in use, but unknown/unsupported */
+#define FS_HPFS         11      /* OS/2 high-performance file system */
+#define FS_ISO9660      12      /* ISO 9660, normally CD-ROM */
+#define FS_BOOT         13      /* partition contains bootstrap */
+#define FS_ADOS         14      /* AmigaDOS fast file system */
+#define FS_HFS          15      /* Macintosh HFS */
+#define FS_FILECORE     16      /* Acorn Filecore Filing System */
+#define FS_EXT2FS       17      /* Linux Extended 2 file system */
+
+
+#endif /* PC_SLICE_H */
diff --exclude=CVS -ur --new-file hurd/diskpart/ChangeLog 
hurd-new/diskpart/ChangeLog
--- hurd/diskpart/ChangeLog     Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/ChangeLog Mon Jan 15 21:18:34 2001
@@ -0,0 +1,9 @@
+2000-01-15  Neal H Walfield   <neal@cs.uml.edu>
+
+       * diskpart.c: New file.
+       * disknode.c: Likewise.
+       * disknode.h: Likewise.
+       * ops.c: Likewise.
+       * consts.c: Likewise.
+       * stubs.c: Likewise.
+       * Makefile: Likewise.
diff --exclude=CVS -ur --new-file hurd/diskpart/Makefile 
hurd-new/diskpart/Makefile
--- hurd/diskpart/Makefile      Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/Makefile  Mon Jan 15 20:56:00 2001
@@ -0,0 +1,30 @@
+#   Copyright (C) 2001 Free Software Foundation
+#
+#   Written by Neal H Walfield <neal@cs.uml.edu>
+#
+#   This file is part of the GNU Hurd.
+#
+#   The GNU Hurd 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, or (at
+#   your option) any later version.
+#
+#   The GNU Hurd 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.
+
+dir := diskpart
+makemode := server
+
+target = diskpart
+LCLHDRS = disknode.h
+SRCS = diskpart.c disknode.c ops.c consts.c stubs.c
+OBJS = $(subst .c,.o,$(SRCS))
+HURDLIBS = diskpart netfs iohelp fshelp store threads ports
+
+include ../Makeconf
diff --exclude=CVS -ur --new-file hurd/diskpart/consts.c 
hurd-new/diskpart/consts.c
--- hurd/diskpart/consts.c      Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/consts.c  Mon Jan 15 22:26:22 2001
@@ -0,0 +1,27 @@
+/* Netfs constants.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+
+/* Maximum number of times to follow symbolic links before returning
+   ELOOP.  */
+int netfs_maxsymlinks = 8;
+
diff --exclude=CVS -ur --new-file hurd/diskpart/disknode.c 
hurd-new/diskpart/disknode.c
--- hurd/diskpart/disknode.c    Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/disknode.c        Mon Jan 15 22:26:32 2001
@@ -0,0 +1,146 @@
+/* Netfs netnode.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+#define _GNU_SOURCE 1
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <hurd/netfs.h>
+
+#include "disknode.h"
+
+/* The 0th node is the root node.  The rest at the partition ids.
+   Nodes may be 0 is there is no partition acording to that slice.  */
+struct node **disk_node;
+/* Number of partitions.  Partition nodes start at 1, thus there are
+   really disk_node_count + 1 (the root) elements in the array.  */
+int disk_node_count;
+
+volatile struct mapped_time_value *mapped_time;
+
+error_t
+build_disk_nodes (struct partition_table *p_table)
+{
+  int allocated = 0;
+
+  struct stat node_stat =
+    {
+      st_fsid: getpid (),
+      st_fstype: FSTYPE_MISC,
+      st_gen: 0,
+      st_flags: 0,
+      st_mode: 0 | S_IFREG,
+      st_nlink: 1,
+      st_uid: 0,
+      st_gid: 0,
+      st_size: 0
+    };
+
+  error_t
+  func (struct partition *p, void *cookie)
+    {
+      struct netnode *dn;
+
+      if (p->do_export)
+       {
+         if (p->id >= allocated)
+           {
+             allocated += 10;
+             disk_node = realloc (disk_node,
+                                  sizeof (struct netnode *) * allocated);
+             if (! disk_node)
+               return ENOMEM;
+           }
+
+         /* Void empty entries.  */
+         for (disk_node_count ++; disk_node_count < p->id;
+              disk_node_count ++)
+           disk_node[disk_node_count] = NULL;
+
+         dn = malloc (sizeof (struct netnode));
+         if (! dn)
+           return ENOMEM;
+
+         dn->partition = p;
+         dn->type = NODE_PARTITION;
+
+         disk_node[p->id] = netfs_make_node (dn);
+
+         disk_node[p->id]->nn_stat = node_stat;
+         disk_node[p->id]->nn_stat.st_ino = disk_node_count;
+       }
+
+      return 0;
+    }
+
+  error_t err;
+
+  /* We must initialize this to NULL as we are going realloc it.  */
+  disk_node = NULL;
+  disk_node_count = 0;
+
+  fshelp_touch (&node_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME,
+               mapped_time);
+
+  err = partition_table_iterate (p_table, func, NULL);
+  if (err)
+    return err;
+
+  return 0;
+}
+
+struct node *
+make_root_node (void)
+{
+  struct netnode *dn;
+
+  struct stat node_stat =
+    {
+      st_fsid: getpid (),
+      st_fstype: FSTYPE_MISC,
+      st_gen: 0,
+      st_flags: 0,
+      st_mode: S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR,
+      st_nlink: 1,
+      st_uid: 0,
+      st_gid: 0,
+      st_size: 0,
+      st_ino: 0
+    };
+
+  dn = malloc (sizeof (struct netnode));
+  if (! dn)
+    return NULL;
+
+  dn->type = NODE_ROOT;
+  dn->partition = NULL;
+
+  disk_node[0] = netfs_make_node (dn);
+
+  fshelp_touch (&node_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME,
+               mapped_time);
+
+  disk_node[0]->nn_stat = node_stat;
+
+  return disk_node[0];
+}
diff --exclude=CVS -ur --new-file hurd/diskpart/disknode.h 
hurd-new/diskpart/disknode.h
--- hurd/diskpart/disknode.h    Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/disknode.h        Mon Jan 15 22:26:44 2001
@@ -0,0 +1,49 @@
+/* Netfs netnode.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+#ifndef DISK_NODE_H
+#define DISK_NODE_H
+
+#include <hurd/diskpart.h>
+
+struct netnode
+{
+  enum
+    {
+      NODE_ROOT,
+      NODE_PARTITION
+    } type;                            /* The node type.  */
+  struct partition *partition;         /* The partition this node is
+                                          representing.  */
+};
+
+extern struct node **disk_node;
+extern int disk_node_count;
+
+/* Fill disk_node from P_TABLE.  */
+error_t
+build_disk_nodes (struct partition_table *p_table);
+
+struct node *
+make_root_node (void);
+
+#endif /* DISK_NODE_H */
diff --exclude=CVS -ur --new-file hurd/diskpart/diskpart.c 
hurd-new/diskpart/diskpart.c
--- hurd/diskpart/diskpart.c    Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/diskpart.c        Mon Jan 15 22:26:52 2001
@@ -0,0 +1,164 @@
+/* Main.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <error.h>
+#include <argp.h>
+
+#include <maptime.h>
+#include <hurd/netfs.h>
+#include <hurd/store.h>
+#include <hurd/diskpart.h>
+#include <mach.h>
+
+#include "disknode.h"
+
+static char *args_doc = "DEVICE";
+static char *doc = "Hurd disk partition translator "
+                  "DEVICE is a kernel device.";
+
+static char *kernel_device_name /* = NULL */;
+struct store *kernel_device_store;
+
+volatile struct mapped_time_value *mapped_time;
+
+static error_t
+parse_options (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case ARGP_KEY_ARG:
+      if (kernel_device_name)
+       argp_usage (state);
+      else
+       kernel_device_name = arg;
+      break;
+
+    case ARGP_KEY_END:
+      if (! kernel_device_name)
+       argp_error (state, "No device specified");
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  error_t err;
+
+  mach_port_t bootstrap;
+  struct partition_table *p_table;
+
+  struct argp_child argp_children[] =
+    { {&netfs_std_startup_argp}, {0} };
+  struct argp argp =
+    { NULL, parse_options, args_doc, doc, argp_children };
+
+  argp_parse (&argp, argc, argv, 0, NULL, NULL);
+
+  task_get_bootstrap_port (mach_task_self (), &bootstrap);
+  netfs_init ();
+
+  err = maptime_map (0, 0, &mapped_time);
+  if (err)
+    error (1, errno, "mapping time");
+
+  /* Read the table.  */
+  {
+    device_t device;
+    mach_port_t master_device_port;
+    size_t sector_size;
+
+    error_t
+    block_read (off_t offset, void **data, void *cookie)
+      {
+       error_t err;
+       size_t amount;
+
+       err = device_read (device, 0, offset, sector_size,
+                          (io_buf_ptr_t *)data, &amount);
+       if (amount != sector_size)
+         err = EIO;
+
+       return err;
+      }
+
+    void
+    free_block (void *data)
+      {
+       vm_deallocate (mach_task_self (), (vm_address_t) data,
+                      sector_size);
+      }
+
+    err = get_privileged_ports (NULL, &master_device_port);
+    if (err)
+      error (1, err, "get_privileged_ports");
+
+    err = device_open (master_device_port, D_READ, kernel_device_name,
+                      &device);
+    if (err) 
+      error (1, err, "opening %s", kernel_device_name);
+
+    {
+      size_t sizes[DEV_GET_SIZE_COUNT];
+      size_t sizes_len = DEV_GET_SIZE_COUNT;
+
+      err = device_get_status (device, DEV_GET_SIZE, sizes, &sizes_len);
+      if (err)
+       error (1, err, "sizing %s", kernel_device_name);
+
+      sector_size = sizes[DEV_GET_SIZE_RECORD_SIZE];
+      assert (sector_size == 512);
+    }
+
+    err = partition_table_scan (&p_table, block_read, NULL, free_block);
+    if (err)
+      error (1, err, "partition_table_scan");
+
+    device_close (device);
+    mach_port_deallocate (mach_task_self (), master_device_port);
+  }
+
+  /* Build the file system nodes from the partition table.  */
+  err = build_disk_nodes (p_table);
+  if (err)
+    error (1, err, "building file system");
+
+  /* Create a base store. The root is this and partitions remap this.  */
+  err = store_device_open (kernel_device_name, 0, &kernel_device_store);
+  if (err)
+    error (1, err, "store_device_open");
+
+  netfs_root_node = make_root_node ();
+  if (! netfs_root_node)
+    return 1;
+
+  netfs_startup (bootstrap, 0);
+
+  for (;;)
+    netfs_server_loop ();
+}
diff --exclude=CVS -ur --new-file hurd/diskpart/ops.c hurd-new/diskpart/ops.c
--- hurd/diskpart/ops.c Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/ops.c     Mon Jan 15 22:27:04 2001
@@ -0,0 +1,323 @@
+/* Netfs call backs.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <maptime.h>
+#include <hurd/diskpart.h>
+#include <hurd/fshelp.h>
+#include <hurd/netfs.h>
+#include <hurd/hurd_types.h>
+#include <hurd/store.h>
+
+#include "disknode.h"
+
+extern struct store *kernel_device_store;
+
+extern volatile struct mapped_time_value *mapped_time;
+
+/* The user must define this function.  Node NP has no more references;
+   free all its associated storage. */
+void netfs_node_norefs (struct node *np)
+{
+  assert (! "No references to node; Impossible!");
+}
+
+/* The user must define this function.  This should attempt a utimes
+   call for the user specified by CRED on locked node NP, to change
+   the atime to ATIME and the mtime to MTIME.  If ATIME or MTIME is
+   null, then set to the current time.  */
+error_t
+netfs_attempt_utimes (struct iouser *cred, struct node *np,
+                     struct timespec *atime, struct timespec *mtime)
+{
+  error_t err;
+  int flags;
+  
+  err = fshelp_isowner (&np->nn_stat, cred);
+  if (err)
+    return err;
+
+  if (mtime)
+    {
+      np->nn_stat.st_mtime = mtime->tv_sec;
+      np->nn_stat.st_mtime_usec = mtime->tv_nsec / 1000;
+    }
+
+  if (atime)
+    {
+      np->nn_stat.st_atime = atime->tv_sec;
+      np->nn_stat.st_atime_usec = atime->tv_nsec / 1000;
+    }
+
+  flags = (mtime ? 0 : TOUCH_MTIME) | (atime ? 0 : TOUCH_ATIME);
+  if (flags)
+    fshelp_touch (&np->nn_stat, flags, mapped_time);
+
+  return 0;
+}
+
+/* The user must define this function.  Make sure that NP->nn_stat is
+   filled with the most current information.  CRED identifies the user
+   responsible for the operation. NP is locked.  */
+error_t
+netfs_validate_stat (struct node *np, struct iouser *cred)
+{
+  return 0;
+}
+
+/* The user must define this function.  This should attempt to fetch
+   filesystem status information for the remote filesystem, for the
+   user CRED. NP is locked.  */
+error_t
+netfs_attempt_statfs (struct iouser *cred, struct node *np,
+                     struct statfs *st)
+{
+  st->f_bsize = 512;
+  st->f_blocks = 0;
+  st->f_bfree = 0;
+  st->f_bavail = 0;
+  st->f_type = FSTYPE_MISC;
+  st->f_files = disk_node_count;
+  st->f_ffree = 0;
+  st->f_fsid = getpid ();
+  st->f_namelen = 0;
+
+  return 0;
+}
+
+/* The user must define this function.  This should sync the locked
+   file NP completely to disk, for the user CRED.  If WAIT is set,
+   return only after the sync is completely finished.  */
+error_t
+netfs_attempt_sync (struct iouser *cred, struct node *np, int wait)
+{
+  return 0;
+}
+
+/* The user must define this function.  This should sync the entire
+   remote filesystem.  If WAIT is set, return only after the sync is
+   completely finished.  */
+error_t
+netfs_attempt_syncfs (struct iouser *cred, int wait)
+{
+  return 0;
+}
+
+/* The user must define this function.  Lookup NAME in DIR (which is
+   locked) for USER; set *NP to the found name upon return.  If the
+   name was not found, then return ENOENT.  On any error, clear *NP.
+   (*NP, if found, should be locked, this call should unlock DIR no
+   matter what.)  */
+error_t
+netfs_attempt_lookup (struct iouser *user, struct node *dir, 
+                     char *name, struct node **np)
+{
+  int entry;
+  char *end;
+
+  if (dir->nn->type != NODE_ROOT)
+    {
+      mutex_unlock (&dir->lock);
+      goto lose;
+    }
+
+  mutex_unlock (&dir->lock);
+
+  /* Root directory.  */
+  if (strcmp (name, ".") == 0)
+    {
+      *np = disk_node[0];
+      goto out;
+    }
+
+  /* A partition.  */
+  entry = strtol (name, &end, 10);
+  if (*end != '\0')
+    goto lose;
+
+  if (! disk_node[entry] || disk_node[entry] == netfs_root_node)
+    goto lose;
+
+  *np = disk_node[entry];
+
+ out:
+  mutex_lock (&(*np)->lock);
+  netfs_nref (*np);
+  return 0;
+
+ lose:
+  *np = NULL;
+  return ENOENT;
+}
+
+/* The user must define this function. Locked node NP is being opened
+   by USER, with FLAGS.  NEWNODE is nonzero if we just created this
+   node.  Return an error if we should not permit the open to complete
+   because of a permission restriction.  */
+error_t
+netfs_check_open_permissions (struct iouser *user, struct node *np,
+                             int flags, int newnode)
+{
+  /* We do not enforce any additional restrictions.  */
+  return 0;
+}
+
+/* The user must define this function.  Return the valid access
+   types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for
+   locked file NP and user CRED.  */
+error_t
+netfs_report_access (struct iouser *cred, struct node *np,
+                    int *types)
+{
+  *types = 0;
+  if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0)
+    *types |= O_READ;
+  if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0)
+    *types |= O_WRITE;
+  if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0)
+    *types |= O_EXEC;
+
+  return 0;
+}
+
+/* The user must define this function.  Fill the array *DATA of size
+   BUFSIZE with up to NENTRIES dirents from DIR (which is locked)
+   starting with entry ENTRY for user CRED.  The number of entries in
+   the array is stored in *AMT and the number of bytes in *DATACNT.
+   If the supplied buffer is not large enough to hold the data, it
+   should be grown.  */
+error_t
+netfs_get_dirents (struct iouser *cred, struct node *dir,
+                  int entry, int nentries, char **data,
+                  mach_msg_type_number_t *datacnt,
+                  vm_size_t bufsize, int *amt)
+{
+
+  int i;
+  int e;
+  int filled;
+  struct dirent *d;
+  void *buf = *data;
+
+  /* I would like to see someone with more that 10k partitions. Bah!  */
+  int max_size = ((entry == -1 ? disk_node_count : entry)
+                * (sizeof (struct dirent) + 4));
+  int allocsize;
+
+  if (! bufsize || bufsize > max_size)
+    allocsize = round_page (max_size);
+  else
+    allocsize = round_page (bufsize);
+  if (allocsize > *datacnt)
+    *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+
+  /* Goto the entry ENTRY.  */
+  for (i = 1, e = 0; e < entry && i < disk_node_count; i ++)
+    if (disk_node[i])
+      e ++;
+
+  if (i == disk_node_count)
+    {
+      *amt = 0;
+      return 0;
+    }
+
+  filled = 0;
+  for (; i <= disk_node_count; i ++)
+    {
+      if (! disk_node[i])
+       continue;
+
+      d = buf;
+      d->d_fileno = i;
+      d->d_type = DT_UNKNOWN;
+      sprintf (d->d_name, "%d", i);
+      d->d_namlen = strlen (d->d_name);
+      d->d_reclen = (sizeof (struct dirent) + d->d_namlen + 1);
+
+      buf += d->d_reclen;
+
+      if (++ filled == nentries)
+       break;
+    }
+
+  *datacnt = (void *)buf - (void *)*data;
+  *amt = filled;
+
+  if (allocsize > *datacnt
+      && round_page (buf - (void *)*data) < round_page (allocsize))
+    munmap ((caddr_t) round_page (buf),
+           round_page (allocsize) - round_page (buf - (void *)*data));
+
+  return 0;
+}
+
+/* The user may define this function.  For a full description,
+   see hurd/hurd_types.h.  The default response indicates a network
+   store.  If the supplied buffers are not large enough, they should
+   be grown as necessary.  NP is locked.  */
+error_t netfs_file_get_storage_info (struct iouser *cred,
+                                    struct node *np,
+                                    mach_port_t **ports,
+                                    mach_msg_type_name_t *ports_type,
+                                    mach_msg_type_number_t *num_ports,
+                                    int **ints,
+                                    mach_msg_type_number_t *num_ints,
+                                    off_t **offsets,
+                                    mach_msg_type_number_t *num_offsets,
+                                    char **data,
+                                    mach_msg_type_number_t *data_len)
+{
+  error_t err;
+  struct store *device;
+
+  err = store_clone (kernel_device_store, &device);
+  if (err)
+    return err;
+
+  if (np->nn->type == NODE_PARTITION)
+    {
+      struct store_run run;
+
+      run.start = np->nn->partition->offset;
+      run.length = np->nn->partition->size;
+
+      err = store_remap (device, &run, 1, &device);
+      if (err)
+       return err;
+    }
+
+  *ports_type = MACH_MSG_TYPE_COPY_SEND;
+  err = store_return (device, ports, num_ports, ints, num_ints,
+                     offsets, num_offsets, data, data_len);
+
+  return err;
+}
diff --exclude=CVS -ur --new-file hurd/diskpart/stubs.c 
hurd-new/diskpart/stubs.c
--- hurd/diskpart/stubs.c       Wed Dec 31 19:00:00 1969
+++ hurd-new/diskpart/stubs.c   Mon Jan 15 22:27:16 2001
@@ -0,0 +1,183 @@
+/* Netfs unused call backs.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+#define _GNU_SOURCE 1
+
+#include <hurd/netfs.h>
+
+/* The user must define this function.  This should attempt a chmod
+   call for the user specified by CRED on locked node NP, to change
+   the owner to UID and the group to GID.  */
+error_t netfs_attempt_chown (struct iouser *cred, struct node *np,
+                            uid_t uid, uid_t gid)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  This should attempt a chauthor
+   call for the user specified by CRED on locked node NP, thereby
+   changing the author to AUTHOR.  */
+error_t netfs_attempt_chauthor (struct iouser *cred, struct node *np,
+                               uid_t author)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  This should attempt a chmod
+   call for the user specified by CRED on locked node NP, thereby
+   changing the mode to MODE.  */
+error_t netfs_attempt_chmod (struct iouser *cred, struct node *np,
+                            mode_t mode)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to turn locked node NP
+   (user CRED) into a symlink with target NAME.  */
+error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *np,
+                                char *name)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to turn NODE (user
+   CRED) into a device.  TYPE is either S_IFBLK or S_IFCHR.  NP is
+   locked.  */
+error_t netfs_attempt_mkdev (struct iouser *cred, struct node *np,
+                            mode_t type, dev_t indexes)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  This should attempt a chflags
+   call for the user specified by CRED on locked node NP, to change
+   the flags to FLAGS.  */
+error_t netfs_attempt_chflags (struct iouser *cred, struct node *np,
+                              int flags)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  This should attempt to set the
+   size of the locked file NP (for user CRED) to SIZE bytes long.  */
+error_t netfs_attempt_set_size (struct iouser *cred, struct node *np,
+                               off_t size)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Delete NAME in DIR (which is
+   locked) for USER.  */
+error_t netfs_attempt_unlink (struct iouser *user, struct node *dir,
+                             char *name)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to rename the
+   directory FROMDIR to TODIR. Note that neither of the specific nodes
+   are locked.  */
+error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir,
+                             char *fromname, struct node *todir, 
+                             char *toname, int excl)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to create a new
+   directory named NAME in DIR (which is locked) for USER with mode
+   MODE. */
+error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir,
+                            char *name, mode_t mode)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to remove directory
+   named NAME in DIR (which is locked) for USER.  */
+error_t netfs_attempt_rmdir (struct iouser *user, 
+                            struct node *dir, char *name)
+{
+  return EOPNOTSUPP;
+}
+
+
+/* The user must define this function.  Create a link in DIR with name
+   NAME to FILE for USER. Note that neither DIR nor FILE are
+   locked. If EXCL is set, do not delete the target.  Return EEXIST if
+   NAME is already found in DIR.  */
+error_t netfs_attempt_link (struct iouser *user, struct node *dir,
+                           struct node *file, char *name, int excl)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to create an anonymous
+   file related to DIR (which is locked) for USER with MODE.  Set *NP
+   to the returned file upon success. No matter what, unlock DIR.  */
+error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir,
+                             mode_t mode, struct node **np)
+{
+  mutex_unlock (&dir->lock);
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Attempt to create a file named
+   NAME in DIR (which is locked) for USER with MODE.  Set *NP to the
+   new node upon return.  On any error, clear *NP.  *NP should be
+   locked on success; no matter what, unlock DIR before returning.  */
+error_t netfs_attempt_create_file (struct iouser *user, struct node *dir,
+                                  char *name, mode_t mode, struct node **np)
+{
+  *np = 0;
+  mutex_unlock (&dir->lock);
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Read the contents of locked
+   node NP (a symlink), for USER, into BUF.  */
+error_t netfs_attempt_readlink (struct iouser *user, struct node *np,
+                               char *buf)
+{
+  return EOPNOTSUPP;
+}
+
+/* The user must define this function.  Read from the locked file NP
+   for user CRED starting at OFFSET and continuing for up to *LEN
+   bytes.  Put the data at DATA.  Set *LEN to the amount successfully
+   read upon return.  */
+error_t netfs_attempt_read (struct iouser *cred, struct node *np,
+                           off_t offset, size_t *len, void *data)
+{
+  return EOPNOTSUPP;
+}
+
+
+/* The user must define this function.  Write to the locked file NP
+   for user CRED starting at OFSET and continuing for up to *LEN bytes
+   from DATA.  Set *LEN to the amount seccessfully written upon
+   return.  */
+error_t netfs_attempt_write (struct iouser *cred, struct node *np,
+                            off_t offset, size_t *len, void *data)
+{
+  return EOPNOTSUPP;
+}
diff --exclude=CVS -ur --new-file hurd/utils/ChangeLog hurd-new/utils/ChangeLog
--- hurd/utils/ChangeLog        Mon Jan  8 17:33:11 2001
+++ hurd-new/utils/ChangeLog    Mon Jan 15 22:33:11 2001
@@ -1,3 +1,8 @@
+2001-01-15  Neal H Walfield  <neal@cs.uml.edu>
+
+       * partinfo.c: New file.
+       * Makefile: Added build information for new program, partinfo.
+
 2001-01-08  Marcus Brinkmann  <marcus@gnu.org>
 
        * storeread.c (main): Change type of addr to store_offset_t,
diff --exclude=CVS -ur --new-file hurd/utils/Makefile hurd-new/utils/Makefile
--- hurd/utils/Makefile Wed Jul 26 07:33:12 2000
+++ hurd-new/utils/Makefile     Mon Jan 15 20:20:01 2001
@@ -21,14 +21,14 @@
 targets = shd ps settrans showtrans syncfs fsysopts \
        storeinfo login w uptime ids loginpr sush vmstat portinfo \
        devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \
-       storeread ping msgport rpctrace mount
+       storeread ping msgport rpctrace mount partinfo
 special-targets = loginpr sush uptime
 SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \
        fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \
        uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \
        parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \
        unsu.c ftpcp.c ftpdir.c storeread.c storecat.c ping.c msgport.c \
-       rpctrace.c mount.c
+       rpctrace.c mount.c partinfo.c
 LCLHDRS = psout.h parse.h pids.h frobauth.h
 
 OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
@@ -59,6 +59,8 @@
 ftpcp ftpdir: ../libftpconn/libftpconn.a
 
 ping: ../libthreads/libthreads.a
+
+partinfo: ../libdiskpart/libdiskpart.a
 
 # We must include libthreads because of a bug in the way shared libraries
 # work: all libraries that *any* routine in libfshelp uses must be defined.
diff --exclude=CVS -ur --new-file hurd/utils/partinfo.c 
hurd-new/utils/partinfo.c
--- hurd/utils/partinfo.c       Wed Dec 31 19:00:00 1969
+++ hurd-new/utils/partinfo.c   Mon Jan 15 20:18:57 2001
@@ -0,0 +1,179 @@
+/* Show the partition table on a device.
+  
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+  
+   This file is part of the GNU Hurd.
+  
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Generall Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd 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.  */
+
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <error.h>
+#include <argp.h>
+
+#include <hurd.h>
+#include <hurd/diskpart.h>
+#include <device/device.h>
+#include <mach.h>
+
+static char *args_doc = "DEVICE...";
+static char *doc = "Print the partition table on the specified devices.";
+
+static mach_port_t master_device_port = MACH_PORT_NULL;
+
+#define BLOCK_TO_MB(x, block_size) ((((x) / 1024) * block_size) / 1024)
+
+/* Print some information on the given device.  */
+void
+info (char *device_name)
+{
+  error_t err;
+
+  size_t sector_size;
+  size_t sector_count;
+  struct partition_table *p_table;
+  device_t device;
+
+  err = device_open (master_device_port, D_READ, device_name, &device);
+  if (err)
+    {
+      error (0, err, "opening %s", device_name);
+      return;
+    }
+
+  {
+    size_t sizes[DEV_GET_SIZE_COUNT];
+    size_t sizes_len = DEV_GET_SIZE_COUNT;
+
+    err = device_get_status (device, DEV_GET_SIZE, sizes, &sizes_len);
+    if (err)
+      {
+       error (0, err, "sizing %s", device_name);
+       return;
+      }
+
+    sector_size = sizes[DEV_GET_SIZE_RECORD_SIZE];
+    sector_count = sizes[DEV_GET_SIZE_DEVICE_SIZE] / sector_size;
+  }
+
+  printf ("%s:\n  record size: %d bytes\n  device size: %u megabytes\n",
+         device_name, sector_size, BLOCK_TO_MB (sector_count, sector_size));
+
+  /* Read the table.  */
+  {
+    error_t
+    block_read (off_t offset, void **data, void *cookie)
+      {
+       error_t err;
+       size_t amount;
+
+       err = device_read (device, 0, offset, sector_size,
+                          (io_buf_ptr_t *)data, &amount);
+       if (amount != sector_size)
+         err = EIO;
+
+       return err;
+      }
+
+    void
+    free_block (void *data)
+      {
+       vm_deallocate (mach_task_self (), (vm_address_t) data,
+                      sector_size);
+      }
+
+    err = partition_table_scan (&p_table, block_read, NULL, free_block);
+    if (err)
+      {
+       error (0, err, "partition_table_scan");
+       return;
+      }
+
+    device_close (device);
+  }
+
+  /* Dump it out.  */
+  {
+    error_t
+    partition_table_dump (struct partition_table *table, char *drive,
+                         FILE *out)
+      {
+       error_t
+       func (struct partition *p, void *cookie)
+         {
+           if (p->do_export)
+             fprintf (out, "%ss%d", drive, p->id);
+           fprintf (out, "\t%d\t%d\t0x%x\t0x%x\n",
+                    BLOCK_TO_MB (p->offset, 512),
+                    BLOCK_TO_MB (p->size, 512),
+                    p->major_type, p->minor_type);
+
+           return 0;
+         }
+
+       fprintf (out, "Drive\tOffset\tSize\tMajor\tMinor\n"
+                     "\t(MB)\t(MB)\tType\tType\n");
+
+       partition_table_iterate (table, func, NULL);
+
+       return 0;
+      }
+
+    partition_table_dump (p_table, device_name, stdout);
+  }
+}
+
+static error_t
+parse_options (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case ARGP_KEY_NO_ARGS:
+      argp_usage (state);
+
+    case ARGP_KEY_ARG:
+      if (master_device_port == MACH_PORT_NULL)
+       {
+          error_t err;
+         err = get_privileged_ports (NULL, &master_device_port);
+         if (err)
+           error (1, err, "get_privileged_ports");
+       }
+
+      info (arg);
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+
+  return 0;
+}
+
+/* Convert X blocks of size BLOCK_SIZE to Megabytes.  */
+#define BLOCK_TO_MB(x, block_size) ((((x) / 1024) * block_size) / 1024)
+
+int main (int argc, char *argv[])
+{
+  struct argp argp = {0, parse_options, args_doc, doc};
+
+  argp_parse (&argp, argc, argv, 0, 0, 0);
+
+  return 0;
+}

Attachment: pgpQZwXDYIqCc.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]