1 /* partition.c - Partition table handling
3 * Copyright 1992-1998 Werner Almesberger
4 * Copyright 1999-2005 John Coffman
5 * Copyright 2009-2013 Joachim Wiedorn
8 * Licensed under the terms contained in the file 'COPYING'
9 * in the source directory.
20 #include <sys/types.h>
30 #include "partition.h"
34 #if __GLIBC__ < 2 || __GLIBC_MINOR__ < 1
35 #if defined(_syscall5) && defined(__NR__llseek)
37 _syscall5(int, _llseek, unsigned int, fd, unsigned int, hi,
38 unsigned int, lo, lloff_t *, res, unsigned int, wh);
39 int _llseek(unsigned int fd, unsigned int offset_high,
40 unsigned int offset_low, lloff_t * result, unsigned int whence);
42 lloff_t lseek64(unsigned int fd, lloff_t offs, unsigned int whence)
44 return _llseek(fd, offs>>32, offs, &res, whence) < 0 ?
49 /* last ditch attempt on small disks, and very old systems */
50 # warning "*****************************************"
51 # warning "***** no 64 bit lseek is available ******"
52 # warning "***** using 23 bit sector addresses *****"
53 # warning "*****************************************"
54 # define lseek64 lseek
59 int anywhere(unsigned char *buf, char *str)
66 s = memchr(buf, *str, n);
68 if (!strncmp(s, str, k)) return 1;
70 n = SECTOR_SIZE - k - (int)(s-(char*)buf);
71 s = memchr(s, *str, n);
78 /* identify partitions which would be destroyed if the boot block
81 known problems occur for:
84 DOS FAT (relocation will fix)
87 int part_nowrite(char* device)
92 int ret=PTW_OKAY; /* say ok, unless we recognize a problem partition */
93 if ( !(do_md_install && extra==X_MBR_ONLY) ) {
94 if ((fd = open(device, O_RDONLY)) < 0) pdie("part_nowrite check:");
95 if (read(fd, bs.sector, sizeof(bs)) != SECTOR_SIZE) pdie("part_nowrite: read:");
98 if (!strncmp("XFSB", (char*)bs.sector, 4)) ret=PTW_XFS;
101 else if ( !strncmp("NTFS", bs.par_d.system, 4)
102 || anywhere(bs.sector,"NTLDR") ) ret=PTW_NTFS;
104 /* do not check for obsolete OS2_HPFS */
105 /* else if ( !strncmp("OS2", bs.par_d.system, 3)
106 || anywhere(bs.sector,"OS2LDR") ) ret=PTW_OS2; */
108 /* check for DOS FAT */
110 (bs.par_d.bpb.media_descriptor >= 0xF8 || bs.par_d.bpb.media_descriptor == 0xF0)
111 && *(short*)bs.par_d.bpb.bytes_per_sector == SECTOR_SIZE
112 && (bs.par_d.bpb.number_of_FATs==1 || bs.par_d.bpb.number_of_FATs==2)
113 /* sectors_per_cluster is a power of 2, meaning only 1 bit is on */
114 && bs.par_d.bpb.sectors_per_cluster
115 && (bs.par_d.bpb.sectors_per_cluster & (bs.par_d.bpb.sectors_per_cluster-1))==0
120 /* check for SWAP -- last check, as 'bs' is overwritten */
121 else if (*(int*)bs.sector == 0xFFFFFFFEU) {
122 if (lseek(fd, (PAGE_SIZE)-SECTOR_SIZE, SEEK_SET) != (PAGE_SIZE)-SECTOR_SIZE)
123 pdie("part_nowrite lseek:");
124 if (SECTOR_SIZE != read(fd, bs.sector, sizeof(bs)) ) pdie("part_nowrite swap check:");
125 if (!strncmp((char*)bs.sector+SECTOR_SIZE-10,"SWAPSPACE2",10)
126 || !strncmp((char*)bs.sector+SECTOR_SIZE-10,"SWAP-SPACE",10) ) ret=PTW_SWAP;
129 /* didn't recognize the superblock type, so assume it is okay */
134 } /* raid install with X_MBR_ONLY in use */
135 if (verbose>=6) printf("part_nowrite: %d\n", ret);
141 void part_verify(int dev_nr,int type)
145 char backup_file[PATH_MAX+1];
146 int fd, bck_file, part, size, lin_3d, cyl;
147 unsigned int second, base;
148 struct partition part_table[PART_MAX];
149 int mask, i, pe, Linux, dos, mbr;
150 unsigned short boot_sig;
153 if (!has_partitions(dev_nr) || !(mask = P_MASK(dev_nr)) || !(dev_nr & mask)
155 || (dev_nr & mask) > PART_MAX
159 if (verbose >= 4) printf("part_verify: dev_nr=%04x, type=%d\n", dev_nr, type);
160 geo_get(&geo,dev_nr & ~mask,-1,1);
161 fd = dev_open(&dev,dev_nr & ~mask,cfg_get_flag(cf_options,"fix-table")
162 && !test ? O_RDWR : O_RDONLY);
163 part = (pe = dev_nr & mask)-1;
166 if (lseek(fd, 0L, SEEK_SET) != 0 ||
167 read(fd, &bs, sizeof(bs)) != sizeof(bs) ) pdie("bs read");
168 if (*(int*)bs.signature==EX_MAG_HL) mbr = bs.stage;
169 else mbr = STAGE_MBR;
170 } else mbr = STAGE_MBR;
172 if (lseek(fd, PART_TABLE_OFFSET, SEEK_SET) < 0) pdie("lseek partition table");
173 if (!(size = read(fd,(char *) part_table, sizeof(struct partition)*
174 PART_MAX))) die("Short read on partition table");
175 if (size < 0) pdie("read partition table");
176 if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig) ||
177 boot_sig != BOOT_SIGNATURE ) die("read boot signature failed");
179 if (verbose>=5) printf("part_verify: part#=%d\n", pe);
182 for (i=0; i<PART_MAX; i++) {
183 if (is_extd_part(part_table[i].sys_ind)) {
184 if (!base) base = part_table[i].start_sect;
185 else die("invalid partition table: second extended partition found");
189 while (i<=pe && base) {
190 if (lseek64(fd, LLSECTORSIZE*(base+second) + PART_TABLE_OFFSET, SEEK_SET) < 0)
191 die("secondary lseek64 failed");
192 if (read(fd, part_table, sizeof(part_table)) != sizeof(part_table)) die("secondary read pt failed");
193 if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig) ||
194 boot_sig != BOOT_SIGNATURE ) die("read second boot signature failed");
195 if (is_extd_part(part_table[1].sys_ind)) second=part_table[1].start_sect;
201 if (type && pe>0 && pe<=(mbr==STAGE_MBR2?63:PART_MAX)
202 && !(part_table[part].boot_ind&0x80) )
203 warn("Partition %d on %s is not marked Active.",
206 i = part_table[part].sys_ind;
208 Linux = i == PART_LINUX_MINIX ||
209 i == PART_LINUX_NATIVE ||
210 i == PART_LINUX_LVM ||
214 dos = i == PART_DOS12 ||
215 i == PART_DOS16_SMALL ||
216 i == PART_DOS16_BIG ||
218 i == PART_FAT32_LBA ||
219 i == PART_FAT16_LBA ||
222 if (type && !Linux) {
223 warn("partition type 0x%02X"" on device 0x%04X is a dangerous place for\n"
225 part_table[part].sys_ind, dev_nr,
226 dos ? " A DOS/Windows system may be rendered unbootable."
227 "\n The backup copy of this boot sector should be retained."
230 if (!dos && !cfg_get_flag(cf_options,"ignore-table"))
231 die("You may proceed by using either '-P ignore' or 'ignore-table'");
233 if (!yesno("\nProceed? ", 0)) exit(0);
236 cyl = part_table[part].cyl+((part_table[part].sector >> 6) << 8);
237 lin_3d = (part_table[part].sector & 63)-1+(part_table[part].head+
238 cyl*geo.heads)*geo.sectors;
239 if (pe <= PART_MAX &&
240 (lin_3d > part_table[part].start_sect || (lin_3d <
241 part_table[part].start_sect && cyl != BIOS_MAX_CYLS-1)) ) {
242 warn("Device 0x%04X: Inconsistent partition table, %d%s entry",
243 dev_nr & ~mask,part+1,!part ? "st" : part == 1 ? "nd" : part ==
246 fprintf(errstd," CHS address in PT: %d:%d:%d --> LBA (%d)\n",
248 part_table[part].head,
249 part_table[part].sector & 63,
251 cyl = part_table[part].start_sect/geo.sectors/geo.heads;
253 fprintf(errstd," LBA address in PT: %d --> CHS (%d:%d:%d)\n",
254 part_table[part].start_sect,
256 part_table[part].head = (part_table[part].start_sect/geo.sectors) % geo.heads,
257 part_table[part].sector = (part_table[part].start_sect % geo.sectors)+1
259 if (cyl >= BIOS_MAX_CYLS) cyl = BIOS_MAX_CYLS-1;
260 part_table[part].sector |= (cyl >> 8)<<6;
261 part_table[part].cyl = cyl & 0xff;
262 if (!cfg_get_flag(cf_options,"fix-table") && !cfg_get_flag(cf_options,
263 "ignore-table")) die("Either FIX-TABLE or IGNORE-TABLE must be specified\n"
264 "If not sure, first try IGNORE-TABLE (-P ignore)");
265 if (test || cfg_get_flag(cf_options,"ignore-table")) {
266 warn("The partition table is *NOT* being adjusted.");
268 sprintf(backup_file,BACKUP_DIR "/part.%04X",dev_nr & ~mask);
269 if ((bck_file = creat(backup_file,0644)) < 0)
270 die("creat %s: %s",backup_file,strerror(errno));
271 if (!(size = write(bck_file,(char *) part_table,
272 sizeof(struct partition)*PART_MAX)))
273 die("Short write on %s",backup_file);
274 if (size < 0) pdie(backup_file);
275 if (close(bck_file) < 0)
276 die("close %s: %s",backup_file,strerror(errno));
278 printf("Backup copy of partition table in %s\n",backup_file);
279 printf("Writing modified partition table to device 0x%04X\n",
281 if (lseek(fd,PART_TABLE_OFFSET,SEEK_SET) < 0)
282 pdie("lseek partition table");
283 if (!(size = write(fd,(char *) part_table,sizeof(struct partition)*
284 PART_MAX))) die("Short write on partition table");
285 if (size < 0) pdie("write partition table");
292 CHANGE_RULE *change_rules = NULL;
295 void do_cr_reset(void)
299 while (change_rules) {
300 next = change_rules->next;
301 free((char *) change_rules->type);
308 static unsigned char cvt_byte(const char *s)
313 value = strtoul(s,&end,0);
314 if (value > 255 || *end) cfg_error("\"%s\" is not a byte value",s);
319 static void add_type(const char *type,int normal,int hidden)
323 for (rule = change_rules; rule; rule = rule->next)
324 if (!strcasecmp(rule->type,type))
325 die("Duplicate type name: \"%s\"",type);
326 rule = alloc_t(CHANGE_RULE);
327 rule->type = stralloc(type);
328 rule->normal = normal == -1 ? hidden ^ HIDDEN_OFF : normal;
329 rule->hidden = hidden == -1 ? normal ^ HIDDEN_OFF : hidden;
330 rule->next = change_rules;
335 void do_cr_type(void)
337 const char *normal,*hidden;
339 cfg_init(cf_change_rule);
340 (void) cfg_parse(cf_change_rule);
341 normal = cfg_get_strg(cf_change_rule,"normal");
342 hidden = cfg_get_strg(cf_change_rule,"hidden");
344 add_type(cfg_get_strg(cf_change_rules,"type"),cvt_byte(normal),
345 hidden ? cvt_byte(hidden) : -1);
348 cfg_error("At least one of NORMAL and HIDDEN must be present");
349 add_type(cfg_get_strg(cf_change_rules,"type"),cvt_byte(hidden),-1);
351 cfg_unset(cf_change_rules,"type");
357 cfg_init(cf_change_rules);
358 (void) cfg_parse(cf_change_rules);
362 #if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
367 * +------+------+------+------+
368 * |drive |offset|expect| set |
369 * +------+------+------+------+
373 static void add_rule(unsigned char bios,unsigned char offset,
374 unsigned char expect,unsigned char set)
378 if (curr_prt_map == PRTMAP_SIZE)
379 cfg_error("Too many change rules (more than %d)",PRTMAP_SIZE);
381 printf(" Adding rule: disk 0x%02x, offset 0x%x, 0x%02x -> 0x%02x\n",
382 bios,PART_TABLE_OFFSET+offset,expect,set);
383 prt_map[curr_prt_map] = (set << 24) | (expect << 16) | (offset << 8) | bios;
384 for (i = 0; i < curr_prt_map; i++) {
385 if (prt_map[i] == prt_map[curr_prt_map])
386 die("Repeated rule: disk 0x%02x, offset 0x%x, 0x%02x -> 0x%02x",
387 bios,PART_TABLE_OFFSET+offset,expect,set);
388 if ((prt_map[i] & 0xffff) == ((offset << 8) | bios) &&
389 (prt_map[i] >> 24) == expect)
390 die("Redundant rule: disk 0x%02x, offset 0x%x: 0x%02x -> 0x%02x "
391 "-> 0x%02x",bios,PART_TABLE_OFFSET+offset,
392 (prt_map[i] >> 16) & 0xff,expect,set);
400 static int has_partition;
402 static CHANGE_RULE *may_change(unsigned char sys_ind)
404 CHANGE_RULE *cr = change_rules;
407 if (cr->normal == sys_ind || cr->hidden == sys_ind) return cr;
414 void do_cr_auto(void)
418 char *table, *table2, *other;
419 int partition, pfd, i, j;
420 struct partition part_table[PART_MAX];
422 if (autoauto) has_partition = 0;
423 other = identify ? cfg_get_strg(cf_identify, "other")
424 : cfg_get_strg(cf_top, "other");
425 if (verbose > 4) printf("do_cr_auto: other=%s has_partition=%d\n",
426 other, has_partition);
428 i = other[strlen(other)-1] - '0';
429 if (i>PART_MAX || i<1) return;
431 table = cfg_get_strg(cf_other,"table");
432 table2 = boot_mbr(other, 1); /* get possible default */
433 if (!table) table = table2;
435 if (!table && autoauto) return;
436 if (table && autoauto && !table2) cfg_error("TABLE may not be specified");
438 if (has_partition) cfg_error("AUTOMATIC must be before PARTITION");
439 if (!table) cfg_error("TABLE must be set to use AUTOMATIC");
442 if (stat(table,&st) < 0) die("stat %s: %s",table,strerror(errno));
443 geo_get(&geo,st.st_rdev & D_MASK(st.st_rdev),-1,1);
444 partition = st.st_rdev & P_MASK(st.st_rdev);
445 if (!S_ISBLK(st.st_mode) || partition)
446 cfg_error("\"%s\" doesn't contain a primary partition table",table);
447 pfd = open(table, O_RDONLY);
448 if (pfd<0) die("Cannot open %s", table);
449 if (lseek(pfd, PART_TABLE_OFFSET, SEEK_SET)!=PART_TABLE_OFFSET)
450 die("Cannot seek to partition table of %s", table);
451 if (read(pfd, part_table, sizeof(part_table))!=sizeof(part_table))
452 die("Cannot read Partition Table of %s", table);
454 partition = other[strlen(other)-1] - '0';
455 if (verbose > 3) printf("partition = %d\n", partition);
456 for (j=i=0; i<PART_MAX; i++)
457 if (may_change(part_table[i].sys_ind)) j++;
460 #if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
461 for (i=0; i<PART_MAX; i++) {
463 if ((cr=may_change(part_table[i].sys_ind))) {
464 j = i*PARTITION_ENTRY + PART_TYPE_ENT_OFF;
466 warn("CHANGE AUTOMATIC assumed after \"other=%s\"", other);
467 autoauto = 0; /* suppress further warnings */
469 if (i == partition-1)
470 add_rule(geo.device, j, cr->hidden, cr->normal);
472 add_rule(geo.device, j, cr->normal, cr->hidden);
476 warn("This LILO is compiled without REWRITE_TABLE;\n"
477 " unable to generate CHANGE/AUTOMATIC change-rules");
483 void do_cr_part(void)
488 int partition,part_base;
490 tmp = cfg_get_strg(cf_change,"partition");
491 if (stat(tmp,&st) < 0) die("stat %s: %s",tmp,strerror(errno));
492 geo_get(&geo,st.st_rdev & D_MASK(st.st_rdev),-1,1);
493 partition = st.st_rdev & P_MASK(st.st_rdev);
494 if (!S_ISBLK(st.st_mode) || !partition || partition > PART_MAX)
495 cfg_error("\"%s\" isn't a primary partition",tmp);
496 part_base = (partition-1)*PARTITION_ENTRY;
498 cfg_init(cf_change_dsc);
499 (void) cfg_parse(cf_change_dsc);
500 tmp = cfg_get_strg(cf_change_dsc,"set");
502 #if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
507 here = (void*)NULL; /* quiet GCC */
508 hidden = 0; /* quiet GCC */
509 if (strlen(tmp) < 7 || !(here = strrchr(tmp,'_')) ||
510 ((hidden = strcasecmp(here+1,"normal")) &&
511 strcasecmp(here+1,"hidden")))
512 cfg_error("Type name must end with _normal or _hidden");
514 for (walk = change_rules; walk; walk = walk->next)
515 if (!strcasecmp(walk->type,tmp)) break;
516 if (!walk) cfg_error("Unrecognized type name");
517 add_rule(geo.device,part_base+PART_TYPE_ENT_OFF,hidden ? walk->normal :
518 walk->hidden,hidden ? walk->hidden : walk->normal);
520 die("This LILO is compiled without REWRITE_TABLE and doesn't support "
524 if (cfg_get_flag(cf_change_dsc,"activate")) {
525 #if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
526 add_rule(geo.device,part_base+PART_ACT_ENT_OFF,0x00,0x80);
527 if (cfg_get_flag(cf_change_dsc,"deactivate"))
528 cfg_error("ACTIVATE and DEACTIVATE are incompatible");
530 die("This LILO is compiled without REWRITE_TABLE and doesn't support "
531 "the ACTIVATE option");
534 if (cfg_get_flag(cf_change_dsc,"deactivate"))
535 #if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
536 add_rule(geo.device,part_base+PART_ACT_ENT_OFF,0x80,0x00);
538 die("This LILO is compiled without REWRITE_TABLE and doesn't support "
539 "the DEACTIVATE option");
541 cfg_unset(cf_change,"partition");
549 (void) cfg_parse(cf_change);
553 void preload_types(void)
555 /* add_type("OS2_HPFS", 0x07, 0x17); */
556 add_type("FAT16_lba", PART_FAT16_LBA, -1);
557 add_type("FAT32_lba", PART_FAT32_LBA, -1);
558 add_type("FAT32", PART_FAT32, -1);
559 add_type("NTFS", PART_NTFS, -1);
560 add_type("DOS16_big", PART_DOS16_BIG, -1);
561 add_type("DOS16_small", PART_DOS16_SMALL, -1);
562 add_type("DOS12", PART_DOS12, -1);
567 #define PART_BEGIN 0x1be
570 #define PART_ACTIVE 0x80
571 #define PART_INACTIVE 0
574 void do_activate(char *part, char *which)
577 int part_max, count, number, fd;
578 struct partition pt [PART_MAX_MAX+1];
579 long long daddr [PART_MAX_MAX+1];
582 part_max = read_partitions(part, extended_pt ? PART_MAX_MAX : 0,
584 /* printf("part_max=%d\n", part_max); */
585 if (!which) { /* one argument: display active partition */
586 for (count=0; count < part_max; count++) {
587 if (pt[count].boot_ind) {
588 printf("%s%d\n",part,count+1);
592 printf("No active partition found on %s\n",part);
595 number = to_number(which);
596 if (number < 0 || number > part_max)
597 die("%s: not a valid partition number (1-%d)",which,part_max);
599 if (number && !pt[number-1].sys_ind) die("Cannot activate an empty partition");
600 number--; /* we are zero-based from here on */
602 if ((fd = open(part, O_RDWR)) < 0)
603 die("open %s: %s",part,strerror(errno));
604 for (count=0; count<part_max; count++) {
605 unsigned char flag = count==number ? PART_ACTIVE : PART_INACTIVE;
606 if (pt[count].sys_ind && pt[count].boot_ind != flag) {
607 pt[count].boot_ind = flag;
608 printf("pt[%d] -> %2x\n", count+1, (int)flag);
609 if (lseek64(fd, daddr[count], SEEK_SET) < 0) die("PT lseek64 failed");
611 if (write(fd, &pt[count], sizeof(pt[0])) != sizeof(pt[0]) )
612 die("PT write failure");
618 printf("The partition table has%s been updated.\n", test ? " *NOT*" : "");
620 printf("No partition table modifications are needed.\n");
624 unsigned char flag, ptype;
626 if ((fd = open(part, !which ? O_RDONLY : O_RDWR)) < 0)
627 die("open %s: %s",part,strerror(errno));
628 if (fstat(fd,&st) < 0) die("stat %s: %s",part,strerror(errno));
629 if (!S_ISBLK(st.st_mode)) die("%s: not a block device",part);
631 printf("st.st_dev = %04X, st.st_rdev = %04X\n",
632 (int)st.st_dev, (int)st.st_rdev);
634 if ((st.st_rdev & has_partitions(st.st_rdev)) != st.st_rdev)
635 die("%s is not a master device with a primary partition table", part);
636 if (!which) { /* one argument: display active partition */
637 for (count = 1; count <= PART_NUM; count++) {
638 if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE,SEEK_SET) < 0)
639 die("lseek: %s",strerror(errno));
640 if (read(fd,&flag,1) != 1) die("read: %s",strerror(errno));
641 if (flag == PART_ACTIVE) {
642 printf("%s%d\n",part,count);
646 die("No active partition found on %s",part);
648 number = to_number(which);
649 if (number < 0 || number > 4)
650 die("%s: not a valid partition number (1-4)",which);
651 for (count = 1; count <= PART_NUM; count++) {
652 if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE+4,SEEK_SET) < 0)
653 die("lseek: %s",strerror(errno));
654 if (read(fd,&ptype,1) != 1) die("read: %s",strerror(errno));
655 if (count == number && ptype==0) die("Cannot activate an empty partition");
658 printf("The partition table of %s has *NOT* been updated\n",part);
660 else for (count = 1; count <= PART_NUM; count++) {
661 if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE,SEEK_SET) < 0)
662 die("lseek: %s",strerror(errno));
663 flag = count == number ? PART_ACTIVE : PART_INACTIVE;
664 if (write(fd,&flag,1) != 1) die("write: %s",strerror(errno));
671 void do_install_mbr(char *part, char *what)
681 if (!what) what = DFL_MBR;
682 extended_pt |= !!strchr(what,'x') || !!strchr(what,'X') || !!strchr(what,'2');
683 if ((fd=open(part,O_RDWR)) < 0) die("Cannot open %s: %s", part,strerror(errno));
684 if (fstat(fd,&st) < 0) die("stat: %s : %s", part,strerror(errno));
685 if (!S_ISBLK(st.st_mode) && !force_fs) die("%s not a block device",part);
686 if (st.st_rdev != (st.st_rdev & has_partitions(st.st_rdev)))
687 die("%s is not a master device with a primary parition table",part);
688 if (read(fd,&buf,SECTOR_SIZE) != SECTOR_SIZE) die("read %s: %s",part, strerror(errno));
690 cp = cfg_get_strg(cf_options,"force-backup");
692 if (!cp) cp = cfg_get_strg(cf_options,"backup");
693 make_backup(cp, i, &buf, st.st_rdev, part);
696 if ((nfd=open(what,O_RDONLY)) < 0) die("Cannot open %s: %s",what,strerror(errno));
697 if (read(nfd,buf,MAX_BOOT_SIZE) != MAX_BOOT_SIZE) die("read %s: %s",what,strerror(errno));
699 memcpy(&buf, extended_pt ? Mbr2.data : Mbr.data, MAX_BOOT_SIZE);
701 buf.boot.boot_ind = BOOT_SIGNATURE;
705 buf.boot.volume_id = 0;
707 if ((cp=cfg_get_strg(cf_options,RAID_EXTRA_BOOT))) {
708 buf.boot.volume_id = strtoul(cp, NULL, 16);
711 } else if (buf.boot.volume_id == 0) {
714 i %= PRIME; /* modulo a prime number; eg, 2551, 9091 */
716 srand(time(NULL)); /* seed the random number generator */
718 *(int*)&buf[PART_TABLE_OFFSET - 6] = rand(); /* insert serial number */
719 if (*(short*)&buf[PART_TABLE_OFFSET - 2] == 0)
720 *(short*)&buf[PART_TABLE_OFFSET - 2] = MAGIC_SERIAL;
722 buf.boot.volume_id = new_serial(st.st_rdev);
723 buf.boot.marker = MAGIC_SERIAL;
727 if (lseek(fd,0,SEEK_SET) != 0) die("seek %s; %s", part, strerror(errno));
729 if (write(fd,&buf,SECTOR_SIZE) != SECTOR_SIZE)
730 die("write %s: %s",part,strerror(errno));
736 printf("The Master Boot Record of %s has %sbeen updated.\n", part, test ? "*NOT* " : "");
742 /* partition table read */
743 int read_partitions(char *part, int max, int *volid,
744 struct partition *p, long long *where)
747 unsigned int second, base;
748 unsigned short boot_sig;
749 struct partition pt[PART_MAX];
754 if ((fd=open(part,O_RDONLY))<0) die("Cannot open '%s'", part);
755 if (fstat(fd,&st)<0) die("Cannot fstat '%s'", part);
756 if (!S_ISBLK(st.st_mode)) die("Not a block device '%s'", part);
758 if (!has_partitions(i) || (P_MASK(i)&i) )
759 die("Not a device with partitions '%s'", part);
761 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) die("read header");
762 if (!strncmp(hdr.signature, "LILO", 4) && hdr.stage == STAGE_MBR2 &&
763 max == 0) max = PART_MAX_MAX;
764 else if (max == 0) max = PART_MAX;
765 if (lseek(fd, PART_TABLE_OFFSET, SEEK_SET)<0) die("lseek failed");
766 if (read(fd, pt, sizeof(pt)) != sizeof(pt)) die("read pt failed");
767 if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig) ||
768 boot_sig != BOOT_SIGNATURE ) die("read boot signature failed");
770 if (lseek(fd, MAX_BOOT_SIZE+2, SEEK_SET)<0) die("lseek vol-ID failed");
771 if (read(fd, volid, sizeof(*volid)) != sizeof(*volid))
772 die("read vol-ID failed");
773 /* printf(" vol-ID: %08X\n", second); */
775 /* printf("%s\n", phead); */
778 for (i=0; i<PART_MAX; i++) {
779 /* print_pt(i+1, pt[i]); */
780 if (is_extd_part(pt[i].sys_ind)) {
781 if (!base) base = pt[i].start_sect;
782 else die("invalid partition table: second extended partition found");
784 if (where) *where++ = PART_TABLE_OFFSET + i*sizeof(*p);
792 daddr = LLSECTORSIZE*(base+second) + PART_TABLE_OFFSET;
793 if (lseek64(fd, daddr, SEEK_SET) < 0)
794 die("secondary lseek64 failed");
795 if (read(fd, pt, sizeof(pt)) != sizeof(pt)) die("secondary read pt failed");
796 if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig) ||
797 boot_sig != BOOT_SIGNATURE ) die("read second boot signature failed");
798 /* print_pt(i++, pt[0]); */
799 if (is_extd_part(pt[1].sys_ind)) second=pt[1].start_sect;
803 if (where) *where++ = daddr;
809 if (where) *where = 0;