| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: gpt.c,v 1.10 2019/08/14 13:02:23 martin Exp $ */ | | 1 | /* $NetBSD: gpt.c,v 1.11 2019/08/26 12:14:06 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright 2018 The NetBSD Foundation, Inc. | | 4 | * Copyright 2018 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -1121,27 +1121,27 @@ gpt_modify_part(const char *disk, struct | | | @@ -1121,27 +1121,27 @@ gpt_modify_part(const char *disk, struct |
1121 | strcpy(p->gp_id, old.gp_id); | | 1121 | strcpy(p->gp_id, old.gp_id); |
1122 | | | 1122 | |
1123 | /* Check type */ | | 1123 | /* Check type */ |
1124 | if (p->gp_type != old.gp_type) { | | 1124 | if (p->gp_type != old.gp_type) { |
1125 | if (run_program(RUN_SILENT, | | 1125 | if (run_program(RUN_SILENT, |
1126 | "gpt label -b %" PRIu64 " -T %s %s", | | 1126 | "gpt label -b %" PRIu64 " -T %s %s", |
1127 | p->gp_start, p->gp_type->tid, disk) != 0) | | 1127 | p->gp_start, p->gp_type->tid, disk) != 0) |
1128 | return false; | | 1128 | return false; |
1129 | } | | 1129 | } |
1130 | | | 1130 | |
1131 | /* Check label */ | | 1131 | /* Check label */ |
1132 | if (strcmp(p->gp_label, old.gp_label) != 0) { | | 1132 | if (strcmp(p->gp_label, old.gp_label) != 0) { |
1133 | if (run_program(RUN_SILENT, | | 1133 | if (run_program(RUN_SILENT, |
1134 | "gpt label -b %" PRIu64 " -l %s %s", | | 1134 | "gpt label -b %" PRIu64 " -l \'%s\' %s", |
1135 | p->gp_start, p->gp_label, disk) != 0) | | 1135 | p->gp_start, p->gp_label, disk) != 0) |
1136 | return false; | | 1136 | return false; |
1137 | } | | 1137 | } |
1138 | | | 1138 | |
1139 | /* Check attributes */ | | 1139 | /* Check attributes */ |
1140 | if (p->gp_attr != old.gp_attr) { | | 1140 | if (p->gp_attr != old.gp_attr) { |
1141 | if (p->gp_attr == 0) { | | 1141 | if (p->gp_attr == 0) { |
1142 | if (run_program(RUN_SILENT, | | 1142 | if (run_program(RUN_SILENT, |
1143 | "gpt set -N -b %" PRIu64 " %s", | | 1143 | "gpt set -N -b %" PRIu64 " %s", |
1144 | p->gp_start, disk) != 0) | | 1144 | p->gp_start, disk) != 0) |
1145 | return false; | | 1145 | return false; |
1146 | } else { | | 1146 | } else { |
1147 | todo_set = (p->gp_attr ^ old.gp_attr) & p->gp_attr; | | 1147 | todo_set = (p->gp_attr ^ old.gp_attr) & p->gp_attr; |
| @@ -1203,58 +1203,75 @@ gpt_add_wedge(const char *disk, struct g | | | @@ -1203,58 +1203,75 @@ gpt_add_wedge(const char *disk, struct g |
1203 | if (fd < 0) | | 1203 | if (fd < 0) |
1204 | return false; | | 1204 | return false; |
1205 | if (ioctl(fd, DIOCAWEDGE, &dkw) == -1) { | | 1205 | if (ioctl(fd, DIOCAWEDGE, &dkw) == -1) { |
1206 | close(fd); | | 1206 | close(fd); |
1207 | return false; | | 1207 | return false; |
1208 | } | | 1208 | } |
1209 | close(fd); | | 1209 | close(fd); |
1210 | | | 1210 | |
1211 | strlcpy(p->gp_dev_name, dkw.dkw_devname, sizeof(p->gp_dev_name)); | | 1211 | strlcpy(p->gp_dev_name, dkw.dkw_devname, sizeof(p->gp_dev_name)); |
1212 | p->gp_flags |= GPEF_WEDGE; | | 1212 | p->gp_flags |= GPEF_WEDGE; |
1213 | return true; | | 1213 | return true; |
1214 | } | | 1214 | } |
1215 | | | 1215 | |
| | | 1216 | static void |
| | | 1217 | escape_spaces(char *dest, const char *src) |
| | | 1218 | { |
| | | 1219 | unsigned char c; |
| | | 1220 | |
| | | 1221 | while (*src) { |
| | | 1222 | c = *src++; |
| | | 1223 | if (isspace(c) || c == '\\') |
| | | 1224 | *dest++ = '\\'; |
| | | 1225 | *dest++ = c; |
| | | 1226 | } |
| | | 1227 | *dest = 0; |
| | | 1228 | } |
| | | 1229 | |
1216 | static bool | | 1230 | static bool |
1217 | gpt_get_part_device(const struct disk_partitions *arg, | | 1231 | gpt_get_part_device(const struct disk_partitions *arg, |
1218 | part_id id, char *devname, size_t max_devname_len, int *part, | | 1232 | part_id id, char *devname, size_t max_devname_len, int *part, |
1219 | enum dev_name_usage usage, bool with_path) | | 1233 | enum dev_name_usage usage, bool with_path) |
1220 | { | | 1234 | { |
1221 | const struct gpt_disk_partitions *parts = | | 1235 | const struct gpt_disk_partitions *parts = |
1222 | (const struct gpt_disk_partitions*)arg; | | 1236 | (const struct gpt_disk_partitions*)arg; |
1223 | struct gpt_part_entry *p = parts->partitions; | | 1237 | struct gpt_part_entry *p = parts->partitions; |
| | | 1238 | char tmpname[GPT_LABEL_LEN*2]; |
1224 | part_id no; | | 1239 | part_id no; |
1225 | | | 1240 | |
1226 | | | 1241 | |
1227 | for (no = 0; p != NULL && no < id; no++) | | 1242 | for (no = 0; p != NULL && no < id; no++) |
1228 | p = p->gp_next; | | 1243 | p = p->gp_next; |
1229 | | | 1244 | |
1230 | if (no != id || p == NULL) | | 1245 | if (no != id || p == NULL) |
1231 | return false; | | 1246 | return false; |
1232 | | | 1247 | |
1233 | if (part) | | 1248 | if (part) |
1234 | *part = -1; | | 1249 | *part = -1; |
1235 | | | 1250 | |
1236 | if (!(p->gp_flags & GPEF_WEDGE) && | | 1251 | if (!(p->gp_flags & GPEF_WEDGE) && |
1237 | (usage == plain_name || usage == raw_dev_name)) | | 1252 | (usage == plain_name || usage == raw_dev_name)) |
1238 | gpt_add_wedge(arg->disk, p); | | 1253 | gpt_add_wedge(arg->disk, p); |
1239 | | | 1254 | |
1240 | switch (usage) { | | 1255 | switch (usage) { |
1241 | case logical_name: | | 1256 | case logical_name: |
1242 | if (p->gp_label[0] != 0) | | 1257 | if (p->gp_label[0] != 0) { |
| | | 1258 | escape_spaces(tmpname, p->gp_label); |
1243 | snprintf(devname, max_devname_len, | | 1259 | snprintf(devname, max_devname_len, |
1244 | "NAME=%s", p->gp_label); | | 1260 | "NAME=%s", tmpname); |
1245 | else | | 1261 | } else { |
1246 | snprintf(devname, max_devname_len, | | 1262 | snprintf(devname, max_devname_len, |
1247 | "NAME=%s", p->gp_id); | | 1263 | "NAME=%s", p->gp_id); |
| | | 1264 | } |
1248 | break; | | 1265 | break; |
1249 | case plain_name: | | 1266 | case plain_name: |
1250 | assert(p->gp_flags & GPEF_WEDGE); | | 1267 | assert(p->gp_flags & GPEF_WEDGE); |
1251 | if (with_path) | | 1268 | if (with_path) |
1252 | snprintf(devname, max_devname_len, _PATH_DEV "%s", | | 1269 | snprintf(devname, max_devname_len, _PATH_DEV "%s", |
1253 | p->gp_dev_name); | | 1270 | p->gp_dev_name); |
1254 | else | | 1271 | else |
1255 | strlcpy(devname, p->gp_dev_name, max_devname_len); | | 1272 | strlcpy(devname, p->gp_dev_name, max_devname_len); |
1256 | break; | | 1273 | break; |
1257 | case raw_dev_name: | | 1274 | case raw_dev_name: |
1258 | assert(p->gp_flags & GPEF_WEDGE); | | 1275 | assert(p->gp_flags & GPEF_WEDGE); |
1259 | if (with_path) | | 1276 | if (with_path) |
1260 | snprintf(devname, max_devname_len, _PATH_DEV "r%s", | | 1277 | snprintf(devname, max_devname_len, _PATH_DEV "r%s", |
| @@ -1265,51 +1282,49 @@ gpt_get_part_device(const struct disk_pa | | | @@ -1265,51 +1282,49 @@ gpt_get_part_device(const struct disk_pa |
1265 | break; | | 1282 | break; |
1266 | default: | | 1283 | default: |
1267 | return false; | | 1284 | return false; |
1268 | } | | 1285 | } |
1269 | | | 1286 | |
1270 | return true; | | 1287 | return true; |
1271 | } | | 1288 | } |
1272 | | | 1289 | |
1273 | static bool | | 1290 | static bool |
1274 | gpt_write_to_disk(struct disk_partitions *arg) | | 1291 | gpt_write_to_disk(struct disk_partitions *arg) |
1275 | { | | 1292 | { |
1276 | struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; | | 1293 | struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; |
1277 | struct gpt_part_entry *p, *n; | | 1294 | struct gpt_part_entry *p, *n; |
1278 | char label_arg[sizeof(p->gp_label) + 4]; | | 1295 | char label_arg[sizeof(p->gp_label) + 10]; |
1279 | char diskpath[MAXPATHLEN]; | | 1296 | char diskpath[MAXPATHLEN]; |
1280 | int fd, bits = 0; | | 1297 | int fd, bits = 0; |
1281 | bool root_is_new = false, efi_is_new = false; | | 1298 | bool root_is_new = false, efi_is_new = false; |
1282 | part_id root_id = NO_PART, efi_id = NO_PART, pno; | | 1299 | part_id root_id = NO_PART, efi_id = NO_PART, pno; |
1283 | | | 1300 | |
1284 | /* | | 1301 | /* |
1285 | * Remove all wedges on this disk - they may become invalid and we | | 1302 | * Remove all wedges on this disk - they may become invalid and we |
1286 | * have no easy way to associate them with the partitioning data. | | 1303 | * have no easy way to associate them with the partitioning data. |
1287 | * Instead we will explicitly request creation of wedges on demand | | 1304 | * Instead we will explicitly request creation of wedges on demand |
1288 | * later. | | 1305 | * later. |
1289 | */ | | 1306 | */ |
1290 | fd = opendisk(arg->disk, O_RDWR, diskpath, sizeof(diskpath), 0); | | 1307 | fd = opendisk(arg->disk, O_RDWR, diskpath, sizeof(diskpath), 0); |
1291 | if (fd < 0) | | 1308 | if (fd < 0) |
1292 | return false; | | 1309 | return false; |
1293 | if (ioctl(fd, DIOCRMWEDGES, &bits) == -1) | | 1310 | if (ioctl(fd, DIOCRMWEDGES, &bits) == -1) |
1294 | return false; | | 1311 | return false; |
1295 | close(fd); | | 1312 | close(fd); |
1296 | | | 1313 | |
1297 | /* | | 1314 | /* |
1298 | * Mark all partitions as "have no wedge yet". While there, | | 1315 | * Collect first root and efi partition (if available) |
1299 | * collect first root and efi partition (if available) | | | |
1300 | */ | | 1316 | */ |
1301 | for (pno = 0, p = parts->partitions; p != NULL; p = p->gp_next, pno++) { | | 1317 | for (pno = 0, p = parts->partitions; p != NULL; p = p->gp_next, pno++) { |
1302 | p->gp_flags &= ~GPEF_WEDGE; | | | |
1303 | if (root_id == NO_PART && p->gp_type != NULL) { | | 1318 | if (root_id == NO_PART && p->gp_type != NULL) { |
1304 | if (p->gp_type->gent.generic_ptype == PT_root && | | 1319 | if (p->gp_type->gent.generic_ptype == PT_root && |
1305 | p->gp_start == pm->ptstart) { | | 1320 | p->gp_start == pm->ptstart) { |
1306 | root_id = pno; | | 1321 | root_id = pno; |
1307 | root_is_new = !(p->gp_flags & GPEF_ON_DISK); | | 1322 | root_is_new = !(p->gp_flags & GPEF_ON_DISK); |
1308 | } else if (efi_id == NO_PART && | | 1323 | } else if (efi_id == NO_PART && |
1309 | p->gp_type->gent.generic_ptype == PT_EFI_SYSTEM) { | | 1324 | p->gp_type->gent.generic_ptype == PT_EFI_SYSTEM) { |
1310 | efi_id = pno; | | 1325 | efi_id = pno; |
1311 | efi_is_new = !(p->gp_flags & GPEF_ON_DISK); | | 1326 | efi_is_new = !(p->gp_flags & GPEF_ON_DISK); |
1312 | } | | 1327 | } |
1313 | } | | 1328 | } |
1314 | } | | 1329 | } |
1315 | | | 1330 | |
| @@ -1363,27 +1378,27 @@ gpt_write_to_disk(struct disk_partitions | | | @@ -1363,27 +1378,27 @@ gpt_write_to_disk(struct disk_partitions |
1363 | | | 1378 | |
1364 | /* | | 1379 | /* |
1365 | * Add new partitions | | 1380 | * Add new partitions |
1366 | */ | | 1381 | */ |
1367 | for (p = parts->partitions; p != NULL; p = p->gp_next) { | | 1382 | for (p = parts->partitions; p != NULL; p = p->gp_next) { |
1368 | if (p->gp_flags & GPEF_ON_DISK) | | 1383 | if (p->gp_flags & GPEF_ON_DISK) |
1369 | continue; | | 1384 | continue; |
1370 | if (!(p->gp_flags & GPEF_MODIFIED)) | | 1385 | if (!(p->gp_flags & GPEF_MODIFIED)) |
1371 | continue; | | 1386 | continue; |
1372 | | | 1387 | |
1373 | if (p->gp_label[0] == 0) | | 1388 | if (p->gp_label[0] == 0) |
1374 | label_arg[0] = 0; | | 1389 | label_arg[0] = 0; |
1375 | else | | 1390 | else |
1376 | sprintf(label_arg, "-l %s", p->gp_label); | | 1391 | sprintf(label_arg, "-l \'%s\'", p->gp_label); |
1377 | | | 1392 | |
1378 | if (p->gp_type != NULL) | | 1393 | if (p->gp_type != NULL) |
1379 | run_program(RUN_SILENT, | | 1394 | run_program(RUN_SILENT, |
1380 | "gpt -n add -b %" PRIu64 " -s %" PRIu64 | | 1395 | "gpt -n add -b %" PRIu64 " -s %" PRIu64 |
1381 | "s -t %s %s %s", | | 1396 | "s -t %s %s %s", |
1382 | p->gp_start, p->gp_size, p->gp_type->tid, | | 1397 | p->gp_start, p->gp_size, p->gp_type->tid, |
1383 | label_arg, arg->disk); | | 1398 | label_arg, arg->disk); |
1384 | else | | 1399 | else |
1385 | run_program(RUN_SILENT, | | 1400 | run_program(RUN_SILENT, |
1386 | "gpt -n add -b %" PRIu64 " -s %" PRIu64 | | 1401 | "gpt -n add -b %" PRIu64 " -s %" PRIu64 |
1387 | "s %s %s", | | 1402 | "s %s %s", |
1388 | p->gp_start, p->gp_size, label_arg, arg->disk); | | 1403 | p->gp_start, p->gp_size, label_arg, arg->disk); |
1389 | gpt_apply_attr(arg->disk, "set", p->gp_start, p->gp_attr); | | 1404 | gpt_apply_attr(arg->disk, "set", p->gp_start, p->gp_attr); |