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