1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdint.h> 4 #include <errno.h> 5 #include <sys/stat.h> 6 #include <sys/bootblock.h> 7 #include <fcntl.h> 8 #include <unistd.h> 9 #include <string.h> 10 11 #ifndef DFL_SECSIZE 12 #define DFL_SECSIZE 512 13 #endif 14 15 #define MFS_FIRST_SUBP_OFFSET 32 16 17 static int minixfs3_read_mbr(const char* device, char* buf) 18 { 19 int fd; 20 int bytes; 21 int n; 22 23 fd = open(device, O_RDONLY); 24 if (fd == -1) { 25 fprintf(stderr, "Can't open %s: %s\n", device, strerror(errno)); 26 return 1; 27 } 28 29 if (lseek(fd, MBR_PART_OFFSET, SEEK_SET) != MBR_PART_OFFSET) { 30 fprintf(stderr, "Can't seek in %s to %d: %s\n", 31 device, MBR_PART_OFFSET, strerror(errno)); 32 close(fd); 33 return 1; 34 } 35 36 bytes = DFL_SECSIZE - MBR_PART_OFFSET; 37 38 if ((n = read(fd, buf, bytes)) != bytes) { 39 fprintf(stderr, "Can't read %d bytes from %s, %d read instead" 40 ": %s\n", 41 bytes, device, n, strerror(errno)); 42 close(fd); 43 return 1; 44 } 45 46 if ((uint8_t)buf[bytes-2] != 0x55 || (uint8_t)buf[bytes-1] != 0xAA) { 47 fprintf(stderr, "No MBR on %s, signature is %x\n", 48 device, *(uint16_t*)(&buf[bytes-2])); 49 close(fd); 50 return 1; 51 } 52 53 close(fd); 54 return 0; 55 } 56 57 58 int minixfs3_is_minix_partition(const char* partition) 59 { 60 char buf[DFL_SECSIZE]; /* part table + signature */ 61 int name_length = strlen(partition); 62 63 /* partition must be 0-3 */ 64 if (atol(&partition[name_length-1]) >= 4) { 65 fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", 66 partition); 67 return 0; 68 } 69 70 /* it should be partition device, not disk */ 71 if (partition[name_length-2] != 'p') { 72 fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", 73 partition); 74 return 0; 75 } 76 77 /* MINIX 3 partition with current scheme *must* have subpartitions, 78 * thus MBR has signature. minixfs3_read_mbr checks the signature. 79 */ 80 if (minixfs3_read_mbr(partition, buf)) 81 return 0; 82 return 1; 83 } 84 85 /* bootxx from NetBSD is ~8Kb, and old MINIX installations have just 86 * 1Kb of space for their bootblock. Check if there is enough space 87 * to install bootxx_minixfs3. New installation should have 16Kb before 88 * the first subpartition. 89 */ 90 int minixfs3_has_bootblock_space(const char* partition) 91 { 92 char buf[DFL_SECSIZE]; /* part table + signature */ 93 char disk[NAME_MAX]; 94 struct mbr_partition *part; 95 uint32_t first_subpartition = (uint32_t) ~0; 96 uint32_t parent_partition = 0; 97 int i; 98 int name_length = strlen(partition); 99 100 /* partition must be 0-3 */ 101 if (atol(&partition[name_length-1]) >= 4) { 102 fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", 103 partition); 104 exit(1); 105 } 106 /* it should be partition device, not disk */ 107 if (partition[name_length-2] != 'p') { 108 fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n", 109 partition); 110 exit(1); 111 } 112 113 if (minixfs3_read_mbr(partition, buf)) 114 exit(1); 115 116 part = (struct mbr_partition *) buf; 117 118 for (i = 0; i < 4; i++) { 119 if (part[i].mbrp_size && part[i].mbrp_start < first_subpartition) 120 first_subpartition = part[i].mbrp_start; 121 } 122 123 strncpy(disk, partition, name_length - 2); 124 disk[name_length - 2] = '\0'; 125 126 if (minixfs3_read_mbr(disk, buf)) 127 exit(1); 128 129 for (i = 0; i < 4; i++) { 130 struct mbr_partition *p = &part[i]; 131 if (p->mbrp_size && p->mbrp_start <= first_subpartition 132 && (p->mbrp_start + p->mbrp_size) > first_subpartition) { 133 parent_partition = p->mbrp_start; 134 break; 135 } 136 } 137 138 if ((first_subpartition - parent_partition) < MFS_FIRST_SUBP_OFFSET) 139 return 0; 140 else 141 return 1; 142 } 143