]> err.no Git - util-linux/commitdiff
lib: add pttype.c for PT types detection
authorKarel Zak <kzak@redhat.com>
Thu, 12 Mar 2009 09:15:50 +0000 (10:15 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 12 Mar 2009 09:15:50 +0000 (10:15 +0100)
This is a small fragment from libdisk (from xfsprogs). The final
solution will be to move the library to util-linux-ng.

Signed-off-by: Karel Zak <kzak@redhat.com>
include/Makefile.am
include/pttype.h [new file with mode: 0644]
lib/.gitignore
lib/Makefile.am
lib/pttype.c [new file with mode: 0644]

index b9314a9723d74ef96d4f927b9410e3276c12f5b0..24acb9f6bd56063cebad56ae5e4f6439672d5e7d 100644 (file)
@@ -16,4 +16,5 @@ dist_noinst_HEADERS = \
        setproctitle.h \
        swapheader.h \
        widechar.h \
-       xstrncpy.h
+       xstrncpy.h \
+       pttype.h
diff --git a/include/pttype.h b/include/pttype.h
new file mode 100644 (file)
index 0000000..d6fe812
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef PTTYPE_H
+#define PTTYPE_H
+
+/*
+ * Note that this is a temporary solution. The final solution will be to move
+ * libdisk from xfsprogs to util-linux-ng.
+ */
+extern const char *get_pt_type(const char *device);
+
+#endif
index 025150b97b10c8b954f4ebe4e93efd5a6f1db8a3..0be0fd86c92e786323b282932b144f16e1c4fdd0 100644 (file)
@@ -1,2 +1,3 @@
 test_blkdev
 test_ismounted
+test_pttype
index cd4871aa367de45ceff229a62a96a7d7643f30ad..f813f685596fccb88a7a88cd208f4484ac55af57 100644 (file)
@@ -1,9 +1,10 @@
 include $(top_srcdir)/config/include-Makefile.am
 
-noinst_PROGRAMS = test_blkdev test_ismounted
+noinst_PROGRAMS = test_blkdev test_ismounted test_pttype
 
 test_blkdev_SOURCES = blkdev.c
 test_ismounted_SOURCES = ismounted.c
+test_pttype_SOURCES = pttype.c
 
 if LINUX
 test_blkdev_SOURCES += linux_version.c
@@ -11,5 +12,5 @@ endif
 
 test_blkdev_CFLAGS = -DTEST_PROGRAM
 test_ismounted_CFLAGS = -DTEST_PROGRAM
-
+test_pttype_CFLAGS = -DTEST_PROGRAM
 
diff --git a/lib/pttype.c b/lib/pttype.c
new file mode 100644 (file)
index 0000000..429b475
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Based on libdisk from xfsprogs and Linux fdisk.
+ *
+ * Copyright (c) 2000-2001 Silicon Graphics, Inc.
+ * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+#include "blkdev.h"
+
+/*
+ * SGI
+ */
+struct sgi_device_parameter { /* 48 bytes */
+       unsigned char  skew;
+       unsigned char  gap1;
+       unsigned char  gap2;
+       unsigned char  sparecyl;
+       unsigned short pcylcount;
+       unsigned short head_vol0;
+       unsigned short ntrks;   /* tracks in cyl 0 or vol 0 */
+       unsigned char  cmd_tag_queue_depth;
+       unsigned char  unused0;
+       unsigned short unused1;
+       unsigned short nsect;   /* sectors/tracks in cyl 0 or vol 0 */
+       unsigned short bytes;
+       unsigned short ilfact;
+       unsigned int   flags;           /* controller flags */
+       unsigned int   datarate;
+       unsigned int   retries_on_error;
+       unsigned int   ms_per_word;
+       unsigned short xylogics_gap1;
+       unsigned short xylogics_syncdelay;
+       unsigned short xylogics_readdelay;
+       unsigned short xylogics_gap2;
+       unsigned short xylogics_readgate;
+       unsigned short xylogics_writecont;
+};
+
+#define        SGI_VOLHDR      0x00
+/* 1 and 2 were used for drive types no longer supported by SGI */
+#define        SGI_SWAP        0x03
+/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
+#define        SGI_VOLUME      0x06
+#define        SGI_EFS         0x07
+#define        SGI_LVOL        0x08
+#define        SGI_RLVOL       0x09
+#define        SGI_XFS         0x0a
+#define        SGI_XFSLOG      0x0b
+#define        SGI_XLV         0x0c
+#define        SGI_XVM         0x0d
+#define        ENTIRE_DISK     SGI_VOLUME
+/*
+ * controller flags
+ */
+#define        SECTOR_SLIP     0x01
+#define        SECTOR_FWD      0x02
+#define        TRACK_FWD       0x04
+#define        TRACK_MULTIVOL  0x08
+#define        IGNORE_ERRORS   0x10
+#define        RESEEK          0x20
+#define        CMDTAGQ_ENABLE  0x40
+
+struct sgi_volume_header {
+       unsigned int   magic;            /* expect SGI_LABEL_MAGIC */
+       unsigned short boot_part;        /* active boot partition */
+       unsigned short swap_part;        /* active swap partition */
+       unsigned char  boot_file[16];    /* name of the bootfile */
+       struct sgi_device_parameter devparam;   /*  1 * 48 bytes */
+       struct volume_directory {               /* 15 * 16 bytes */
+               unsigned char vol_file_name[8]; /* a character array */
+               unsigned int  vol_file_start;   /* number of logical block */
+               unsigned int  vol_file_size;    /* number of bytes */
+       } directory[15];
+       struct sgi_partition {                  /* 16 * 12 bytes */
+               unsigned int num_sectors;       /* number of blocks */
+               unsigned int start_sector;      /* must be cylinder aligned */
+               unsigned int id;
+       } partitions[16];
+       unsigned int   csum;
+       unsigned int   fillbytes;
+};
+
+#define        SGI_LABEL_MAGIC         0x0be5a941
+
+static uint32_t
+twos_complement_32bit_sum(u_int32_t *base, int size)
+{
+       int i;
+       u_int32_t sum = 0;
+
+       size = size / sizeof(u_int32_t);
+       for (i = 0; i < size; i++)
+               sum = sum - ntohl(base[i]);
+       return sum;
+}
+
+static int
+sgi_parttable(char *base)
+{
+       u_int32_t csum;
+       struct sgi_volume_header *vh = (struct sgi_volume_header *) base;
+
+       if (ntohl(vh->magic) != SGI_LABEL_MAGIC)
+               return 0;
+       csum = twos_complement_32bit_sum((uint32_t *)vh,
+                               sizeof(struct sgi_volume_header));
+       return !csum;
+}
+
+/*
+ * DOS
+ */
+static int
+dos_parttable(char *base)
+{
+       return (base[510] == 0x55 && base[511] == 0xaa);
+}
+
+/*
+ * AIX
+ */
+typedef struct {
+       unsigned int   magic;        /* expect AIX_LABEL_MAGIC */
+       /* ... */
+} aix_partition;
+
+#define        AIX_LABEL_MAGIC         0xc9c2d4c1
+#define        AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
+#define aixlabel(x) ((aix_partition *)x)
+
+static int
+aix_parttable(char *base)
+{
+       return (aixlabel(base)->magic == AIX_LABEL_MAGIC ||
+               aixlabel(base)->magic == AIX_LABEL_MAGIC_SWAPPED);
+}
+
+/*
+ * SUN
+ */
+typedef struct {
+       unsigned char info[128];   /* Informative text string */
+       unsigned char spare0[14];
+       struct sun_info {
+               unsigned char spare1;
+               unsigned char id;
+               unsigned char spare2;
+               unsigned char flags;
+       } infos[8];
+       unsigned char spare1[246]; /* Boot information etc. */
+       unsigned short rspeed;     /* Disk rotational speed */
+       unsigned short pcylcount;  /* Physical cylinder count */
+       unsigned short sparecyl;   /* extra sects per cylinder */
+       unsigned char spare2[4];   /* More magic... */
+       unsigned short ilfact;     /* Interleave factor */
+       unsigned short ncyl;       /* Data cylinder count */
+       unsigned short nacyl;      /* Alt. cylinder count */
+       unsigned short ntrks;      /* Tracks per cylinder */
+       unsigned short nsect;      /* Sectors per track */
+       unsigned char spare3[4];   /* Even more magic... */
+       struct sun_partition {
+               u_int32_t start_cylinder;
+               u_int32_t num_sectors;
+       } partitions[8];
+       unsigned short magic;      /* Magic number */
+       unsigned short csum;       /* Label xor'd checksum */
+} sun_partition;
+
+#define SUN_LABEL_MAGIC          0xDABE
+#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
+#define sunlabel(x) ((sun_partition *)x)
+
+static int
+sun_parttable(char *base)
+{
+       unsigned short *ush;
+       int csum = 0;
+
+       if (sunlabel(base)->magic != SUN_LABEL_MAGIC &&
+           sunlabel(base)->magic != SUN_LABEL_MAGIC_SWAPPED)
+               return csum;
+       ush = ((unsigned short *) (sunlabel(base) + 1)) - 1;
+       while (ush >= (unsigned short *)sunlabel(base))
+               csum ^= *ush--;
+       return !csum;
+}
+
+/*
+ * MAC
+ */
+typedef struct {
+       unsigned short magic;
+       /* ... */
+} mac_partition;
+
+#define MAC_LABEL_MAGIC                0x4552
+#define MAC_PARTITION_MAGIC    0x504d
+#define MAC_OLD_PARTITION_MAGIC        0x5453
+#define maclabel(x) ((mac_partition *)x)
+
+static int
+mac_parttable(char *base)
+{
+       return (ntohs(maclabel(base)->magic) == MAC_LABEL_MAGIC ||
+               ntohs(maclabel(base)->magic) == MAC_PARTITION_MAGIC ||
+               ntohs(maclabel(base)->magic) == MAC_OLD_PARTITION_MAGIC);
+}
+
+const char *
+get_pt_type(const char *device)
+{
+       int     fd;
+       char    *type = NULL;
+       char    buf[DEFAULT_SECTOR_SIZE];
+
+       if ((fd = open(device, O_RDONLY)) < 0)
+               ;
+       else if (read(fd, buf, DEFAULT_SECTOR_SIZE) != DEFAULT_SECTOR_SIZE)
+               ;
+       else {
+               if (sgi_parttable(buf))
+                       type = "SGI";
+               else if (sun_parttable(buf))
+                       type = "Sun";
+               else if (aix_parttable(buf))
+                       type = "AIX";
+               else if (dos_parttable(buf))
+                       type = "DOS";
+               else if (mac_parttable(buf))
+                       type = "Mac";
+       }
+
+       if (fd >= 0)
+               close(fd);
+       return type;
+}
+
+#ifdef TEST_PROGRAM
+int
+main(int argc, char **argv)
+{
+       const char *type;
+
+       if (argc < 2) {
+               fprintf(stderr, "usage: %s <device>\n", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       type = get_pt_type(argv[1]);
+       if (type)
+               printf("Partition type: %s\n", type);
+       exit(EXIT_SUCCESS);
+}
+#endif