(root)/
util-linux-2.39/
libblkid/
src/
partitions/
unixware.c
       1  /*
       2   * unixware partition parsing code
       3   *
       4   * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
       5   *
       6   * This file may be redistributed under the terms of the
       7   * GNU Lesser General Public License.
       8   *
       9   *
      10   * The interesting information about unixware PT:
      11   *   - Linux kernel / partx
      12   *   - vtoc(7) SCO UNIX command man page
      13   *   - evms source code (http://evms.sourceforge.net/)
      14   *   - vxtools source code (http://martin.hinner.info/fs/vxfs/)
      15   */
      16  #include <stdio.h>
      17  #include <string.h>
      18  #include <stdlib.h>
      19  #include <stdint.h>
      20  
      21  #include "partitions.h"
      22  
      23  /* disklabel location */
      24  #define UNIXWARE_SECTOR		29
      25  #define UNIXWARE_OFFSET		(UNIXWARE_SECTOR << 9)	/* offset in bytes */
      26  #define UNIXWARE_KBOFFSET	(UNIXWARE_OFFSET >> 10)	/* offset in 1024-blocks */
      27  
      28  /* disklabel->d_magic offset within the last 1024 block */
      29  #define UNIXWARE_MAGICOFFSET	(UNIXWARE_OFFSET - UNIXWARE_KBOFFSET + 4)
      30  
      31  #define UNIXWARE_VTOCMAGIC	0x600DDEEEUL
      32  #define UNIXWARE_MAXPARTITIONS	16
      33  
      34  /* unixware_partition->s_label flags */
      35  #define UNIXWARE_TAG_UNUSED       0x0000  /* unused partition */
      36  #define UNIXWARE_TAG_BOOT         0x0001  /* boot fs */
      37  #define UNIXWARE_TAG_ROOT         0x0002  /* root fs */
      38  #define UNIXWARE_TAG_SWAP         0x0003  /* swap fs */
      39  #define UNIXWARE_TAG_USER         0x0004  /* user fs */
      40  #define UNIXWARE_TAG_ENTIRE_DISK  0x0005  /* whole disk */
      41  #define UNIXWARE_TAG_ALT_S        0x0006  /* alternate sector space */
      42  #define UNIXWARE_TAG_OTHER        0x0007  /* non unix */
      43  #define UNIXWARE_TAG_ALT_T        0x0008  /* alternate track space */
      44  #define UNIXWARE_TAG_STAND        0x0009  /* stand partition */
      45  #define UNIXWARE_TAG_VAR          0x000a  /* var partition */
      46  #define UNIXWARE_TAG_HOME         0x000b  /* home partition */
      47  #define UNIXWARE_TAG_DUMP         0x000c  /* dump partition */
      48  #define UNIXWARE_TAG_ALT_ST       0x000d  /* alternate sector track */
      49  #define UNIXWARE_TAG_VM_PUBLIC    0x000e  /* volume mgt public partition */
      50  #define UNIXWARE_TAG_VM_PRIVATE   0x000f  /* volume mgt private partition */
      51  
      52  
      53  /* unixware_partition->s_flags flags */
      54  #define UNIXWARE_FLAG_VALID	0x0200
      55  
      56  struct unixware_partition {
      57  	uint16_t	s_label;	/* partition label (tag) */
      58  	uint16_t	s_flags;	/* permission flags */
      59  	uint32_t	start_sect;	/* starting sector */
      60  	uint32_t	nr_sects;	/* number of sectors */
      61  } __attribute__((packed));
      62  
      63  struct unixware_disklabel {
      64  	uint32_t	d_type;		/* drive type */
      65  	uint32_t	d_magic;	/* the magic number */
      66  	uint32_t	d_version;	/* version number */
      67  	char		d_serial[12];	/* serial number of the device */
      68  	uint32_t	d_ncylinders;	/* # of data cylinders per device */
      69  	uint32_t	d_ntracks;	/* # of tracks per cylinder */
      70  	uint32_t	d_nsectors;	/* # of data sectors per track */
      71  	uint32_t	d_secsize;	/* # of bytes per sector */
      72  	uint32_t	d_part_start;	/* # of first sector of this partition */
      73  	uint32_t	d_unknown1[12];	/* ? */
      74  	uint32_t	d_alt_tbl;	/* byte offset of alternate table */
      75  	uint32_t	d_alt_len;	/* byte length of alternate table */
      76  	uint32_t	d_phys_cyl;	/* # of physical cylinders per device */
      77  	uint32_t	d_phys_trk;	/* # of physical tracks per cylinder */
      78  	uint32_t	d_phys_sec;	/* # of physical sectors per track */
      79  	uint32_t	d_phys_bytes;	/* # of physical bytes per sector */
      80  	uint32_t	d_unknown2;	/* ? */
      81  	uint32_t	d_unknown3;	/* ? */
      82  	uint32_t	d_pad[8];	/* pad */
      83  
      84  	struct unixware_vtoc {
      85  		uint32_t	v_magic;	/* the magic number */
      86  		uint32_t	v_version;	/* version number */
      87  		char		v_name[8];	/* volume name */
      88  		uint16_t	v_nslices;	/* # of partitions */
      89  		uint16_t	v_unknown1;	/* ? */
      90  		uint32_t	v_reserved[10];	/* reserved */
      91  
      92  		struct unixware_partition
      93  			v_slice[UNIXWARE_MAXPARTITIONS]; /* partition */
      94  	} __attribute__((packed)) vtoc;
      95  };
      96  
      97  static int probe_unixware_pt(blkid_probe pr,
      98  		const struct blkid_idmag *mag __attribute__((__unused__)))
      99  {
     100  	struct unixware_disklabel *l;
     101  	struct unixware_partition *p;
     102  	blkid_parttable tab = NULL;
     103  	blkid_partition parent;
     104  	blkid_partlist ls;
     105  	int i;
     106  
     107  	l = (struct unixware_disklabel *)
     108  			blkid_probe_get_sector(pr, UNIXWARE_SECTOR);
     109  	if (!l) {
     110  		if (errno)
     111  			return -errno;
     112  		goto nothing;
     113  	}
     114  
     115  	if (le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_VTOCMAGIC)
     116  		goto nothing;
     117  
     118  	if (blkid_partitions_need_typeonly(pr))
     119  		/* caller does not ask for details about partitions */
     120  		return BLKID_PROBE_OK;
     121  
     122  	ls = blkid_probe_get_partlist(pr);
     123  	if (!ls)
     124  		goto nothing;
     125  
     126  	parent = blkid_partlist_get_parent(ls);
     127  
     128  	tab = blkid_partlist_new_parttable(ls, "unixware", UNIXWARE_OFFSET);
     129  	if (!tab)
     130  		goto err;
     131  
     132  	/* Skip the first partition that describe whole disk
     133  	 */
     134  	for (i = 1, p = &l->vtoc.v_slice[1];
     135  			i < UNIXWARE_MAXPARTITIONS; i++, p++) {
     136  
     137  		uint32_t start, size;
     138  		uint16_t tag, flg;
     139  		blkid_partition par;
     140  
     141  		tag = le16_to_cpu(p->s_label);
     142  		flg = le16_to_cpu(p->s_flags);
     143  
     144  		if (tag == UNIXWARE_TAG_UNUSED ||
     145  		    tag == UNIXWARE_TAG_ENTIRE_DISK ||
     146  		    flg != UNIXWARE_FLAG_VALID)
     147  			continue;
     148  
     149  		start = le32_to_cpu(p->start_sect);
     150  		size = le32_to_cpu(p->nr_sects);
     151  
     152  		if (parent && !blkid_is_nested_dimension(parent, start, size)) {
     153  			DBG(LOWPROBE, ul_debug(
     154  				"WARNING: unixware partition (%d) overflow "
     155  				"detected, ignore", i));
     156  			continue;
     157  		}
     158  
     159  		par = blkid_partlist_add_partition(ls, tab, start, size);
     160  		if (!par)
     161  			goto err;
     162  
     163  		blkid_partition_set_type(par, tag);
     164  		blkid_partition_set_flags(par, flg);
     165  	}
     166  
     167  	return BLKID_PROBE_OK;
     168  
     169  nothing:
     170  	return BLKID_PROBE_NONE;
     171  err:
     172  	return -ENOMEM;
     173  }
     174  
     175  
     176  /*
     177   * The unixware partition table is within primary DOS partition.  The PT is
     178   * located on 29 sector, PT magic string is d_magic member of 'struct
     179   * unixware_disklabel'.
     180   */
     181  const struct blkid_idinfo unixware_pt_idinfo =
     182  {
     183  	.name		= "unixware",
     184  	.probefunc	= probe_unixware_pt,
     185  	.minsz		= 1024 * 1440 + 1,		/* ignore floppies */
     186  	.magics		=
     187  	{
     188  		{
     189  		  .magic = "\x0D\x60\xE5\xCA",	/* little-endian magic string */
     190  		  .len = 4,			/* d_magic size in bytes */
     191  		  .kboff = UNIXWARE_KBOFFSET,
     192  		  .sboff = UNIXWARE_MAGICOFFSET
     193  		},
     194  		{ NULL }
     195  	}
     196  };
     197