From e85a2a9392bde75b45bc9973782d8ff5bfa2b54b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 12 Mar 2009 10:15:50 +0100 Subject: [PATCH] lib: add pttype.c for PT types detection 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 --- include/Makefile.am | 3 +- include/pttype.h | 10 ++ lib/.gitignore | 1 + lib/Makefile.am | 5 +- lib/pttype.c | 260 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 include/pttype.h create mode 100644 lib/pttype.c diff --git a/include/Makefile.am b/include/Makefile.am index b9314a97..24acb9f6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -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 index 00000000..d6fe8128 --- /dev/null +++ b/include/pttype.h @@ -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 diff --git a/lib/.gitignore b/lib/.gitignore index 025150b9..0be0fd86 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,2 +1,3 @@ test_blkdev test_ismounted +test_pttype diff --git a/lib/Makefile.am b/lib/Makefile.am index cd4871aa..f813f685 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 index 00000000..429b4755 --- /dev/null +++ b/lib/pttype.c @@ -0,0 +1,260 @@ +/* + * Based on libdisk from xfsprogs and Linux fdisk. + * + * Copyright (c) 2000-2001 Silicon Graphics, Inc. + * Copyright (C) 2009 Karel Zak + */ +#include +#include +#include +#include +#include +#include + +#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 \n", argv[0]); + exit(EXIT_FAILURE); + } + + type = get_pt_type(argv[1]); + if (type) + printf("Partition type: %s\n", type); + exit(EXIT_SUCCESS); +} +#endif -- 2.39.5