[lkml]   [2003]   [Sep]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Subjectrfc: test whether a device has a partition table
    As everyone knows it is a bad idea to let the kernel guess
    whether there is a partition table on a given block device,
    and if so, of what type.
    Nevertheless this is what almost everybody does.

    Until now the philosophy was: floppies do not have a partition table,
    disks do have one, and for ZIP drives nobody knows. With USB we get
    more types of block device that may or may not have a partition table
    (and if they have none, usually there is a FAT filesystem with bootsector).
    In such cases the kernel assumes a partition table, and creates a mess
    if there was none. Some heuristics are needed.

    Many checks are possible (for a DOS-type partition table: boot indicator
    must be 0 or 0x80, partitions are not larger than the disk,
    non-extended partitions are mutually disjoint; for a boot sector:
    it starts with a jump, the number of bytes per sector is 512 or
    at least a power of two, the number of sectors per cluster is 1
    or at least a power of two, the number of reserved sectors is 1 or 32,
    the number of FAT copies is 2, ...).

    I tried a minimal test, and the below is good enough for the
    boot sectors and DOS-type partition tables that I have here.

    So, question: are there people with DOS-type partition tables
    or FAT fs bootsectors where the below gives the wrong answer?
    I would be interested in a copy of the sector.

    I expect to submit some sanity check to DOS-type partition table
    parsing, and hope to recognize with high probability the presence
    of a full disk FAT filesystem.


    ------------ sniffsect.c -----------------

    * Given a block device, does it have a DOS-type partition table?
    * Or does it behave like a floppy and have a whole-disk filesystem?
    * Or is it something else?
    * Return 1 for pt, -1 for boot sect, 0 for unknown.

    #include <stdio.h>
    #include <fcntl.h>

    /* DOS-type partition */
    struct partition {
    unsigned char bootable; /* 0 or 0x80 */
    unsigned char begin_chs[3];
    unsigned char systype;
    unsigned char end_chs[3];
    unsigned char start_sect[4];
    unsigned char nr_sects[4];

    int sniffsect(unsigned char *p) {
    struct partition *pt;
    int i, n;
    int maybept = 1;
    int maybebs = 1;

    /* Both DOS-type pt and boot sector have a 55 aa signature */
    if (p[510] != 0x55 || p[511] != 0xaa)
    return 0;

    /* A partition table has boot indicators 0 or 0x80 */
    for (i=0; i<4; i++) {
    pt = (struct partition *)(p + 446 + 16*i);
    if (pt->bootable != 0 && pt->bootable != 0x80)
    maybept = 0;

    /* A boot sector has a power of two as #sectors/cluster */
    n = p[13];
    if (n == 0 || (n & (n-1)) != 0)
    maybebs = 0;

    /* A boot sector has a power of two as #bytes/sector */
    n = (p[12] << 8) + p[11];
    if (n == 0 || (n & (n-1)) != 0)
    maybebs = 0;

    return maybept - maybebs;

    int main(int argc, char **argv) {
    unsigned char sect[512];
    int fd, n;

    if (argc != 2) {
    fprintf(stderr, "Call: sniffsect file\n");

    fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
    fprintf(stderr, "Cannot open %s\n", argv[1]);

    n = read(fd, sect, sizeof(sect));
    if (n != sizeof(sect)) {
    if (n == -1)
    fprintf(stderr, "Cannot read 512 bytes from %s\n", argv[1]);

    n = sniffsect(sect);
    printf((n == 1) ? "partition table\n" :
    (n == -1) ? "boot sector\n" : "no idea\n");
    return 0;
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to
    More majordomo info at
    Please read the FAQ at

     \ /
      Last update: 2005-03-22 13:48    [W:0.022 / U:28.888 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site