lspart
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/lspart.c Fri Oct 14 07:45:44 2011 +0300 1.3 @@ -0,0 +1,228 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <inttypes.h> 1.8 +#include <errno.h> 1.9 +#include <unistd.h> 1.10 +#include <fcntl.h> 1.11 +#include "ptype.h" 1.12 + 1.13 +#define PATTR_ACT_BIT (1 << 9) 1.14 +#define PATTR_PRIM_BIT (1 << 10) 1.15 + 1.16 +#define PTYPE(attr) ((attr) & 0xff) 1.17 +#define IS_ACT(attr) ((attr) & PATTR_ACT_BIT) 1.18 +#define IS_PRIM(attr) ((attr) & PATTR_PRIM_BIT) 1.19 + 1.20 +struct partition { 1.21 + uint32_t start_sect; 1.22 + size_t size_sect; 1.23 + 1.24 + unsigned int attr; 1.25 + 1.26 + struct partition *next; 1.27 +}; 1.28 + 1.29 +struct part_record { 1.30 + uint8_t stat; 1.31 + uint8_t first_head, first_cyl, first_sect; 1.32 + uint8_t type; 1.33 + uint8_t last_head, last_cyl, last_sect; 1.34 + uint32_t first_lba; 1.35 + uint32_t nsect_lba; 1.36 +} __attribute__((packed)); 1.37 + 1.38 +static void print_parlist(struct partition *plist); 1.39 + 1.40 +static struct partition *load_parlist(void); 1.41 +static uint16_t bootsig(const char *sect); 1.42 +static int read_sector(void *buf, uint32_t sector); 1.43 +static const char *printsz(unsigned int sz); 1.44 +static const char *ptype_name(int type); 1.45 + 1.46 +int bdev; 1.47 + 1.48 +int main(int argc, char **argv) 1.49 +{ 1.50 + struct partition *plist; 1.51 + 1.52 + if(argc != 2) { 1.53 + fprintf(stderr, "usage: %s <block device>\n", argv[0]); 1.54 + return 1; 1.55 + } 1.56 + 1.57 + if((bdev = open(argv[1], O_RDONLY)) == -1) { 1.58 + fprintf(stderr, "failed to open %s: %s\n", argv[1], strerror(errno)); 1.59 + return 1; 1.60 + } 1.61 + 1.62 + if((plist = load_parlist())) { 1.63 + printf("partitions:\n"); 1.64 + print_parlist(plist); 1.65 + } 1.66 + 1.67 + return 0; 1.68 +} 1.69 + 1.70 +static void print_parlist(struct partition *plist) 1.71 +{ 1.72 + int idx = 0; 1.73 + 1.74 + while(plist) { 1.75 + printf("%d%c ", idx++, IS_ACT(plist->attr) ? '*' : ' '); 1.76 + printf("(%s) %-20s ", IS_PRIM(plist->attr) ? "pri" : "log", ptype_name(PTYPE(plist->attr))); 1.77 + printf("start: %-10lu ", (unsigned long)plist->start_sect); 1.78 + printf("size: %-10lu [%s]\n", (unsigned long)plist->size_sect, printsz(plist->size_sect)); 1.79 + plist = plist->next; 1.80 + } 1.81 +} 1.82 + 1.83 + 1.84 +#define BOOTSIG_OFFS 510 1.85 +#define PTABLE_OFFS 0x1be 1.86 + 1.87 +#define BOOTSIG 0xaa55 1.88 + 1.89 +#define IS_MBR (sidx == 0) 1.90 +#define IS_FIRST_EBR (!IS_MBR && (first_ebr_offs == 0)) 1.91 +static struct partition *load_parlist(void) 1.92 +{ 1.93 + char *sect; 1.94 + struct partition *phead = 0, *ptail = 0; 1.95 + uint32_t sidx = 0; 1.96 + uint32_t first_ebr_offs = 0; 1.97 + int i, num_bootrec = 0; 1.98 + 1.99 + if(!(sect = malloc(512))) { 1.100 + perror("failed to allocate sector buffer"); 1.101 + return 0; 1.102 + } 1.103 + 1.104 + 1.105 + do { 1.106 + int num_rec; 1.107 + struct part_record *prec; 1.108 + 1.109 + if(IS_FIRST_EBR) { 1.110 + first_ebr_offs = sidx; 1.111 + } 1.112 + 1.113 + if(read_sector(sect, sidx) == -1) { 1.114 + goto err; 1.115 + } 1.116 + if(bootsig(sect) != BOOTSIG) { 1.117 + fprintf(stderr, "invalid/corrupted partition table, sector %lu has no magic\n", (unsigned long)sidx); 1.118 + goto err; 1.119 + } 1.120 + prec = (struct part_record*)(sect + PTABLE_OFFS); 1.121 + 1.122 + /* MBR has 4 records, EBRs have 2 */ 1.123 + num_rec = IS_MBR ? 4 : 2; 1.124 + 1.125 + for(i=0; i<num_rec; i++) { 1.126 + struct partition *pnode; 1.127 + 1.128 + /* ignore empty partitions in the MBR, stop if encountered in an EBR */ 1.129 + if(prec[i].type == 0) { 1.130 + if(num_bootrec > 0) { 1.131 + sidx = 0; 1.132 + break; 1.133 + } 1.134 + continue; 1.135 + } 1.136 + 1.137 + /* ignore extended partitions and setup sector index to read 1.138 + * the next logical partition afterwards. 1.139 + */ 1.140 + if(prec[i].type == PTYPE_EXT || prec[i].type == PTYPE_EXT_LBA) { 1.141 + /* all EBR start fields are relative to the first EBR offset */ 1.142 + sidx = first_ebr_offs + prec[i].first_lba; 1.143 + continue; 1.144 + } 1.145 + 1.146 + if(!(pnode = malloc(sizeof *pnode))) { 1.147 + perror("failed to allocate partition list node"); 1.148 + goto err; 1.149 + } 1.150 + 1.151 + pnode->attr = prec[i].type; 1.152 + 1.153 + if(prec[i].stat & 0x80) { 1.154 + pnode->attr |= PATTR_ACT_BIT; 1.155 + } 1.156 + if(IS_MBR) { 1.157 + pnode->attr |= PATTR_PRIM_BIT; 1.158 + } 1.159 + pnode->start_sect = prec[i].first_lba + first_ebr_offs; 1.160 + pnode->size_sect = prec[i].nsect_lba; 1.161 + pnode->next = 0; 1.162 + 1.163 + /* append to the list */ 1.164 + if(!phead) { 1.165 + phead = ptail = pnode; 1.166 + } else { 1.167 + ptail->next = pnode; 1.168 + ptail = pnode; 1.169 + } 1.170 + } 1.171 + 1.172 + num_bootrec++; 1.173 + } while(sidx > 0); 1.174 + 1.175 + free(sect); 1.176 + return phead; 1.177 + 1.178 +err: 1.179 + free(sect); 1.180 + while(phead) { 1.181 + void *tmp = phead; 1.182 + phead = phead->next; 1.183 + free(tmp); 1.184 + } 1.185 + return 0; 1.186 +} 1.187 + 1.188 +static uint16_t bootsig(const char *sect) 1.189 +{ 1.190 + return *(uint16_t*)(sect + BOOTSIG_OFFS); 1.191 +} 1.192 + 1.193 +static int read_sector(void *buf, uint32_t sector) 1.194 +{ 1.195 + if(lseek(bdev, (off_t)sector * 512, SEEK_SET) == -1) { 1.196 + fprintf(stderr, "read_sector: failed to seek: %s\n", strerror(errno)); 1.197 + return -1; 1.198 + } 1.199 + if(read(bdev, buf, 512) != 512) { 1.200 + fprintf(stderr, "failed to read sector %lu: %s\n", (unsigned long)sector, strerror(errno)); 1.201 + return -1; 1.202 + } 1.203 + return 0; 1.204 +} 1.205 + 1.206 +const char *printsz(unsigned int sz) 1.207 +{ 1.208 + int i = 0; 1.209 + const char *suffix[] = { "kb", "mb", "gb", "tb", "pb", 0 }; 1.210 + static char buf[512]; 1.211 + 1.212 + while(sz > 1024 && suffix[i + 1]) { 1.213 + sz /= 1024; 1.214 + i++; 1.215 + } 1.216 + 1.217 + sprintf(buf, "%u %s", sz, suffix[i]); 1.218 + return buf; 1.219 +} 1.220 + 1.221 +static const char *ptype_name(int type) 1.222 +{ 1.223 + int i; 1.224 + 1.225 + for(i=0; i<PTYPES_SIZE; i++) { 1.226 + if(partypes[i].type == type) { 1.227 + return partypes[i].name; 1.228 + } 1.229 + } 1.230 + return "unknown"; 1.231 +}