lspart

annotate lspart.c @ 0:29d89c00e611

simple partition table reading test
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 14 Oct 2011 07:45:44 +0300
parents
children 3bd9cfd79fc0
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <string.h>
nuclear@0 4 #include <inttypes.h>
nuclear@0 5 #include <errno.h>
nuclear@0 6 #include <unistd.h>
nuclear@0 7 #include <fcntl.h>
nuclear@0 8 #include "ptype.h"
nuclear@0 9
nuclear@0 10 #define PATTR_ACT_BIT (1 << 9)
nuclear@0 11 #define PATTR_PRIM_BIT (1 << 10)
nuclear@0 12
nuclear@0 13 #define PTYPE(attr) ((attr) & 0xff)
nuclear@0 14 #define IS_ACT(attr) ((attr) & PATTR_ACT_BIT)
nuclear@0 15 #define IS_PRIM(attr) ((attr) & PATTR_PRIM_BIT)
nuclear@0 16
nuclear@0 17 struct partition {
nuclear@0 18 uint32_t start_sect;
nuclear@0 19 size_t size_sect;
nuclear@0 20
nuclear@0 21 unsigned int attr;
nuclear@0 22
nuclear@0 23 struct partition *next;
nuclear@0 24 };
nuclear@0 25
nuclear@0 26 struct part_record {
nuclear@0 27 uint8_t stat;
nuclear@0 28 uint8_t first_head, first_cyl, first_sect;
nuclear@0 29 uint8_t type;
nuclear@0 30 uint8_t last_head, last_cyl, last_sect;
nuclear@0 31 uint32_t first_lba;
nuclear@0 32 uint32_t nsect_lba;
nuclear@0 33 } __attribute__((packed));
nuclear@0 34
nuclear@0 35 static void print_parlist(struct partition *plist);
nuclear@0 36
nuclear@0 37 static struct partition *load_parlist(void);
nuclear@0 38 static uint16_t bootsig(const char *sect);
nuclear@0 39 static int read_sector(void *buf, uint32_t sector);
nuclear@0 40 static const char *printsz(unsigned int sz);
nuclear@0 41 static const char *ptype_name(int type);
nuclear@0 42
nuclear@0 43 int bdev;
nuclear@0 44
nuclear@0 45 int main(int argc, char **argv)
nuclear@0 46 {
nuclear@0 47 struct partition *plist;
nuclear@0 48
nuclear@0 49 if(argc != 2) {
nuclear@0 50 fprintf(stderr, "usage: %s <block device>\n", argv[0]);
nuclear@0 51 return 1;
nuclear@0 52 }
nuclear@0 53
nuclear@0 54 if((bdev = open(argv[1], O_RDONLY)) == -1) {
nuclear@0 55 fprintf(stderr, "failed to open %s: %s\n", argv[1], strerror(errno));
nuclear@0 56 return 1;
nuclear@0 57 }
nuclear@0 58
nuclear@0 59 if((plist = load_parlist())) {
nuclear@0 60 printf("partitions:\n");
nuclear@0 61 print_parlist(plist);
nuclear@0 62 }
nuclear@0 63
nuclear@0 64 return 0;
nuclear@0 65 }
nuclear@0 66
nuclear@0 67 static void print_parlist(struct partition *plist)
nuclear@0 68 {
nuclear@0 69 int idx = 0;
nuclear@0 70
nuclear@0 71 while(plist) {
nuclear@0 72 printf("%d%c ", idx++, IS_ACT(plist->attr) ? '*' : ' ');
nuclear@0 73 printf("(%s) %-20s ", IS_PRIM(plist->attr) ? "pri" : "log", ptype_name(PTYPE(plist->attr)));
nuclear@0 74 printf("start: %-10lu ", (unsigned long)plist->start_sect);
nuclear@0 75 printf("size: %-10lu [%s]\n", (unsigned long)plist->size_sect, printsz(plist->size_sect));
nuclear@0 76 plist = plist->next;
nuclear@0 77 }
nuclear@0 78 }
nuclear@0 79
nuclear@0 80
nuclear@0 81 #define BOOTSIG_OFFS 510
nuclear@0 82 #define PTABLE_OFFS 0x1be
nuclear@0 83
nuclear@0 84 #define BOOTSIG 0xaa55
nuclear@0 85
nuclear@0 86 #define IS_MBR (sidx == 0)
nuclear@0 87 #define IS_FIRST_EBR (!IS_MBR && (first_ebr_offs == 0))
nuclear@0 88 static struct partition *load_parlist(void)
nuclear@0 89 {
nuclear@0 90 char *sect;
nuclear@0 91 struct partition *phead = 0, *ptail = 0;
nuclear@0 92 uint32_t sidx = 0;
nuclear@0 93 uint32_t first_ebr_offs = 0;
nuclear@0 94 int i, num_bootrec = 0;
nuclear@0 95
nuclear@0 96 if(!(sect = malloc(512))) {
nuclear@0 97 perror("failed to allocate sector buffer");
nuclear@0 98 return 0;
nuclear@0 99 }
nuclear@0 100
nuclear@0 101
nuclear@0 102 do {
nuclear@0 103 int num_rec;
nuclear@0 104 struct part_record *prec;
nuclear@0 105
nuclear@0 106 if(IS_FIRST_EBR) {
nuclear@0 107 first_ebr_offs = sidx;
nuclear@0 108 }
nuclear@0 109
nuclear@0 110 if(read_sector(sect, sidx) == -1) {
nuclear@0 111 goto err;
nuclear@0 112 }
nuclear@0 113 if(bootsig(sect) != BOOTSIG) {
nuclear@0 114 fprintf(stderr, "invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx);
nuclear@0 115 goto err;
nuclear@0 116 }
nuclear@0 117 prec = (struct part_record*)(sect + PTABLE_OFFS);
nuclear@0 118
nuclear@0 119 /* MBR has 4 records, EBRs have 2 */
nuclear@0 120 num_rec = IS_MBR ? 4 : 2;
nuclear@0 121
nuclear@0 122 for(i=0; i<num_rec; i++) {
nuclear@0 123 struct partition *pnode;
nuclear@0 124
nuclear@0 125 /* ignore empty partitions in the MBR, stop if encountered in an EBR */
nuclear@0 126 if(prec[i].type == 0) {
nuclear@0 127 if(num_bootrec > 0) {
nuclear@0 128 sidx = 0;
nuclear@0 129 break;
nuclear@0 130 }
nuclear@0 131 continue;
nuclear@0 132 }
nuclear@0 133
nuclear@0 134 /* ignore extended partitions and setup sector index to read
nuclear@0 135 * the next logical partition afterwards.
nuclear@0 136 */
nuclear@0 137 if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) {
nuclear@0 138 /* all EBR start fields are relative to the first EBR offset */
nuclear@0 139 sidx = first_ebr_offs + prec[i].first_lba;
nuclear@0 140 continue;
nuclear@0 141 }
nuclear@0 142
nuclear@0 143 if(!(pnode = malloc(sizeof *pnode))) {
nuclear@0 144 perror("failed to allocate partition list node");
nuclear@0 145 goto err;
nuclear@0 146 }
nuclear@0 147
nuclear@0 148 pnode->attr = prec[i].type;
nuclear@0 149
nuclear@0 150 if(prec[i].stat & 0x80) {
nuclear@0 151 pnode->attr |= PATTR_ACT_BIT;
nuclear@0 152 }
nuclear@0 153 if(IS_MBR) {
nuclear@0 154 pnode->attr |= PATTR_PRIM_BIT;
nuclear@0 155 }
nuclear@0 156 pnode->start_sect = prec[i].first_lba + first_ebr_offs;
nuclear@0 157 pnode->size_sect = prec[i].nsect_lba;
nuclear@0 158 pnode->next = 0;
nuclear@0 159
nuclear@0 160 /* append to the list */
nuclear@0 161 if(!phead) {
nuclear@0 162 phead = ptail = pnode;
nuclear@0 163 } else {
nuclear@0 164 ptail->next = pnode;
nuclear@0 165 ptail = pnode;
nuclear@0 166 }
nuclear@0 167 }
nuclear@0 168
nuclear@0 169 num_bootrec++;
nuclear@0 170 } while(sidx > 0);
nuclear@0 171
nuclear@0 172 free(sect);
nuclear@0 173 return phead;
nuclear@0 174
nuclear@0 175 err:
nuclear@0 176 free(sect);
nuclear@0 177 while(phead) {
nuclear@0 178 void *tmp = phead;
nuclear@0 179 phead = phead->next;
nuclear@0 180 free(tmp);
nuclear@0 181 }
nuclear@0 182 return 0;
nuclear@0 183 }
nuclear@0 184
nuclear@0 185 static uint16_t bootsig(const char *sect)
nuclear@0 186 {
nuclear@0 187 return *(uint16_t*)(sect + BOOTSIG_OFFS);
nuclear@0 188 }
nuclear@0 189
nuclear@0 190 static int read_sector(void *buf, uint32_t sector)
nuclear@0 191 {
nuclear@0 192 if(lseek(bdev, (off_t)sector * 512, SEEK_SET) == -1) {
nuclear@0 193 fprintf(stderr, "read_sector: failed to seek: %s\n", strerror(errno));
nuclear@0 194 return -1;
nuclear@0 195 }
nuclear@0 196 if(read(bdev, buf, 512) != 512) {
nuclear@0 197 fprintf(stderr, "failed to read sector %lu: %s\n", (unsigned long)sector, strerror(errno));
nuclear@0 198 return -1;
nuclear@0 199 }
nuclear@0 200 return 0;
nuclear@0 201 }
nuclear@0 202
nuclear@0 203 const char *printsz(unsigned int sz)
nuclear@0 204 {
nuclear@0 205 int i = 0;
nuclear@0 206 const char *suffix[] = { "kb", "mb", "gb", "tb", "pb", 0 };
nuclear@0 207 static char buf[512];
nuclear@0 208
nuclear@0 209 while(sz > 1024 && suffix[i + 1]) {
nuclear@0 210 sz /= 1024;
nuclear@0 211 i++;
nuclear@0 212 }
nuclear@0 213
nuclear@0 214 sprintf(buf, "%u %s", sz, suffix[i]);
nuclear@0 215 return buf;
nuclear@0 216 }
nuclear@0 217
nuclear@0 218 static const char *ptype_name(int type)
nuclear@0 219 {
nuclear@0 220 int i;
nuclear@0 221
nuclear@0 222 for(i=0; i<PTYPES_SIZE; i++) {
nuclear@0 223 if(partypes[i].type == type) {
nuclear@0 224 return partypes[i].name;
nuclear@0 225 }
nuclear@0 226 }
nuclear@0 227 return "unknown";
nuclear@0 228 }