* '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
pull/574/head
Karel Zak 2018-01-31 11:08:06 +01:00
commit 9a84ecc0d8
10 changed files with 310 additions and 1 deletions

View 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 \

View File

@ -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
};

View 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
};
/*

View 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 */

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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

Binary file not shown.

Binary file not shown.