Merge branch 'libblkid-atari' of https://github.com/yontalcar/util-linux
* '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 schemepull/574/head
commit
9a84ecc0d8
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -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
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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'
|
|
@ -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'
|
|
@ -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
|
|
@ -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.
Loading…
Reference in New Issue