lspart

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