]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libfdisk/src/context.c
10 * Returns: newly allocated libfdisk handler
12 struct fdisk_context
*fdisk_new_context(void)
14 struct fdisk_context
*cxt
;
16 cxt
= calloc(1, sizeof(*cxt
));
20 DBG(CXT
, ul_debugobj(cxt
, "alloc"));
24 * Allocate label specific structs.
26 * This is necessary (for example) to store label specific
29 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_gpt_label(cxt
);
30 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_dos_label(cxt
);
31 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_bsd_label(cxt
);
32 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_sgi_label(cxt
);
33 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_sun_label(cxt
);
39 * fdisk_new_nested_context:
40 * @parent: parental context
41 * @name: optional label name (e.g. "bsd")
43 * This is supported for MBR+BSD and GPT+pMBR only.
45 * Returns: new context for nested partiton table.
47 struct fdisk_context
*fdisk_new_nested_context(struct fdisk_context
*parent
,
50 struct fdisk_context
*cxt
;
51 struct fdisk_label
*lb
= NULL
;
55 cxt
= calloc(1, sizeof(*cxt
));
59 DBG(CXT
, ul_debugobj(parent
, "alloc nested [%p]", cxt
));
60 cxt
->dev_fd
= parent
->dev_fd
;
63 cxt
->io_size
= parent
->io_size
;
64 cxt
->optimal_io_size
= parent
->optimal_io_size
;
65 cxt
->min_io_size
= parent
->min_io_size
;
66 cxt
->phy_sector_size
= parent
->phy_sector_size
;
67 cxt
->sector_size
= parent
->sector_size
;
68 cxt
->alignment_offset
= parent
->alignment_offset
;
69 cxt
->grain
= parent
->grain
;
70 cxt
->first_lba
= parent
->first_lba
;
71 cxt
->total_sectors
= parent
->total_sectors
;
72 cxt
->firstsector
= parent
->firstsector
;
74 cxt
->ask_cb
= parent
->ask_cb
;
75 cxt
->ask_data
= parent
->ask_data
;
77 cxt
->geom
= parent
->geom
;
80 if (strcmp(name
, "bsd") == 0)
81 lb
= cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_bsd_label(cxt
);
82 else if (strcmp(name
, "dos") == 0)
83 lb
= cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_dos_label(cxt
);
87 DBG(CXT
, ul_debugobj(cxt
, "probing for nested %s", lb
->name
));
91 if (lb
->op
->probe(cxt
) == 1)
92 __fdisk_switch_label(cxt
, lb
);
94 DBG(CXT
, ul_debugobj(cxt
, "not found %s label", lb
->name
));
107 * @cxt: context instance
108 * @name: label name (e.g. "gpt")
110 * If no @name specified then returns the current context label.
112 * Returns: label struct or NULL in case of error.
114 struct fdisk_label
*fdisk_get_label(struct fdisk_context
*cxt
, const char *name
)
123 for (i
= 0; i
< cxt
->nlabels
; i
++)
125 && strcmp(cxt
->labels
[i
]->name
, name
) == 0)
126 return cxt
->labels
[i
];
128 DBG(CXT
, ul_debugobj(cxt
, "failed to found %s label driver", name
));
134 * @cxt: context instance
135 * @lb: returns pointer to the next label
139 * // print all supported labels
140 * struct fdisk_context *cxt = fdisk_new_context();
141 * struct fdisk_label *lb = NULL;
143 * while (fdisk_next_label(cxt, &lb) == 0)
144 * print("label name: %s\n", fdisk_label_get_name(lb));
145 * fdisk_free_context(cxt);
149 * Returns: <0 in case of error, 0 on success, 1 at the end.
151 int fdisk_next_label(struct fdisk_context
*cxt
, struct fdisk_label
**lb
)
154 struct fdisk_label
*res
= NULL
;
160 res
= cxt
->labels
[0];
162 for (i
= 1; i
< cxt
->nlabels
; i
++) {
163 if (*lb
== cxt
->labels
[i
- 1]) {
164 res
= cxt
->labels
[i
];
178 * Returns: number of supported label types
180 size_t fdisk_get_nlabels(struct fdisk_context
*cxt
)
182 return cxt
? cxt
->nlabels
: 0;
185 int __fdisk_switch_label(struct fdisk_context
*cxt
, struct fdisk_label
*lb
)
190 DBG(CXT
, ul_debugobj(cxt
, "*** attempt to switch to disabled label %s -- ignore!", lb
->name
));
194 DBG(CXT
, ul_debugobj(cxt
, "--> switching context to %s!", lb
->name
));
199 * fdisk_switch_label:
201 * @name: label name (e.g. "gpt")
203 * Forces libfdisk to use the label driver.
205 * Returns: 0 on succes, <0 in case of error.
207 int fdisk_switch_label(struct fdisk_context
*cxt
, const char *name
)
209 return __fdisk_switch_label(cxt
, fdisk_get_label(cxt
, name
));
213 static void reset_context(struct fdisk_context
*cxt
)
217 DBG(CXT
, ul_debugobj(cxt
, "*** resetting context"));
219 /* reset drives' private data */
220 for (i
= 0; i
< cxt
->nlabels
; i
++)
221 fdisk_deinit_label(cxt
->labels
[i
]);
223 /* free device specific stuff */
224 if (!cxt
->parent
&& cxt
->dev_fd
> -1)
228 if (cxt
->parent
== NULL
|| cxt
->parent
->firstsector
!= cxt
->firstsector
)
229 free(cxt
->firstsector
);
233 cxt
->dev_path
= NULL
;
234 cxt
->firstsector
= NULL
;
235 cxt
->firstsector_bufsz
= 0;
237 fdisk_zeroize_device_properties(cxt
);
243 * This function prints a warning if the device is not wiped (e.g. wipefs(8).
244 * Please don't call this function if there is already a PT.
246 * Returns: 0 if nothing found, < 0 on error, 1 if found a signature
248 static int warn_wipe(struct fdisk_context
*cxt
)
257 if (fdisk_dev_has_disklabel(cxt
) || cxt
->dev_fd
< 0)
260 DBG(CXT
, ul_debugobj(cxt
, "wipe check: initialize libblkid prober"));
262 pr
= blkid_new_probe();
265 rc
= blkid_probe_set_device(pr
, cxt
->dev_fd
, 0, 0);
269 blkid_probe_enable_superblocks(pr
, 1);
270 blkid_probe_set_superblocks_flags(pr
, BLKID_SUBLKS_TYPE
);
271 blkid_probe_enable_partitions(pr
, 1);
273 /* we care about the first found FS/raid, so don't call blkid_do_probe()
274 * in loop or don't use blkid_do_fullprobe() ... */
275 rc
= blkid_do_probe(pr
);
277 const char *name
= NULL
;
279 if (blkid_probe_lookup_value(pr
, "TYPE", &name
, 0) == 0 ||
280 blkid_probe_lookup_value(pr
, "PTTYPE", &name
, 0) == 0) {
282 "%s: device contains a valid '%s' signature, it's "
283 "strongly recommended to wipe the device by command wipefs(8) "
284 "if this setup is unexpected to avoid "
285 "possible collisions."), cxt
->dev_path
, name
);
290 blkid_free_probe(pr
);
296 * fdisk_assign_device:
297 * @fname: path to the device to be handled
298 * @readonly: how to open the device
300 * Open the device, discovery topology, geometry, and detect disklabel.
302 * Returns: 0 on success, < 0 on error.
304 int fdisk_assign_device(struct fdisk_context
*cxt
,
305 const char *fname
, int readonly
)
309 DBG(CXT
, ul_debugobj(cxt
, "assigning device %s", fname
));
314 fd
= open(fname
, (readonly
? O_RDONLY
: O_RDWR
) | O_CLOEXEC
);
318 cxt
->readonly
= readonly
;
320 cxt
->dev_path
= strdup(fname
);
324 fdisk_discover_topology(cxt
);
325 fdisk_discover_geometry(cxt
);
327 if (fdisk_read_firstsector(cxt
) < 0)
330 /* detect labels and apply labes specific stuff (e.g geomery)
332 fdisk_probe_labels(cxt
);
334 /* let's apply user geometry *after* label prober
335 * to make it possible to override in-label setting */
336 fdisk_apply_user_device_properties(cxt
);
338 /* warn about obsolete stuff on the device if we aren't in
339 * list-only mode and there is not PT yet */
340 if (!fdisk_is_listonly(cxt
) && !fdisk_dev_has_disklabel(cxt
))
343 DBG(CXT
, ul_debugobj(cxt
, "initialized for %s [%s]",
344 fname
, readonly
? "READ-ONLY" : "READ-WRITE"));
347 DBG(CXT
, ul_debugobj(cxt
, "failed to assign device"));
351 int fdisk_deassign_device(struct fdisk_context
*cxt
, int nosync
)
354 assert(cxt
->dev_fd
>= 0);
356 if (cxt
->readonly
|| nosync
)
360 if (fsync(cxt
->dev_fd
) || close(cxt
->dev_fd
)) {
361 fdisk_warn(cxt
, _("%s: close device failed"),
366 fdisk_info(cxt
, _("Syncing disks."));
373 int fdisk_is_readonly(struct fdisk_context
*cxt
)
376 return cxt
->readonly
;
380 * fdisk_free_context:
381 * @cxt: fdisk context
383 * Deallocates context struct.
385 void fdisk_free_context(struct fdisk_context
*cxt
)
392 DBG(CXT
, ul_debugobj(cxt
, "freeing context %p for %s", cxt
, cxt
->dev_path
));
395 /* deallocate label's private stuff */
396 for (i
= 0; i
< cxt
->nlabels
; i
++) {
399 if (cxt
->labels
[i
]->op
->free
)
400 cxt
->labels
[i
]->op
->free(cxt
->labels
[i
]);
402 free(cxt
->labels
[i
]);
412 * @data: callback data
414 * Set callbacks for dialog driven partitioning and library warnings/errors.
416 * Returns: 0 on success, < 0 on error.
418 int fdisk_set_ask(struct fdisk_context
*cxt
,
419 int (*ask_cb
)(struct fdisk_context
*, struct fdisk_ask
*, void *),
424 cxt
->ask_cb
= ask_cb
;
425 cxt
->ask_data
= data
;
430 * fdisk_enable_details:
432 * @enable: true/flase
434 * Enables or disables "details" display mode. This function has effect to
435 * fdisk_partition_to_string() function.
437 * Returns: 0 on success, < 0 on error.
439 int fdisk_enable_details(struct fdisk_context
*cxt
, int enable
)
442 cxt
->display_details
= enable
? 1 : 0;
450 * Returns: 1 if details are enabled
452 int fdisk_is_details(struct fdisk_context
*cxt
)
455 return cxt
->display_details
== 1;
459 * fdisk_enable_listonly:
461 * @enable: true/flase
463 * Just list partition only, don't care about another details, mistakes, ...
465 * Returns: 0 on success, < 0 on error.
467 int fdisk_enable_listonly(struct fdisk_context
*cxt
, int enable
)
470 cxt
->listonly
= enable
? 1 : 0;
478 * Returns: 1 if list-only mode enabled
480 int fdisk_is_listonly(struct fdisk_context
*cxt
)
483 return cxt
->listonly
== 1;
490 * @str: "cylinder" or "sector".
492 * This is pure shit, unfortunately for example Sun addresses begin of the
493 * partition by cylinders...
495 * Returns: 0 on succes, <0 on error.
497 int fdisk_set_unit(struct fdisk_context
*cxt
, const char *str
)
501 cxt
->display_in_cyl_units
= 0;
506 if (strcmp(str
, "cylinder") == 0 || strcmp(str
, "cylinders") == 0)
507 cxt
->display_in_cyl_units
= 1;
509 else if (strcmp(str
, "sector") == 0 || strcmp(str
, "sectors") == 0)
510 cxt
->display_in_cyl_units
= 0;
512 DBG(CXT
, ul_debugobj(cxt
, "display unit: %s", fdisk_get_unit(cxt
, 0)));
520 * Returns: unit name.
522 const char *fdisk_get_unit(struct fdisk_context
*cxt
, int n
)
526 if (fdisk_use_cylinders(cxt
))
527 return P_("cylinder", "cylinders", n
);
528 return P_("sector", "sectors", n
);
532 * fdisk_use_cylinders:
535 * Returns 1 if user wants to display in cylinders.
537 int fdisk_use_cylinders(struct fdisk_context
*cxt
)
540 return cxt
->display_in_cyl_units
== 1;
544 * fdisk_get_units_per_sector:
547 * This is neccessary only for brain dead situations when we use "cylinders";
549 * Returns: number of "units" per sector, default is 1 if display unit is sector.
551 unsigned int fdisk_get_units_per_sector(struct fdisk_context
*cxt
)
555 if (fdisk_use_cylinders(cxt
)) {
556 assert(cxt
->geom
.heads
);
557 return cxt
->geom
.heads
* cxt
->geom
.sectors
;
563 * fdisk_get_optimal_iosize:
566 * Returns: optimal I/O size
568 unsigned long fdisk_get_optimal_iosize(struct fdisk_context
*cxt
)
571 return cxt
->optimal_io_size
;
575 * fdisk_get_minimal_iosize:
578 * Returns: minimal I/O size
580 unsigned long fdisk_get_minimal_size(struct fdisk_context
*cxt
)
583 return cxt
->min_io_size
;
587 * fdisk_get_physector_size:
590 * Returns: physical sector size
592 unsigned long fdisk_get_physector_size(struct fdisk_context
*cxt
)
595 return cxt
->phy_sector_size
;
599 * fdisk_get_sector_size:
602 * Returns: sector size
604 unsigned long fdisk_get_sector_size(struct fdisk_context
*cxt
)
607 return cxt
->sector_size
;
611 * fdisk_get_alignment_offset
614 * Returns: alignment offset (used by 4K disks for backward compatibility with DOS tools).
616 unsigned long fdisk_get_alignment_offset(struct fdisk_context
*cxt
)
619 return cxt
->alignment_offset
;
623 * fdisk_get_grain_size:
626 * Returns: usual grain used to align partitions
628 unsigned long fdisk_get_grain_size(struct fdisk_context
*cxt
)
635 * fdisk_get_first_lba:
638 * Returns: first possible LBA on disk for data partitions.
640 unsigned long fdisk_get_first_lba(struct fdisk_context
*cxt
)
643 return cxt
->first_lba
;
647 * fdisk_get_nsectors:
650 * Returns: size of the device in (real) sectors.
652 unsigned long fdisk_get_nsectors(struct fdisk_context
*cxt
)
655 return cxt
->total_sectors
;
662 * Returns: device name.
664 const char *fdisk_get_devname(struct fdisk_context
*cxt
)
667 return cxt
->dev_path
;