]>
Commit | Line | Data |
---|---|---|
152788aa KZ |
1 | #include <libfdisk.h> |
2 | #include <libsmartcols.h> | |
3 | #include <assert.h> | |
4 | ||
5 | #include "c.h" | |
6 | #include "xalloc.h" | |
7 | #include "nls.h" | |
8 | #include "blkdev.h" | |
9 | #include "mbsalign.h" | |
10 | #include "pathnames.h" | |
11 | #include "canonicalize.h" | |
12 | #include "strutils.h" | |
13 | #include "sysfs.h" | |
14 | #include "colors.h" | |
fff8ad58 | 15 | #include "ttyutils.h" |
152788aa KZ |
16 | |
17 | #include "fdisk-list.h" | |
18 | ||
fff8ad58 KZ |
19 | /* see init_fields() */ |
20 | static const char *fields_string; | |
21 | static int *fields_ids; | |
22 | static size_t fields_nids; | |
23 | static const struct fdisk_label *fields_label; | |
24 | ||
152788aa KZ |
25 | static int is_ide_cdrom_or_tape(char *device) |
26 | { | |
27 | int fd, ret; | |
28 | ||
38401453 | 29 | if ((fd = open(device, O_RDONLY|O_NONBLOCK)) < 0) |
152788aa KZ |
30 | return 0; |
31 | ret = blkdev_is_cdrom(fd); | |
32 | ||
33 | close(fd); | |
34 | return ret; | |
35 | } | |
36 | ||
35ca5118 KZ |
37 | void list_disk_identifier(struct fdisk_context *cxt) |
38 | { | |
39 | struct fdisk_label *lb = fdisk_get_label(cxt, NULL); | |
40 | char *id = NULL; | |
41 | ||
42 | if (fdisk_has_label(cxt)) | |
43 | fdisk_info(cxt, _("Disklabel type: %s"), | |
44 | fdisk_label_get_name(lb)); | |
45 | ||
46 | if (!fdisk_is_details(cxt) && fdisk_get_disklabel_id(cxt, &id) == 0 && id) { | |
47 | fdisk_info(cxt, _("Disk identifier: %s"), id); | |
48 | free(id); | |
49 | } | |
50 | } | |
152788aa KZ |
51 | |
52 | void list_disk_geometry(struct fdisk_context *cxt) | |
53 | { | |
152788aa KZ |
54 | struct fdisk_label *lb = fdisk_get_label(cxt, NULL); |
55 | uint64_t bytes = fdisk_get_nsectors(cxt) * fdisk_get_sector_size(cxt); | |
39f37044 KZ |
56 | char *strsz = size_to_human_string(SIZE_DECIMAL_2DIGITS |
57 | | SIZE_SUFFIX_SPACE | |
152788aa KZ |
58 | | SIZE_SUFFIX_3LETTER, bytes); |
59 | ||
60 | color_scheme_enable("header", UL_COLOR_BOLD); | |
61 | fdisk_info(cxt, _("Disk %s: %s, %ju bytes, %ju sectors"), | |
62 | fdisk_get_devname(cxt), strsz, | |
63 | bytes, (uintmax_t) fdisk_get_nsectors(cxt)); | |
64 | color_disable(); | |
65 | free(strsz); | |
66 | ||
6ec47609 KZ |
67 | if (fdisk_get_devmodel(cxt)) |
68 | fdisk_info(cxt, _("Disk model: %s"), fdisk_get_devmodel(cxt)); | |
69 | ||
152788aa | 70 | if (lb && (fdisk_label_require_geometry(lb) || fdisk_use_cylinders(cxt))) |
fbae1442 | 71 | fdisk_info(cxt, _("Geometry: %d heads, %ju sectors/track, %ju cylinders"), |
152788aa | 72 | fdisk_get_geom_heads(cxt), |
fbae1442 KZ |
73 | (uintmax_t) fdisk_get_geom_sectors(cxt), |
74 | (uintmax_t) fdisk_get_geom_cylinders(cxt)); | |
152788aa KZ |
75 | |
76 | fdisk_info(cxt, _("Units: %s of %d * %ld = %ld bytes"), | |
77 | fdisk_get_unit(cxt, FDISK_PLURAL), | |
78 | fdisk_get_units_per_sector(cxt), | |
79 | fdisk_get_sector_size(cxt), | |
80 | fdisk_get_units_per_sector(cxt) * fdisk_get_sector_size(cxt)); | |
81 | ||
82 | fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"), | |
83 | fdisk_get_sector_size(cxt), | |
84 | fdisk_get_physector_size(cxt)); | |
85 | fdisk_info(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"), | |
86 | fdisk_get_minimal_iosize(cxt), | |
87 | fdisk_get_optimal_iosize(cxt)); | |
88 | if (fdisk_get_alignment_offset(cxt)) | |
89 | fdisk_info(cxt, _("Alignment offset: %lu bytes"), | |
90 | fdisk_get_alignment_offset(cxt)); | |
152788aa | 91 | |
35ca5118 | 92 | list_disk_identifier(cxt); |
152788aa KZ |
93 | } |
94 | ||
95 | void list_disklabel(struct fdisk_context *cxt) | |
96 | { | |
97 | struct fdisk_table *tb = NULL; | |
98 | struct fdisk_partition *pa = NULL; | |
99 | struct fdisk_iter *itr = NULL; | |
100 | struct fdisk_label *lb; | |
101 | struct libscols_table *out = NULL; | |
102 | const char *bold = NULL; | |
103 | int *ids = NULL; /* IDs of fdisk_fields */ | |
104 | size_t nids = 0, i; | |
c7475647 | 105 | int post = 0; |
152788aa KZ |
106 | |
107 | /* print label specific stuff by libfdisk FDISK_ASK_INFO API */ | |
108 | fdisk_list_disklabel(cxt); | |
109 | ||
110 | /* get partitions and generate output */ | |
111 | if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0) | |
112 | goto done; | |
113 | ||
fff8ad58 KZ |
114 | ids = init_fields(cxt, NULL, &nids); |
115 | if (!ids) | |
152788aa KZ |
116 | goto done; |
117 | ||
118 | itr = fdisk_new_iter(FDISK_ITER_FORWARD); | |
119 | if (!itr) { | |
54fefa07 | 120 | fdisk_warn(cxt, _("failed to allocate iterator")); |
152788aa KZ |
121 | goto done; |
122 | } | |
123 | ||
124 | out = scols_new_table(); | |
125 | if (!out) { | |
54fefa07 | 126 | fdisk_warn(cxt, _("failed to allocate output table")); |
152788aa KZ |
127 | goto done; |
128 | } | |
129 | ||
130 | if (colors_wanted()) { | |
131 | scols_table_enable_colors(out, 1); | |
132 | bold = color_scheme_get_sequence("header", UL_COLOR_BOLD); | |
133 | } | |
134 | ||
135 | lb = fdisk_get_label(cxt, NULL); | |
136 | assert(lb); | |
137 | ||
138 | /* define output table columns */ | |
139 | for (i = 0; i < nids; i++) { | |
140 | int fl = 0; | |
141 | struct libscols_column *co; | |
142 | const struct fdisk_field *field = | |
143 | fdisk_label_get_field(lb, ids[i]); | |
144 | if (!field) | |
6d812a48 | 145 | continue; |
152788aa KZ |
146 | if (fdisk_field_is_number(field)) |
147 | fl |= SCOLS_FL_RIGHT; | |
148 | if (fdisk_field_get_id(field) == FDISK_FIELD_TYPE) | |
149 | fl |= SCOLS_FL_TRUNC; | |
150 | ||
151 | co = scols_table_new_column(out, | |
9ac1fcf6 | 152 | _(fdisk_field_get_name(field)), |
152788aa KZ |
153 | fdisk_field_get_width(field), fl); |
154 | if (!co) | |
155 | goto done; | |
156 | ||
3fd1f771 | 157 | /* set column header color */ |
152788aa KZ |
158 | if (bold) |
159 | scols_cell_set_color(scols_column_get_header(co), bold); | |
160 | } | |
161 | ||
162 | /* fill-in output table */ | |
163 | while (fdisk_table_next_partition(tb, itr, &pa) == 0) { | |
164 | struct libscols_line *ln = scols_table_new_line(out, NULL); | |
165 | ||
166 | if (!ln) { | |
54fefa07 | 167 | fdisk_warn(cxt, _("failed to allocate output line")); |
152788aa KZ |
168 | goto done; |
169 | } | |
170 | ||
171 | for (i = 0; i < nids; i++) { | |
172 | char *data = NULL; | |
173 | ||
174 | if (fdisk_partition_to_string(pa, cxt, ids[i], &data)) | |
175 | continue; | |
780ce22c KZ |
176 | if (scols_line_refer_data(ln, i, data)) { |
177 | fdisk_warn(cxt, _("failed to add output data")); | |
178 | goto done; | |
179 | } | |
152788aa KZ |
180 | } |
181 | } | |
182 | ||
183 | /* print */ | |
184 | if (!scols_table_is_empty(out)) { | |
fbae1442 | 185 | fdisk_info(cxt, "%s", ""); /* just line break */ |
152788aa KZ |
186 | scols_print_table(out); |
187 | } | |
188 | ||
189 | /* print warnings */ | |
c7475647 | 190 | fdisk_reset_iter(itr, FDISK_ITER_FORWARD); |
152788aa | 191 | while (itr && fdisk_table_next_partition(tb, itr, &pa) == 0) { |
ecf40cda KZ |
192 | if (!fdisk_partition_has_start(pa)) |
193 | continue; | |
c7475647 KZ |
194 | if (!fdisk_lba_is_phy_aligned(cxt, fdisk_partition_get_start(pa))) { |
195 | if (!post) | |
fbae1442 | 196 | fdisk_info(cxt, "%s", ""); /* line break */ |
152788aa KZ |
197 | fdisk_warnx(cxt, _("Partition %zu does not start on physical sector boundary."), |
198 | fdisk_partition_get_partno(pa) + 1); | |
c7475647 KZ |
199 | post++; |
200 | } | |
ddead341 KZ |
201 | if (fdisk_partition_has_wipe(cxt, pa)) { |
202 | if (!post) | |
fbae1442 | 203 | fdisk_info(cxt, "%s", ""); /* line break */ |
ad524980 RP |
204 | |
205 | fdisk_info(cxt, _("Filesystem/RAID signature on partition %zu will be wiped."), | |
206 | fdisk_partition_get_partno(pa) + 1); | |
207 | post++; | |
ddead341 | 208 | } |
152788aa KZ |
209 | } |
210 | ||
c7475647 KZ |
211 | if (fdisk_table_wrong_order(tb)) { |
212 | if (!post) | |
fbae1442 | 213 | fdisk_info(cxt, "%s", ""); /* line break */ |
152788aa | 214 | fdisk_info(cxt, _("Partition table entries are not in disk order.")); |
c7475647 | 215 | } |
152788aa | 216 | done: |
152788aa KZ |
217 | scols_unref_table(out); |
218 | fdisk_unref_table(tb); | |
219 | fdisk_free_iter(itr); | |
220 | } | |
221 | ||
0efd951c KZ |
222 | void list_freespace(struct fdisk_context *cxt) |
223 | { | |
224 | struct fdisk_table *tb = NULL; | |
225 | struct fdisk_partition *pa = NULL; | |
226 | struct fdisk_iter *itr = NULL; | |
227 | struct libscols_table *out = NULL; | |
228 | const char *bold = NULL; | |
229 | size_t i; | |
230 | uintmax_t sumsize = 0, bytes = 0; | |
231 | char *strsz; | |
232 | ||
233 | static const char *colnames[] = { N_("Start"), N_("End"), N_("Sectors"), N_("Size") }; | |
234 | static const int colids[] = { FDISK_FIELD_START, FDISK_FIELD_END, FDISK_FIELD_SECTORS, FDISK_FIELD_SIZE }; | |
235 | ||
236 | if (fdisk_get_freespaces(cxt, &tb)) | |
237 | goto done; | |
238 | ||
239 | itr = fdisk_new_iter(FDISK_ITER_FORWARD); | |
240 | if (!itr) { | |
241 | fdisk_warn(cxt, _("failed to allocate iterator")); | |
242 | goto done; | |
243 | } | |
244 | ||
245 | out = scols_new_table(); | |
246 | if (!out) { | |
247 | fdisk_warn(cxt, _("failed to allocate output table")); | |
248 | goto done; | |
249 | } | |
250 | ||
251 | if (colors_wanted()) { | |
252 | scols_table_enable_colors(out, 1); | |
253 | bold = color_scheme_get_sequence("header", UL_COLOR_BOLD); | |
254 | } | |
255 | ||
256 | for (i = 0; i < ARRAY_SIZE(colnames); i++) { | |
257 | struct libscols_column *co = scols_table_new_column(out, _(colnames[i]), 5, SCOLS_FL_RIGHT); | |
258 | ||
259 | if (!co) | |
260 | goto done; | |
261 | if (bold) | |
262 | scols_cell_set_color(scols_column_get_header(co), bold); | |
263 | } | |
264 | ||
265 | /* fill-in output table */ | |
266 | while (fdisk_table_next_partition(tb, itr, &pa) == 0) { | |
267 | struct libscols_line *ln = scols_table_new_line(out, NULL); | |
268 | char *data; | |
269 | ||
270 | if (!ln) { | |
271 | fdisk_warn(cxt, _("failed to allocate output line")); | |
272 | goto done; | |
273 | } | |
274 | for (i = 0; i < ARRAY_SIZE(colids); i++) { | |
275 | if (fdisk_partition_to_string(pa, cxt, colids[i], &data)) | |
276 | continue; | |
780ce22c KZ |
277 | if (scols_line_refer_data(ln, i, data)) { |
278 | fdisk_warn(cxt, _("failed to add output data")); | |
279 | goto done; | |
280 | } | |
0efd951c KZ |
281 | } |
282 | ||
283 | if (fdisk_partition_has_size(pa)) | |
284 | sumsize += fdisk_partition_get_size(pa); | |
285 | } | |
286 | ||
287 | bytes = sumsize * fdisk_get_sector_size(cxt); | |
39f37044 KZ |
288 | strsz = size_to_human_string(SIZE_DECIMAL_2DIGITS |
289 | | SIZE_SUFFIX_SPACE | |
290 | | SIZE_SUFFIX_3LETTER, bytes); | |
0efd951c KZ |
291 | |
292 | color_scheme_enable("header", UL_COLOR_BOLD); | |
293 | fdisk_info(cxt, _("Unpartitioned space %s: %s, %ju bytes, %ju sectors"), | |
294 | fdisk_get_devname(cxt), strsz, | |
295 | bytes, sumsize); | |
296 | color_disable(); | |
297 | free(strsz); | |
298 | ||
299 | fdisk_info(cxt, _("Units: %s of %d * %ld = %ld bytes"), | |
300 | fdisk_get_unit(cxt, FDISK_PLURAL), | |
301 | fdisk_get_units_per_sector(cxt), | |
302 | fdisk_get_sector_size(cxt), | |
303 | fdisk_get_units_per_sector(cxt) * fdisk_get_sector_size(cxt)); | |
304 | ||
305 | fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"), | |
306 | fdisk_get_sector_size(cxt), | |
307 | fdisk_get_physector_size(cxt)); | |
308 | ||
309 | /* print */ | |
310 | if (!scols_table_is_empty(out)) { | |
fbae1442 | 311 | fdisk_info(cxt, "%s", ""); /* line break */ |
0efd951c KZ |
312 | scols_print_table(out); |
313 | } | |
314 | done: | |
315 | scols_unref_table(out); | |
316 | fdisk_unref_table(tb); | |
317 | fdisk_free_iter(itr); | |
318 | } | |
319 | ||
d464e2f0 | 320 | char *next_proc_partition(FILE **f) |
152788aa | 321 | { |
152788aa | 322 | char line[128 + 1]; |
152788aa | 323 | |
d464e2f0 KZ |
324 | if (!*f) { |
325 | *f = fopen(_PATH_PROC_PARTITIONS, "r"); | |
326 | if (!*f) { | |
327 | warn(_("cannot open %s"), _PATH_PROC_PARTITIONS); | |
328 | return NULL; | |
329 | } | |
152788aa KZ |
330 | } |
331 | ||
d464e2f0 | 332 | while (fgets(line, sizeof(line), *f)) { |
152788aa KZ |
333 | char buf[PATH_MAX], *cn; |
334 | dev_t devno; | |
335 | ||
336 | if (sscanf(line, " %*d %*d %*d %128[^\n ]", buf) != 1) | |
337 | continue; | |
338 | ||
efb17218 | 339 | devno = sysfs_devname_to_devno(buf); |
152788aa KZ |
340 | if (devno <= 0) |
341 | continue; | |
342 | ||
80ec018c | 343 | if (sysfs_devno_is_dm_private(devno, NULL) || |
152788aa KZ |
344 | sysfs_devno_is_wholedisk(devno) <= 0) |
345 | continue; | |
346 | ||
347 | if (!sysfs_devno_to_devpath(devno, buf, sizeof(buf))) | |
348 | continue; | |
349 | ||
350 | cn = canonicalize_path(buf); | |
351 | if (!cn) | |
352 | continue; | |
353 | ||
d464e2f0 KZ |
354 | if (!is_ide_cdrom_or_tape(cn)) |
355 | return cn; | |
356 | } | |
357 | fclose(*f); | |
358 | *f = NULL; | |
359 | ||
360 | return NULL; | |
361 | } | |
362 | ||
4a52959d | 363 | int print_device_pt(struct fdisk_context *cxt, char *device, int warnme, |
cb776288 | 364 | int verify, int separator) |
d464e2f0 KZ |
365 | { |
366 | if (fdisk_assign_device(cxt, device, 1) != 0) { /* read-only */ | |
367 | if (warnme || errno == EACCES) | |
368 | warn(_("cannot open %s"), device); | |
369 | return -1; | |
370 | } | |
371 | ||
cb776288 | 372 | if (separator) |
4a52959d WS |
373 | fputs("\n\n", stdout); |
374 | ||
d464e2f0 KZ |
375 | list_disk_geometry(cxt); |
376 | ||
d2c47697 | 377 | if (fdisk_has_label(cxt)) { |
d464e2f0 | 378 | list_disklabel(cxt); |
d2c47697 KZ |
379 | if (verify) |
380 | fdisk_verify_disklabel(cxt); | |
381 | } | |
d464e2f0 KZ |
382 | fdisk_deassign_device(cxt, 1); |
383 | return 0; | |
384 | } | |
385 | ||
9bf75171 | 386 | int print_device_freespace(struct fdisk_context *cxt, char *device, int warnme, |
cb776288 | 387 | int separator) |
0efd951c KZ |
388 | { |
389 | if (fdisk_assign_device(cxt, device, 1) != 0) { /* read-only */ | |
390 | if (warnme || errno == EACCES) | |
391 | warn(_("cannot open %s"), device); | |
392 | return -1; | |
393 | } | |
394 | ||
cb776288 | 395 | if (separator) |
9bf75171 WS |
396 | fputs("\n\n", stdout); |
397 | ||
0efd951c KZ |
398 | list_freespace(cxt); |
399 | fdisk_deassign_device(cxt, 1); | |
400 | return 0; | |
401 | } | |
402 | ||
d2c47697 | 403 | void print_all_devices_pt(struct fdisk_context *cxt, int verify) |
d464e2f0 KZ |
404 | { |
405 | FILE *f = NULL; | |
4a52959d | 406 | int sep = 0; |
d464e2f0 KZ |
407 | char *dev; |
408 | ||
409 | while ((dev = next_proc_partition(&f))) { | |
4a52959d | 410 | print_device_pt(cxt, dev, 0, verify, sep); |
d464e2f0 | 411 | free(dev); |
4a52959d | 412 | sep = 1; |
152788aa | 413 | } |
152788aa KZ |
414 | } |
415 | ||
0efd951c KZ |
416 | void print_all_devices_freespace(struct fdisk_context *cxt) |
417 | { | |
418 | FILE *f = NULL; | |
9bf75171 | 419 | int sep = 0; |
0efd951c KZ |
420 | char *dev; |
421 | ||
422 | while ((dev = next_proc_partition(&f))) { | |
9bf75171 | 423 | print_device_freespace(cxt, dev, 0, sep); |
0efd951c | 424 | free(dev); |
9bf75171 | 425 | sep = 1; |
0efd951c KZ |
426 | } |
427 | } | |
428 | ||
fff8ad58 KZ |
429 | /* usable for example in usage() */ |
430 | void list_available_columns(FILE *out) | |
431 | { | |
432 | size_t i; | |
433 | int termwidth; | |
434 | struct fdisk_label *lb = NULL; | |
435 | struct fdisk_context *cxt = fdisk_new_context(); | |
436 | ||
437 | if (!cxt) | |
438 | return; | |
439 | ||
43b4f7ea | 440 | termwidth = get_terminal_width(80); |
fff8ad58 | 441 | |
c3a4cfc5 | 442 | fprintf(out, USAGE_COLUMNS); |
fff8ad58 KZ |
443 | |
444 | while (fdisk_next_label(cxt, &lb) == 0) { | |
445 | size_t width = 6; /* label name and separators */ | |
446 | ||
447 | fprintf(out, " %s:", fdisk_label_get_name(lb)); | |
448 | for (i = 1; i < FDISK_NFIELDS; i++) { | |
449 | const struct fdisk_field *fl = fdisk_label_get_field(lb, i); | |
450 | const char *name = fl ? fdisk_field_get_name(fl) : NULL; | |
451 | size_t len; | |
452 | ||
453 | if (!name) | |
454 | continue; | |
455 | len = strlen(name) + 1; | |
456 | if (width + len > (size_t) termwidth) { | |
457 | fputs("\n ", out); | |
458 | width = 6; | |
459 | } | |
460 | fprintf(out, " %s", name); | |
461 | width += len; | |
462 | } | |
463 | fputc('\n', out); | |
464 | } | |
465 | ||
466 | fdisk_unref_context(cxt); | |
467 | } | |
468 | ||
469 | static int fieldname_to_id(const char *name, size_t namesz) | |
470 | { | |
471 | const struct fdisk_field *fl; | |
472 | char buf[namesz + 1]; | |
473 | ||
474 | assert(name); | |
475 | assert(namesz); | |
476 | assert(fields_label); | |
477 | ||
478 | memcpy(buf, name, namesz); | |
479 | buf[namesz] = '\0'; | |
480 | ||
481 | fl = fdisk_label_get_field_by_name(fields_label, buf); | |
482 | if (!fl) { | |
483 | warnx(_("%s unknown column: %s"), | |
484 | fdisk_label_get_name(fields_label), buf); | |
485 | return -1; | |
486 | } | |
487 | return fdisk_field_get_id(fl); | |
488 | } | |
489 | ||
490 | /* | |
491 | * Initialize array with output columns (fields_ids[]) according to | |
492 | * comma delimited list of columns (@str). If the list string is not | |
493 | * defined then use library defaults. This function is "-o <list>" | |
494 | * backend. | |
495 | * | |
496 | * If the columns are already initialized then returns already existing columns. | |
497 | */ | |
498 | int *init_fields(struct fdisk_context *cxt, const char *str, size_t *n) | |
499 | { | |
500 | int *dflt_ids = NULL; | |
6d812a48 | 501 | struct fdisk_label *lb; |
fff8ad58 KZ |
502 | |
503 | if (!fields_string) | |
504 | fields_string = str; | |
6d812a48 KZ |
505 | if (!cxt) |
506 | goto done; | |
fff8ad58 | 507 | |
6d812a48 KZ |
508 | lb = fdisk_get_label(cxt, NULL); |
509 | ||
510 | if (!lb || fields_label != lb) { /* label changed: reset */ | |
511 | free(fields_ids); | |
512 | fields_ids = NULL; | |
513 | fields_label = lb; | |
514 | fields_nids = 0; | |
515 | } | |
fff8ad58 | 516 | |
6d812a48 | 517 | if (!fields_label) /* no label */ |
fff8ad58 | 518 | goto done; |
6d812a48 KZ |
519 | if (fields_nids) |
520 | goto done; /* already initialized */ | |
fff8ad58 KZ |
521 | |
522 | /* library default */ | |
523 | if (fdisk_label_get_fields_ids(NULL, cxt, &dflt_ids, &fields_nids)) | |
524 | goto done; | |
525 | ||
622be278 | 526 | fields_ids = xcalloc(FDISK_NFIELDS * 2, sizeof(int)); |
fff8ad58 KZ |
527 | |
528 | /* copy defaults to the list with wanted fields */ | |
529 | memcpy(fields_ids, dflt_ids, fields_nids * sizeof(int)); | |
530 | free(dflt_ids); | |
531 | ||
532 | /* extend or replace fields_nids[] according to fields_string */ | |
533 | if (fields_string && | |
534 | string_add_to_idarray(fields_string, fields_ids, FDISK_NFIELDS * 2, | |
40b17508 | 535 | &fields_nids, fieldname_to_id) < 0) |
fff8ad58 KZ |
536 | exit(EXIT_FAILURE); |
537 | done: | |
538 | fields_label = NULL; | |
539 | if (n) | |
540 | *n = fields_nids; | |
541 | return fields_ids; | |
542 | } | |
543 |