]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
Merge branch 'libblkid-atari' of https://github.com/yontalcar/util-linux
authorKarel Zak <kzak@redhat.com>
Wed, 31 Jan 2018 10:08:06 +0000 (11:08 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 31 Jan 2018 10:08:06 +0000 (11:08 +0100)
* 'libblkid-atari' of https://github.com/yontalcar/util-linux:
  libblkid: atari - reject devices with blocksize != 512
  libblkid: atari - don't add duplicate entries
  libblkid: atari - test if any partition fits disk size
  tests: added missing expected outputs for partx (atari)
  libblkid: atari - fix bad variable name
  tests: added test for libblkid atari pt
  libblkid: Support for Atari partitioning scheme

libblkid/src/Makemodule.am
libblkid/src/partitions/atari.c [new file with mode: 0644]
libblkid/src/partitions/partitions.c
libblkid/src/partitions/partitions.h
tests/expected/blkid/lowprobe-pt-atari-icd [new file with mode: 0644]
tests/expected/blkid/lowprobe-pt-atari-xgm [new file with mode: 0644]
tests/expected/partx/partx-image-atari-icd [new file with mode: 0644]
tests/expected/partx/partx-image-atari-xgm [new file with mode: 0644]
tests/ts/blkid/images-pt/atari-icd.img.xz [new file with mode: 0644]
tests/ts/blkid/images-pt/atari-xgm.img.xz [new file with mode: 0644]

index 1046be10058cae22f0cc1d5a56bd996808c9afb7..0e1c765fb3a72b28ec4ecfd2ff5c647c368a4d85 100644 (file)
@@ -29,6 +29,7 @@ libblkid_la_SOURCES = \
        \
        libblkid/src/partitions/aix.c \
        libblkid/src/partitions/aix.h \
+       libblkid/src/partitions/atari.c \
        libblkid/src/partitions/bsd.c \
        libblkid/src/partitions/dos.c \
        libblkid/src/partitions/gpt.c \
diff --git a/libblkid/src/partitions/atari.c b/libblkid/src/partitions/atari.c
new file mode 100644 (file)
index 0000000..1224a57
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * atari partitions parsing code
+ *
+ * Copyright (C) 2018 Vaclav Dolezal <vdolezal@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * Based on Linux kernel implementation and atari-fdisk
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "partitions.h"
+
+struct atari_part_def {
+       /*
+        * flags:
+        * 0 (LSB): active
+        * 1-6:     (reserved)
+        * 7 (MSB): bootable
+        */
+       unsigned char flags;
+       char id[3];
+       uint32_t start;
+       uint32_t size;
+} __attribute__((packed));
+
+struct atari_rootsector {
+       char unused0[0x156]; /* boot code */
+       struct atari_part_def icd_part[8]; /* ICD partition entries */
+       char unused1[0xc];
+       uint32_t hd_size;
+       struct atari_part_def part[4]; /* primary partition entries */
+       uint32_t bsl_start; /* bad sector list start */
+       uint32_t bsl_len; /* bad sector list length */
+       uint16_t checksum;
+} __attribute__((packed));
+
+
+/*
+ * Generated using linux kernel ctype.{c,h}
+ *
+ * Since kernel uses isalnum() to detect whether it is Atari PT, we need same
+ * definition of alnum character to be consistent with kernel.
+ */
+static const unsigned char _linux_isalnum[] = {
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1
+};
+
+static int linux_isalnum(unsigned char c) {
+       return _linux_isalnum[c];
+}
+
+#define isalnum linux_isalnum
+
+#define IS_ACTIVE(partdef) ((partdef).flags & 1)
+
+#define IS_PARTDEF_VALID(partdef, hdsize) \
+       ( \
+               (partdef).flags & 1 && \
+               isalnum((partdef).id[0]) && \
+               isalnum((partdef).id[1]) && \
+               isalnum((partdef).id[2]) && \
+               be32_to_cpu((partdef).start) <= (hdsize) && \
+               be32_to_cpu((partdef).start) + \
+                       be32_to_cpu((partdef).size) <= (hdsize) \
+       )
+
+static int is_id_common(char *id)
+{
+       const char *ids[] = {"GEM", "BGM", "LNX", "SWP", "RAW", };
+       unsigned i;
+
+       for (i = 0; i < ARRAY_SIZE(ids); i++) {
+               if (!memcmp(ids[i], id, 3))
+                       return 1;
+       }
+       return 0;
+}
+
+static int parse_partition(blkid_partlist ls, blkid_parttable tab,
+       struct atari_part_def *part, uint32_t offset)
+{
+       blkid_partition par;
+       uint32_t start;
+       uint32_t size;
+
+       start = be32_to_cpu(part->start) + offset;
+       size = be32_to_cpu(part->size);
+
+       if (blkid_partlist_get_partition_by_start(ls, start)) {
+               /* Don't increment partno for extended parts */
+               if (!offset)
+                       blkid_partlist_increment_partno(ls);
+               return 0;
+       }
+
+       par = blkid_partlist_add_partition(ls, tab, start, size);
+       if (!par)
+               return -ENOMEM;
+
+       blkid_partition_set_type_string(par, (unsigned char *) part->id,
+                                       sizeof(part->id));
+       return 1;
+}
+
+/*
+ * \return 1: OK, 0: bad format or -errno
+ */
+static int parse_extended(blkid_probe pr, blkid_partlist ls,
+       blkid_parttable tab, struct atari_part_def *part)
+{
+       uint32_t x0start, xstart;
+       unsigned i = 0;
+       int rc;
+
+       x0start = xstart = be32_to_cpu(part->start);
+       while (1) {
+               struct atari_rootsector *xrs;
+               xrs = (struct atari_rootsector *) blkid_probe_get_sector(pr, xstart);
+               if (!xrs) {
+                       if (errno)
+                               return -errno;
+                       return 0;
+               }
+
+               /*
+                * There must be data partition followed by reference to next
+                * XGM or inactive entry.
+                */
+               for (i=0; ; i++) {
+                       if (i >= ARRAY_SIZE(xrs->part) - 1)
+                               return 0;
+                       if (IS_ACTIVE(xrs->part[i]))
+                               break;
+               }
+
+               if (!memcmp(xrs->part[i].id, "XGM", 3))
+                       return 0;
+
+               rc = parse_partition(ls, tab, &xrs->part[i], xstart);
+               if (rc <= 0)
+                       return rc;
+
+               if (!IS_ACTIVE(xrs->part[i+1]))
+                       break;
+
+               if (memcmp(xrs->part[i+1].id, "XGM", 3))
+                       return 0;
+
+               xstart = x0start + be32_to_cpu(xrs->part[i+1].start);
+       }
+
+       return 1;
+}
+
+static int probe_atari_pt(blkid_probe pr,
+               const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+       struct atari_rootsector *rs;
+
+       blkid_parttable tab = NULL;
+       blkid_partlist ls;
+
+       unsigned i;
+       int has_xgm = 0;
+       int rc = 0;
+       off_t hdsize;
+
+       /* Atari partition is not defined for other sector sizes */
+       if (blkid_probe_get_sectorsize(pr) != 512)
+               goto nothing;
+
+       rs = (struct atari_rootsector *) blkid_probe_get_sector(pr, 0);
+       if (!rs) {
+               if (errno)
+                       return -errno;
+               goto nothing;
+       }
+
+       hdsize = blkid_probe_get_size(pr) / 512;
+
+       /* Look for validly looking primary partition */
+       for (i = 0; ; i++) {
+               if (i >= ARRAY_SIZE(rs->part))
+                       goto nothing;
+
+               if (IS_PARTDEF_VALID(rs->part[i], hdsize)) {
+                       blkid_probe_set_magic(pr,
+                               offsetof(struct atari_rootsector, part[i]),
+                               sizeof(rs->part[i].flags) + sizeof(rs->part[i].id),
+                               (unsigned char *) &rs->part[i]);
+                       break;
+               }
+       }
+
+       if (blkid_partitions_need_typeonly(pr))
+               /* caller does not ask for details about partitions */
+               return BLKID_PROBE_OK;
+
+       ls = blkid_probe_get_partlist(pr);
+       if (!ls)
+               goto nothing;
+
+       tab = blkid_partlist_new_parttable(ls, "atari", 0);
+       if (!tab)
+               goto err;
+
+       for (i = 0; i < ARRAY_SIZE(rs->part); i++) {
+               struct atari_part_def *p = &rs->part[i];
+
+               if (!IS_ACTIVE(*p)) {
+                       blkid_partlist_increment_partno(ls);
+                       continue;
+               }
+
+               if (!memcmp(p->id, "XGM", 3)) {
+                       has_xgm = 1;
+                       rc = parse_extended(pr, ls, tab, p);
+               } else {
+                       rc = parse_partition(ls, tab, p, 0);
+               }
+               if (rc < 0)
+                       return rc;
+       }
+
+       /* if there are no XGM partitions, we can try ICD format */
+       /* if first ICD partition ID is not valid, assume no ICD format */
+       if (!has_xgm && is_id_common(rs->icd_part[0].id)) {
+               for (i = 0; i < ARRAY_SIZE(rs->icd_part); i++) {
+                       struct atari_part_def *p = &rs->icd_part[i];
+
+                       if (!IS_ACTIVE(*p) || !is_id_common(p->id)) {
+                               blkid_partlist_increment_partno(ls);
+                               continue;
+                       }
+
+                       rc = parse_partition(ls, tab, p, 0);
+                       if (rc < 0)
+                               return rc;
+               }
+       }
+
+       return BLKID_PROBE_OK;
+
+nothing:
+       return BLKID_PROBE_NONE;
+err:
+       return -ENOMEM;
+}
+
+const struct blkid_idinfo atari_pt_idinfo =
+{
+       .name           = "atari",
+       .probefunc      = probe_atari_pt,
+       .magics         = BLKID_NONE_MAGIC
+};
index d8fc8e3c8e402cafc6a5c6d7535550a1aa94a645..1f1fc4515255e4823a77f40e5a065e78483fc436 100644 (file)
@@ -133,7 +133,8 @@ static const struct blkid_idinfo *idinfos[] =
        &bsd_pt_idinfo,
        &unixware_pt_idinfo,
        &solaris_x86_pt_idinfo,
-       &minix_pt_idinfo
+       &minix_pt_idinfo,
+       &atari_pt_idinfo
 };
 
 /*
index 1d99fb6a36e56f0444ec4d6df9bac9ad9e9d263f..4a718f4eaa42a5183feac84d559d8c8aedb0121e 100644 (file)
@@ -69,5 +69,6 @@ extern const struct blkid_idinfo minix_pt_idinfo;
 extern const struct blkid_idinfo gpt_pt_idinfo;
 extern const struct blkid_idinfo pmbr_pt_idinfo;
 extern const struct blkid_idinfo ultrix_pt_idinfo;
+extern const struct blkid_idinfo atari_pt_idinfo;
 
 #endif /* BLKID_PARTITIONS_H */
diff --git a/tests/expected/blkid/lowprobe-pt-atari-icd b/tests/expected/blkid/lowprobe-pt-atari-icd
new file mode 100644 (file)
index 0000000..29942b1
--- /dev/null
@@ -0,0 +1,8 @@
+size: 8388608, sector size: 512, PT: atari, offset: 0, id=(null)
+---
+#1:         65       4032  0x0 type='FAT'
+#2:       4097        904  0x0 type='FOO'
+#4:      12289       4096  0x0 type='BAR'
+#5:       5002       1999  0x0 type='GEM'
+#6:       7003       3238  0x0 type='RAW'
+#7:      10241       2048  0x0 type='RAW'
diff --git a/tests/expected/blkid/lowprobe-pt-atari-xgm b/tests/expected/blkid/lowprobe-pt-atari-xgm
new file mode 100644 (file)
index 0000000..4b77566
--- /dev/null
@@ -0,0 +1,8 @@
+size: 8388608, sector size: 512, PT: atari, offset: 0, id=(null)
+---
+#1:         65       4032  0x0 type='FAT'
+#2:       4097        904  0x0 type='FOO'
+#3:       5002       1999  0x0 type='GEM'
+#4:       7003       3238  0x0 type='RAW'
+#5:      10241       2048  0x0 type='RAW'
+#6:      12289       4096  0x0 type='BAR'
diff --git a/tests/expected/partx/partx-image-atari-icd b/tests/expected/partx/partx-image-atari-icd
new file mode 100644 (file)
index 0000000..8677dff
--- /dev/null
@@ -0,0 +1,7 @@
+NR START   END SECTORS   SIZE NAME UUID
+ 1    65  4096    4032     2M      
+ 2  4097  5000     904   452K      
+ 4 12289 16384    4096     2M      
+ 5  5002  7000    1999 999.5K      
+ 6  7003 10240    3238   1.6M      
+ 7 10241 12288    2048     1M      
diff --git a/tests/expected/partx/partx-image-atari-xgm b/tests/expected/partx/partx-image-atari-xgm
new file mode 100644 (file)
index 0000000..248d6a5
--- /dev/null
@@ -0,0 +1,7 @@
+NR START   END SECTORS   SIZE NAME UUID
+ 1    65  4096    4032     2M      
+ 2  4097  5000     904   452K      
+ 3  5002  7000    1999 999.5K      
+ 4  7003 10240    3238   1.6M      
+ 5 10241 12288    2048     1M      
+ 6 12289 16384    4096     2M      
diff --git a/tests/ts/blkid/images-pt/atari-icd.img.xz b/tests/ts/blkid/images-pt/atari-icd.img.xz
new file mode 100644 (file)
index 0000000..00a2aba
Binary files /dev/null and b/tests/ts/blkid/images-pt/atari-icd.img.xz differ
diff --git a/tests/ts/blkid/images-pt/atari-xgm.img.xz b/tests/ts/blkid/images-pt/atari-xgm.img.xz
new file mode 100644 (file)
index 0000000..bc2b8f9
Binary files /dev/null and b/tests/ts/blkid/images-pt/atari-xgm.img.xz differ