tools/llvm: Do not build with symbols
[minix3.git] / usr.sbin / installboot / minixfs3.c
blobcf491b8b946015caf719655c94e926e608c28062
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 <sys/syslimits.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <string.h>
12 #include "installboot.h"
14 #ifndef DFL_SECSIZE
15 #define DFL_SECSIZE 512
16 #endif
18 #define MFS_FIRST_SUBP_OFFSET 32
20 enum {
21 TYPE_BAD,
22 TYPE_PART,
23 TYPE_DISK
26 static int
27 minixfs3_read_mbr(const char* device, char* buf)
29 int fd;
30 int bytes;
31 int n;
33 fd = open(device, O_RDONLY);
34 if (fd == -1) {
35 fprintf(stderr, "Can't open %s: %s\n", device, strerror(errno));
36 return 1;
39 if (lseek(fd, MBR_PART_OFFSET, SEEK_SET) != MBR_PART_OFFSET) {
40 fprintf(stderr, "Can't seek in %s to %d: %s\n",
41 device, MBR_PART_OFFSET, strerror(errno));
42 close(fd);
43 return 1;
46 bytes = DFL_SECSIZE - MBR_PART_OFFSET;
48 if ((n = read(fd, buf, bytes)) != bytes) {
49 fprintf(stderr, "Can't read %d bytes from %s, %d read instead"
50 ": %s\n",
51 bytes, device, n, strerror(errno));
52 close(fd);
53 return 1;
56 if ((uint8_t)buf[bytes-2] != 0x55 || (uint8_t)buf[bytes-1] != 0xAA) {
57 fprintf(stderr, "No MBR on %s, signature is %x\n",
58 device, *(uint16_t*)(&buf[bytes-2]));
59 close(fd);
60 return 1;
63 close(fd);
64 return 0;
67 static int
68 minixfs3_get_dev_type(const char *device, ib_params *params)
70 int len, type;
73 * Unless the -f flag is given, we expect to be provided with a primary
74 * partition. That is, a device name that ends with "pN", N being 0-3.
75 * If the -f flag is given, we assume that anything else is a whole
76 * disk. If we were given a subpartition, it will fail the subsequent
77 * MBR signature test, so we need not check this explicitly.
79 len = strlen(device);
81 if (len > 2 && device[len-2] == 'p' &&
82 (unsigned) (device[len-1] - '0') <= 3) {
83 type = TYPE_PART;
84 } else {
85 type = TYPE_DISK;
88 if (type != TYPE_PART && !(params->flags & IB_FORCE)) {
89 fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n",
90 device);
91 return TYPE_BAD;
94 return type;
97 int
98 minixfs3_is_minix_partition(ib_params *params)
100 char buf[DFL_SECSIZE]; /* part table + signature */
102 if (minixfs3_get_dev_type(params->filesystem, params) == TYPE_BAD)
103 return 0;
105 /* MINIX 3 partition with current scheme *must* have subpartitions,
106 * thus MBR has signature. minixfs3_read_mbr checks the signature.
108 if (minixfs3_read_mbr(params->filesystem, buf))
109 return 0;
110 return 1;
113 /* bootxx from NetBSD is ~8Kb, and old MINIX installations have just
114 * 1Kb of space for their bootblock. Check if there is enough space
115 * to install bootxx_minixfs3. New installation should have 16Kb before
116 * the first subpartition.
119 minixfs3_has_bootblock_space(ib_params *params)
121 const char *device;
122 char buf[DFL_SECSIZE]; /* part table + signature */
123 char parent_name[NAME_MAX];
124 struct mbr_partition *part;
125 uint32_t first_subpartition = (uint32_t) ~0;
126 uint32_t parent_partition;
127 int i, len, type = 0;
129 device = params->filesystem;
131 if ((type = minixfs3_get_dev_type(device, params)) == TYPE_BAD)
132 exit(1);
134 if (minixfs3_read_mbr(device, buf))
135 exit(1);
137 part = (struct mbr_partition *) buf;
139 for (i = 0; i < 4; i++) {
140 if (part[i].mbrp_size &&
141 part[i].mbrp_start < first_subpartition)
142 first_subpartition = part[i].mbrp_start;
145 if (type == TYPE_PART) {
146 /* The target is a partition. Look up its starting offset. */
147 len = strlen(device);
148 strncpy(parent_name, device, len - 2);
149 parent_name[len - 2] = '\0';
151 if (minixfs3_read_mbr(parent_name, buf))
152 exit(1);
154 parent_partition = 0;
155 for (i = 0; i < 4; i++) {
156 struct mbr_partition *p = &part[i];
157 if (p->mbrp_size && p->mbrp_start <= first_subpartition
158 && (p->mbrp_start + p->mbrp_size) >
159 first_subpartition) {
160 parent_partition = p->mbrp_start;
161 break;
164 } else {
165 /* The target is a whole disk. The starting offset is 0. */
166 parent_partition = 0;
169 if ((first_subpartition - parent_partition) < MFS_FIRST_SUBP_OFFSET)
170 return 0;
171 else
172 return 1;