]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libfdisk/src/context.c
16 * @short_description: stores info about device, labels etc.
18 * The library distinguish between three types of partitioning objects.
21 * - disk label specific
22 * - probed and read by disklabel drivers when assign device to the context
23 * or when switch to another disk label type
24 * - only fdisk_write_disklabel() modify on-disk data
27 * - generic data and disklabel specific data stored in struct fdisk_label
28 * - all partitioning operations are based on in-memory data only
30 * struct fdisk_partition
31 * - provides abstraction to present partitions to users
32 * - fdisk_partition is possible to gather to fdisk_table container
33 * - used as unified template for new partitions
34 * - the struct fdisk_partition is always completely independent object and
35 * any change to the object has no effect to in-memory (or on-disk) label data
41 * Returns: newly allocated libfdisk handler
43 struct fdisk_context
*fdisk_new_context(void)
45 struct fdisk_context
*cxt
;
47 cxt
= calloc(1, sizeof(*cxt
));
51 DBG(CXT
, ul_debugobj(cxt
, "alloc"));
55 INIT_LIST_HEAD(&cxt
->wipes
);
58 * Allocate label specific structs.
60 * This is necessary (for example) to store label specific
63 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_gpt_label(cxt
);
64 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_dos_label(cxt
);
65 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_bsd_label(cxt
);
66 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_sgi_label(cxt
);
67 cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_sun_label(cxt
);
69 bindtextdomain(LIBFDISK_TEXTDOMAIN
, LOCALEDIR
);
74 static int init_nested_from_parent(struct fdisk_context
*cxt
, int isnew
)
76 struct fdisk_context
*parent
;
83 cxt
->alignment_offset
= parent
->alignment_offset
;
84 cxt
->ask_cb
= parent
->ask_cb
;
85 cxt
->ask_data
= parent
->ask_data
;
86 cxt
->dev_fd
= parent
->dev_fd
;
87 cxt
->first_lba
= parent
->first_lba
;
88 cxt
->firstsector_bufsz
= parent
->firstsector_bufsz
;
89 cxt
->firstsector
= parent
->firstsector
;
90 cxt
->geom
= parent
->geom
;
91 cxt
->grain
= parent
->grain
;
92 cxt
->io_size
= parent
->io_size
;
93 cxt
->last_lba
= parent
->last_lba
;
94 cxt
->min_io_size
= parent
->min_io_size
;
95 cxt
->optimal_io_size
= parent
->optimal_io_size
;
96 cxt
->phy_sector_size
= parent
->phy_sector_size
;
97 cxt
->readonly
= parent
->readonly
;
98 cxt
->script
= parent
->script
;
99 fdisk_ref_script(cxt
->script
);
100 cxt
->sector_size
= parent
->sector_size
;
101 cxt
->total_sectors
= parent
->total_sectors
;
102 cxt
->user_geom
= parent
->user_geom
;
103 cxt
->user_log_sector
= parent
->user_log_sector
;
104 cxt
->user_pyh_sector
= parent
->user_pyh_sector
;
106 /* parent <--> nested independent setting, initialize for new nested
109 cxt
->listonly
= parent
->listonly
;
110 cxt
->display_details
= parent
->display_details
;
111 cxt
->display_in_cyl_units
= parent
->display_in_cyl_units
;
112 cxt
->protect_bootbits
= parent
->protect_bootbits
;
116 cxt
->dev_path
= NULL
;
118 if (parent
->dev_path
) {
119 cxt
->dev_path
= strdup(parent
->dev_path
);
124 INIT_LIST_HEAD(&cxt
->wipes
);
130 * fdisk_new_nested_context:
131 * @parent: parental context
132 * @name: optional label name (e.g. "bsd")
134 * Create a new nested fdisk context for nested disk labels (e.g. BSD or PMBR).
135 * The function also probes for the nested label on the device if device is
136 * already assigned to parent.
138 * The new context is initialized according to @parent and both context shares
139 * some settings and file descriptor to the device. The child propagate some
140 * changes (like fdisk_assign_device()) to parent, but it does not work
141 * vice-versa. The behavior is undefined if you assign another device to
144 * Returns: new context for nested partition table.
146 struct fdisk_context
*fdisk_new_nested_context(struct fdisk_context
*parent
,
149 struct fdisk_context
*cxt
;
150 struct fdisk_label
*lb
= NULL
;
154 cxt
= calloc(1, sizeof(*cxt
));
158 DBG(CXT
, ul_debugobj(parent
, "alloc nested [%p] [name=%s]", cxt
, name
));
161 fdisk_ref_context(parent
);
162 cxt
->parent
= parent
;
164 if (init_nested_from_parent(cxt
, 1) != 0) {
166 fdisk_unref_context(cxt
);
171 if (strcasecmp(name
, "bsd") == 0)
172 lb
= cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_bsd_label(cxt
);
173 else if (strcasecmp(name
, "dos") == 0 || strcasecmp(name
, "mbr") == 0)
174 lb
= cxt
->labels
[ cxt
->nlabels
++ ] = fdisk_new_dos_label(cxt
);
177 if (lb
&& parent
->dev_fd
>= 0) {
178 DBG(CXT
, ul_debugobj(cxt
, "probing for nested %s", lb
->name
));
182 if (lb
->op
->probe(cxt
) == 1)
183 __fdisk_switch_label(cxt
, lb
);
185 DBG(CXT
, ul_debugobj(cxt
, "not found %s label", lb
->name
));
198 * @cxt: context pointer
200 * Increments reference counter.
202 void fdisk_ref_context(struct fdisk_context
*cxt
)
210 * @cxt: context instance
211 * @name: label name (e.g. "gpt")
213 * If no @name specified then returns the current context label.
215 * The label is allocated and maintained within the context #cxt. There is
216 * nothing like reference counting for labels, you cannot deallocate the
219 * Returns: label struct or NULL in case of error.
221 struct fdisk_label
*fdisk_get_label(struct fdisk_context
*cxt
, const char *name
)
229 else if (strcasecmp(name
, "mbr") == 0)
232 for (i
= 0; i
< cxt
->nlabels
; i
++)
234 && strcasecmp(cxt
->labels
[i
]->name
, name
) == 0)
235 return cxt
->labels
[i
];
237 DBG(CXT
, ul_debugobj(cxt
, "failed to found %s label driver", name
));
243 * @cxt: context instance
244 * @lb: returns pointer to the next label
248 * // print all supported labels
249 * struct fdisk_context *cxt = fdisk_new_context();
250 * struct fdisk_label *lb = NULL;
252 * while (fdisk_next_label(cxt, &lb) == 0)
253 * print("label name: %s\n", fdisk_label_get_name(lb));
254 * fdisk_unref_context(cxt);
258 * Returns: <0 in case of error, 0 on success, 1 at the end.
260 int fdisk_next_label(struct fdisk_context
*cxt
, struct fdisk_label
**lb
)
263 struct fdisk_label
*res
= NULL
;
269 res
= cxt
->labels
[0];
271 for (i
= 1; i
< cxt
->nlabels
; i
++) {
272 if (*lb
== cxt
->labels
[i
- 1]) {
273 res
= cxt
->labels
[i
];
287 * Returns: number of supported label types
289 size_t fdisk_get_nlabels(struct fdisk_context
*cxt
)
291 return cxt
? cxt
->nlabels
: 0;
294 int __fdisk_switch_label(struct fdisk_context
*cxt
, struct fdisk_label
*lb
)
299 DBG(CXT
, ul_debugobj(cxt
, "*** attempt to switch to disabled label %s -- ignore!", lb
->name
));
303 DBG(CXT
, ul_debugobj(cxt
, "--> switching context to %s!", lb
->name
));
305 fdisk_apply_label_device_properties(cxt
);
311 * @cxt: fdisk context
313 * Returns: return 1 if there is label on the device.
315 int fdisk_has_label(struct fdisk_context
*cxt
)
317 return cxt
&& cxt
->label
;
321 * fdisk_has_protected_bootbits:
322 * @cxt: fdisk context
324 * Returns: return 1 if boot bits protection enabled.
326 int fdisk_has_protected_bootbits(struct fdisk_context
*cxt
)
328 return cxt
&& cxt
->protect_bootbits
;
332 * fdisk_enable_bootbits_protection:
333 * @cxt: fdisk context
336 * The library zeroizes all the first sector when create a new disk label by
337 * default. This function allows to control this behavior. For now it's
338 * supported for MBR and GPT.
340 * Returns: 0 on success, < 0 on error.
342 int fdisk_enable_bootbits_protection(struct fdisk_context
*cxt
, int enable
)
346 cxt
->protect_bootbits
= enable
? 1 : 0;
350 * fdisk_disable_dialogs
351 * @cxt: fdisk context
354 * The library uses dialog driven partitioning by default.
356 * Returns: 0 on success, < 0 on error.
360 int fdisk_disable_dialogs(struct fdisk_context
*cxt
, int disable
)
365 cxt
->no_disalogs
= disable
;
371 * @cxt: fdisk context
373 * See fdisk_disable_dialogs()
375 * Returns: 1 if dialog driven partitioning enabled (default), or 0.
379 int fdisk_has_dialogs(struct fdisk_context
*cxt
)
381 return cxt
->no_disalogs
== 0;
386 * @cxt: fdisk context
389 * The library removes all PT/filesystem/RAID signatures before it writes
390 * partition table. The probing area where it looks for signatures is from
391 * the begin of the disk. The device is wiped by libblkid.
393 * See also fdisk_wipe_partition().
395 * Returns: 0 on success, < 0 on error.
397 int fdisk_enable_wipe(struct fdisk_context
*cxt
, int enable
)
402 fdisk_set_wipe_area(cxt
, 0, cxt
->total_sectors
, enable
);
408 * @cxt: fdisk context
410 * Returns the current wipe setting. See fdisk_enable_wipe().
412 * Returns: 0 on success, < 0 on error.
414 int fdisk_has_wipe(struct fdisk_context
*cxt
)
419 return fdisk_has_wipe_area(cxt
, 0, cxt
->total_sectors
);
424 * fdisk_get_collision
425 * @cxt: fdisk context
427 * Returns: name of the filesystem or RAID detected on the device or NULL.
429 const char *fdisk_get_collision(struct fdisk_context
*cxt
)
431 return cxt
->collision
;
435 * fdisk_is_ptcollision:
436 * @cxt: fdisk context
438 * The collision detected by libblkid (usually another partition table). Note
439 * that libfdisk does not support all partitions tables, so fdisk_has_label()
440 * may return false, but fdisk_is_ptcollision() may return true.
446 int fdisk_is_ptcollision(struct fdisk_context
*cxt
)
448 return cxt
->pt_collision
;
452 * fdisk_get_npartitions:
455 * The maximal number of the partitions depends on disklabel and does not
456 * have to describe the real limit of PT.
458 * For example the limit for MBR without extend partition is 4, with extended
459 * partition it's unlimited (so the function returns the current number of all
460 * partitions in this case).
462 * And for example for GPT it depends on space allocated on disk for array of
463 * entry records (usually 128).
465 * It's fine to use fdisk_get_npartitions() in loops, but don't forget that
466 * partition may be unused (see fdisk_is_partition_used()).
470 * struct fdisk_partition *pa = NULL;
471 * size_t i, nmax = fdisk_get_npartitions(cxt);
473 * for (i = 0; i < nmax; i++) {
474 * if (!fdisk_is_partition_used(cxt, i))
476 * ... do something ...
481 * Note that the recommended way to list partitions is to use
482 * fdisk_get_partitions() and struct fdisk_table than ask disk driver for each
483 * individual partitions.
485 * Returns: maximal number of partitions for the current label.
487 size_t fdisk_get_npartitions(struct fdisk_context
*cxt
)
489 return cxt
&& cxt
->label
? cxt
->label
->nparts_max
: 0;
493 * fdisk_is_labeltype:
494 * @cxt: fdisk context
495 * @id: FDISK_DISKLABEL_*
497 * See also fdisk_is_label() macro in libfdisk.h.
499 * Returns: return 1 if the current label is @id
501 int fdisk_is_labeltype(struct fdisk_context
*cxt
, enum fdisk_labeltype id
)
505 return cxt
->label
&& (unsigned)fdisk_label_get_type(cxt
->label
) == id
;
510 * @cxt: nested fdisk context
512 * Returns: pointer to parental context, or NULL
514 struct fdisk_context
*fdisk_get_parent(struct fdisk_context
*cxt
)
520 static void reset_context(struct fdisk_context
*cxt
)
524 DBG(CXT
, ul_debugobj(cxt
, "*** resetting context"));
526 /* reset drives' private data */
527 for (i
= 0; i
< cxt
->nlabels
; i
++)
528 fdisk_deinit_label(cxt
->labels
[i
]);
531 /* the first sector may be independent on parent */
532 if (cxt
->parent
->firstsector
!= cxt
->firstsector
)
533 free(cxt
->firstsector
);
535 /* we close device only in primary context */
536 if (cxt
->dev_fd
> -1)
538 free(cxt
->firstsector
);
542 cxt
->dev_path
= NULL
;
544 free(cxt
->collision
);
545 cxt
->collision
= NULL
;
547 memset(&cxt
->dev_st
, 0, sizeof(cxt
->dev_st
));
550 cxt
->firstsector
= NULL
;
551 cxt
->firstsector_bufsz
= 0;
553 fdisk_zeroize_device_properties(cxt
);
555 fdisk_unref_script(cxt
->script
);
560 fdisk_free_wipe_areas(cxt
);
564 * fdisk_assign_device:
566 * @fname: path to the device to be handled
567 * @readonly: how to open the device
569 * Open the device, discovery topology, geometry, detect disklabel and switch
570 * the current label driver to reflect the probing result.
572 * Note that this function resets all generic setting in context. If the @cxt
573 * is nested context then the device is assigned to the parental context and
574 * necessary properties are copied to the @cxt. The change is propagated in
575 * child->parent direction only. It's impossible to use a different device for
576 * primary and nested contexts.
578 * Returns: 0 on success, < 0 on error.
580 int fdisk_assign_device(struct fdisk_context
*cxt
,
581 const char *fname
, int readonly
)
585 DBG(CXT
, ul_debugobj(cxt
, "assigning device %s", fname
));
588 /* redirect request to parent */
590 int rc
, org
= fdisk_is_listonly(cxt
->parent
);
592 /* assign_device() is sensitive to "listonly" mode, so let's
593 * follow the current context setting for the parent to avoid
594 * unwanted extra warnings. */
595 fdisk_enable_listonly(cxt
->parent
, fdisk_is_listonly(cxt
));
597 rc
= fdisk_assign_device(cxt
->parent
, fname
, readonly
);
598 fdisk_enable_listonly(cxt
->parent
, org
);
601 rc
= init_nested_from_parent(cxt
, 0);
603 fdisk_probe_labels(cxt
);
609 fd
= open(fname
, (readonly
? O_RDONLY
: O_RDWR
) | O_CLOEXEC
);
613 if (fstat(fd
, &cxt
->dev_st
) != 0)
616 cxt
->readonly
= readonly
;
618 cxt
->dev_path
= strdup(fname
);
622 fdisk_discover_topology(cxt
);
623 fdisk_discover_geometry(cxt
);
625 fdisk_apply_user_device_properties(cxt
);
627 if (fdisk_read_firstsector(cxt
) < 0)
630 fdisk_probe_labels(cxt
);
632 fdisk_apply_label_device_properties(cxt
);
634 /* warn about obsolete stuff on the device if we aren't in
635 * list-only mode and there is not PT yet */
636 if (!fdisk_is_listonly(cxt
) && !fdisk_has_label(cxt
)
637 && fdisk_check_collisions(cxt
) < 0)
640 DBG(CXT
, ul_debugobj(cxt
, "initialized for %s [%s]",
641 fname
, readonly
? "READ-ONLY" : "READ-WRITE"));
648 DBG(CXT
, ul_debugobj(cxt
, "failed to assign device [rc=%d]", rc
));
654 * fdisk_deassign_device:
656 * @nosync: disable fsync()
658 * Close device and call fsync(). If the @cxt is nested context than the
659 * request is redirected to the parent.
661 * Returns: 0 on success, < 0 on error.
663 int fdisk_deassign_device(struct fdisk_context
*cxt
, int nosync
)
666 assert(cxt
->dev_fd
>= 0);
669 int rc
= fdisk_deassign_device(cxt
->parent
, nosync
);
672 rc
= init_nested_from_parent(cxt
, 0);
676 DBG(CXT
, ul_debugobj(cxt
, "de-assigning device %s", cxt
->dev_path
));
681 if (fsync(cxt
->dev_fd
) || close(cxt
->dev_fd
)) {
682 fdisk_warn(cxt
, _("%s: close device failed"),
688 fdisk_info(cxt
, _("Syncing disks."));
694 cxt
->dev_path
= NULL
;
702 * fdisk_reassign_device:
705 * This function is "hard reset" of the context and it does not write anything
706 * to the device. All in-memory changes associated with the context will be
707 * lost. It's recommended to use this function after some fatal problem when the
708 * context (and label specific driver) is in an undefined state.
710 * Returns: 0 on success, < 0 on error.
712 int fdisk_reassign_device(struct fdisk_context
*cxt
)
718 assert(cxt
->dev_fd
>= 0);
720 DBG(CXT
, ul_debugobj(cxt
, "re-assigning device %s", cxt
->dev_path
));
722 devname
= strdup(cxt
->dev_path
);
726 rdonly
= cxt
->readonly
;
728 fdisk_deassign_device(cxt
, 1);
729 rc
= fdisk_assign_device(cxt
, devname
, rdonly
);
736 * fdisk_reread_partition_table:
739 * Force *kernel* to re-read partition table on block devices.
741 * Returns: 0 on success, < 0 in case of error.
743 int fdisk_reread_partition_table(struct fdisk_context
*cxt
)
748 assert(cxt
->dev_fd
>= 0);
750 if (!S_ISBLK(cxt
->dev_st
.st_mode
))
753 DBG(CXT
, ul_debugobj(cxt
, "calling re-read ioctl"));
756 fdisk_info(cxt
, _("Calling ioctl() to re-read partition table."));
757 i
= ioctl(cxt
->dev_fd
, BLKRRPART
);
765 fdisk_warn(cxt
, _("Re-reading the partition table failed."));
767 "The kernel still uses the old table. The "
768 "new table will be used at the next reboot "
769 "or after you run partprobe(8) or kpartx(8)."));
777 static inline int add_to_partitions_array(
778 struct fdisk_partition
***ary
,
779 struct fdisk_partition
*pa
,
780 size_t *n
, size_t nmax
)
783 *ary
= calloc(nmax
, sizeof(struct fdisk_partition
*));
794 * fdisk_reread_changes:
796 * @org: original layout (on disk)
798 * Like fdisk_reread_partition_table() but don't forces kernel re-read all
799 * partition table. The BLKPG_* ioctls are used for individual partitions. The
800 * advantage is that unmodified partitions maybe mounted.
802 * The function behavies like fdisk_reread_partition_table() on systems where
803 * are no available BLKPG_* ioctls.
805 * Returns: <0 on error, or 0.
808 int fdisk_reread_changes(struct fdisk_context
*cxt
, struct fdisk_table
*org
)
810 struct fdisk_table
*tb
= NULL
;
811 struct fdisk_iter itr
;
812 struct fdisk_partition
*pa
;
813 struct fdisk_partition
**rem
= NULL
, **add
= NULL
, **upd
= NULL
;
814 int change
, rc
= 0, err
= 0;
815 size_t nparts
, i
, nadds
= 0, nupds
= 0, nrems
= 0;
817 DBG(CXT
, ul_debugobj(cxt
, "rereading changes"));
819 fdisk_reset_iter(&itr
, FDISK_ITER_FORWARD
);
821 /* the current layout */
822 fdisk_get_partitions(cxt
, &tb
);
823 /* maximal number of partitions */
824 nparts
= max(fdisk_table_get_nents(tb
), fdisk_table_get_nents(org
));
826 while (fdisk_diff_tables(org
, tb
, &itr
, &pa
, &change
) == 0) {
827 if (change
== FDISK_DIFF_UNCHANGED
)
830 case FDISK_DIFF_REMOVED
:
831 rc
= add_to_partitions_array(&rem
, pa
, &nrems
, nparts
);
833 case FDISK_DIFF_ADDED
:
834 rc
= add_to_partitions_array(&add
, pa
, &nadds
, nparts
);
836 case FDISK_DIFF_RESIZED
:
837 rc
= add_to_partitions_array(&upd
, pa
, &nupds
, nparts
);
839 case FDISK_DIFF_MOVED
:
840 rc
= add_to_partitions_array(&rem
, pa
, &nrems
, nparts
);
841 rc
= add_to_partitions_array(&add
, pa
, &nadds
, nparts
);
848 for (i
= 0; i
< nrems
; i
++) {
850 DBG(PART
, ul_debugobj(pa
, "#%zu calling BLKPG_DEL_PARTITION", pa
->partno
));
851 if (partx_del_partition(cxt
->dev_fd
, pa
->partno
+ 1) != 0) {
852 fdisk_warn(cxt
, _("Failed to remove partition %zu from system"), pa
->partno
+ 1);
856 for (i
= 0; i
< nupds
; i
++) {
858 DBG(PART
, ul_debugobj(pa
, "#%zu calling BLKPG_RESIZE_PARTITION", pa
->partno
));
859 if (partx_resize_partition(cxt
->dev_fd
, pa
->partno
+ 1, pa
->start
, pa
->size
) != 0) {
860 fdisk_warn(cxt
, _("Failed to update system information about partition %zu"), pa
->partno
+ 1);
864 for (i
= 0; i
< nadds
; i
++) {
866 DBG(PART
, ul_debugobj(pa
, "#%zu calling BLKPG_ADD_PARTITION", pa
->partno
));
867 if (partx_add_partition(cxt
->dev_fd
, pa
->partno
+ 1, pa
->start
, pa
->size
) != 0) {
868 fdisk_warn(cxt
, _("Failed to add partition %zu to system"), pa
->partno
+ 1);
874 "The kernel still uses the old partitions. The new "
875 "table will be used at the next reboot. "));
880 fdisk_unref_table(tb
);
884 int fdisk_reread_changes(struct fdisk_context
*cxt
,
885 struct fdisk_table
*org
__attribute__((__unused__
))) {
886 return fdisk_reread_partition_table(cxt
);
891 * fdisk_device_is_used:
894 * On systems where is no BLKRRPART ioctl the function returns zero and
895 * sets errno to ENOSYS.
897 * Returns: 1 if the device assigned to the context is used by system, or 0.
899 int fdisk_device_is_used(struct fdisk_context
*cxt
)
904 assert(cxt
->dev_fd
>= 0);
909 /* it seems kernel always return EINVAL for BLKRRPART on loopdevices */
910 if (S_ISBLK(cxt
->dev_st
.st_mode
)
911 && major(cxt
->dev_st
.st_rdev
) != LOOPDEV_MAJOR
) {
912 DBG(CXT
, ul_debugobj(cxt
, "calling re-read ioctl"));
913 rc
= ioctl(cxt
->dev_fd
, BLKRRPART
) != 0;
918 DBG(CXT
, ul_debugobj(cxt
, "device used: %s [errno=%d]", rc
? "TRUE" : "FALSE", errno
));
926 * Returns: 1 if device open readonly
928 int fdisk_is_readonly(struct fdisk_context
*cxt
)
931 return cxt
->readonly
;
940 * Returns: 1 if open file descriptor is regular file rather than a block device.
942 int fdisk_is_regfile(struct fdisk_context
*cxt
)
945 return S_ISREG(cxt
->dev_st
.st_mode
);
949 * fdisk_unref_context:
950 * @cxt: fdisk context
952 * Deallocates context struct.
954 void fdisk_unref_context(struct fdisk_context
*cxt
)
962 if (cxt
->refcount
<= 0) {
963 DBG(CXT
, ul_debugobj(cxt
, "freeing context %p for %s", cxt
, cxt
->dev_path
));
965 reset_context(cxt
); /* this is sensitive to parent<->child relationship! */
967 /* deallocate label's private stuff */
968 for (i
= 0; i
< cxt
->nlabels
; i
++) {
971 if (cxt
->labels
[i
]->op
->free
)
972 cxt
->labels
[i
]->op
->free(cxt
->labels
[i
]);
974 free(cxt
->labels
[i
]);
977 fdisk_unref_context(cxt
->parent
);
986 * fdisk_enable_details:
988 * @enable: true/false
990 * Enables or disables "details" display mode. This function has effect to
991 * fdisk_partition_to_string() function.
993 * Returns: 0 on success, < 0 on error.
995 int fdisk_enable_details(struct fdisk_context
*cxt
, int enable
)
998 cxt
->display_details
= enable
? 1 : 0;
1006 * Returns: 1 if details are enabled
1008 int fdisk_is_details(struct fdisk_context
*cxt
)
1011 return cxt
->display_details
== 1;
1015 * fdisk_enable_listonly:
1017 * @enable: true/false
1019 * Just list partition only, don't care about another details, mistakes, ...
1021 * Returns: 0 on success, < 0 on error.
1023 int fdisk_enable_listonly(struct fdisk_context
*cxt
, int enable
)
1026 cxt
->listonly
= enable
? 1 : 0;
1031 * fdisk_is_listonly:
1034 * Returns: 1 if list-only mode enabled
1036 int fdisk_is_listonly(struct fdisk_context
*cxt
)
1039 return cxt
->listonly
== 1;
1046 * @str: "cylinder" or "sector".
1048 * This is pure shit, unfortunately for example Sun addresses begin of the
1049 * partition by cylinders...
1051 * Returns: 0 on success, <0 on error.
1053 int fdisk_set_unit(struct fdisk_context
*cxt
, const char *str
)
1057 cxt
->display_in_cyl_units
= 0;
1062 if (strcmp(str
, "cylinder") == 0 || strcmp(str
, "cylinders") == 0)
1063 cxt
->display_in_cyl_units
= 1;
1065 else if (strcmp(str
, "sector") == 0 || strcmp(str
, "sectors") == 0)
1066 cxt
->display_in_cyl_units
= 0;
1068 DBG(CXT
, ul_debugobj(cxt
, "display unit: %s", fdisk_get_unit(cxt
, 0)));
1075 * @n: FDISK_PLURAL or FDISK_SINGULAR
1077 * Returns: unit name.
1079 const char *fdisk_get_unit(struct fdisk_context
*cxt
, int n
)
1083 if (fdisk_use_cylinders(cxt
))
1084 return P_("cylinder", "cylinders", n
);
1085 return P_("sector", "sectors", n
);
1089 * fdisk_use_cylinders:
1092 * Returns: 1 if user wants to display in cylinders.
1094 int fdisk_use_cylinders(struct fdisk_context
*cxt
)
1097 return cxt
->display_in_cyl_units
== 1;
1101 * fdisk_get_units_per_sector:
1104 * This is necessary only for brain dead situations when we use "cylinders";
1106 * Returns: number of "units" per sector, default is 1 if display unit is sector.
1108 unsigned int fdisk_get_units_per_sector(struct fdisk_context
*cxt
)
1112 if (fdisk_use_cylinders(cxt
)) {
1113 assert(cxt
->geom
.heads
);
1114 return cxt
->geom
.heads
* cxt
->geom
.sectors
;
1120 * fdisk_get_optimal_iosize:
1123 * The optimal I/O is optional and does not have to be provided by device,
1124 * anyway libfdisk never returns zero. If the optimal I/O size is not provided
1125 * then libfdisk returns minimal I/O size or sector size.
1127 * Returns: optimal I/O size in bytes.
1129 unsigned long fdisk_get_optimal_iosize(struct fdisk_context
*cxt
)
1132 return cxt
->optimal_io_size
? cxt
->optimal_io_size
: cxt
->io_size
;
1136 * fdisk_get_minimal_iosize:
1139 * Returns: minimal I/O size in bytes
1141 unsigned long fdisk_get_minimal_iosize(struct fdisk_context
*cxt
)
1144 return cxt
->min_io_size
;
1148 * fdisk_get_physector_size:
1151 * Returns: physical sector size in bytes
1153 unsigned long fdisk_get_physector_size(struct fdisk_context
*cxt
)
1156 return cxt
->phy_sector_size
;
1160 * fdisk_get_sector_size:
1163 * Returns: logical sector size in bytes
1165 unsigned long fdisk_get_sector_size(struct fdisk_context
*cxt
)
1168 return cxt
->sector_size
;
1172 * fdisk_get_alignment_offset
1175 * The alignment offset is offset between logical and physical sectors. For
1176 * backward compatibility the first logical sector on 4K disks does no have to
1177 * start on the same place like physical sectors.
1179 * Returns: alignment offset in bytes
1181 unsigned long fdisk_get_alignment_offset(struct fdisk_context
*cxt
)
1184 return cxt
->alignment_offset
;
1188 * fdisk_get_grain_size:
1191 * Returns: grain in bytes used to align partitions (usually 1MiB)
1193 unsigned long fdisk_get_grain_size(struct fdisk_context
*cxt
)
1200 * fdisk_get_first_lba:
1203 * Returns: first possible LBA on disk for data partitions.
1205 fdisk_sector_t
fdisk_get_first_lba(struct fdisk_context
*cxt
)
1208 return cxt
->first_lba
;
1212 * fdisk_set_first_lba:
1213 * @cxt: fdisk context
1214 * @lba: first possible logical sector for data
1216 * It's strongly recommended to use the default library setting. The first LBA
1217 * is always reset by fdisk_assign_device(), fdisk_override_geometry()
1218 * and fdisk_reset_alignment(). This is very low level function and library
1219 * does not check if your setting makes any sense.
1221 * This function is necessary only when you want to work with very unusual
1222 * partition tables like GPT protective MBR or hybrid partition tables on
1223 * bootable media where the first partition may start on very crazy offsets.
1225 * Returns: 0 on success, <0 on error.
1227 fdisk_sector_t
fdisk_set_first_lba(struct fdisk_context
*cxt
, fdisk_sector_t lba
)
1230 DBG(CXT
, ul_debugobj(cxt
, "setting first LBA from %ju to %ju",
1231 (uintmax_t) cxt
->first_lba
, (uintmax_t) lba
));
1232 cxt
->first_lba
= lba
;
1237 * fdisk_get_last_lba:
1238 * @cxt: fdisk context
1240 * Note that the device has to be already assigned.
1242 * Returns: last possible LBA on device
1244 fdisk_sector_t
fdisk_get_last_lba(struct fdisk_context
*cxt
)
1246 return cxt
->last_lba
;
1250 * fdisk_set_last_lba:
1251 * @cxt: fdisk context
1252 * @lba: last possible logical sector
1254 * It's strongly recommended to use the default library setting. The last LBA
1255 * is always reset by fdisk_assign_device(), fdisk_override_geometry() and
1256 * fdisk_reset_alignment().
1258 * The default is number of sectors on the device, but maybe modified by the
1259 * current disklabel driver (for example GPT uses the end of disk for backup
1260 * header, so last_lba is smaller than total number of sectors).
1262 * Returns: 0 on success, <0 on error.
1264 fdisk_sector_t
fdisk_set_last_lba(struct fdisk_context
*cxt
, fdisk_sector_t lba
)
1268 if (lba
> cxt
->total_sectors
- 1 || lba
< 1)
1270 cxt
->last_lba
= lba
;
1275 * fdisk_set_size_unit:
1276 * @cxt: fdisk context
1277 * @unit: FDISK_SIZEUNIT_*
1279 * Sets unit for SIZE output field (see fdisk_partition_to_string()).
1281 * Returns: 0 on success, <0 on error.
1283 int fdisk_set_size_unit(struct fdisk_context
*cxt
, int unit
)
1286 cxt
->sizeunit
= unit
;
1291 * fdisk_get_size_unit:
1292 * @cxt: fdisk context
1294 * Gets unit for SIZE output field (see fdisk_partition_to_string()).
1298 int fdisk_get_size_unit(struct fdisk_context
*cxt
)
1301 return cxt
->sizeunit
;
1305 * fdisk_get_nsectors:
1308 * Returns: size of the device in logical sectors.
1310 fdisk_sector_t
fdisk_get_nsectors(struct fdisk_context
*cxt
)
1313 return cxt
->total_sectors
;
1317 * fdisk_get_devname:
1320 * Returns: device name.
1322 const char *fdisk_get_devname(struct fdisk_context
*cxt
)
1325 return cxt
->dev_path
;
1332 * Returns: device file descriptor.
1334 int fdisk_get_devfd(struct fdisk_context
*cxt
)
1341 * fdisk_get_geom_heads:
1344 * Returns: number of geometry heads.
1346 unsigned int fdisk_get_geom_heads(struct fdisk_context
*cxt
)
1349 return cxt
->geom
.heads
;
1352 * fdisk_get_geom_sectors:
1355 * Returns: number of geometry sectors.
1357 fdisk_sector_t
fdisk_get_geom_sectors(struct fdisk_context
*cxt
)
1360 return cxt
->geom
.sectors
;
1365 * fdisk_get_geom_cylinders:
1368 * Returns: number of geometry cylinders
1370 fdisk_sector_t
fdisk_get_geom_cylinders(struct fdisk_context
*cxt
)
1373 return cxt
->geom
.cylinders
;
1376 int fdisk_missing_geometry(struct fdisk_context
*cxt
)
1380 if (!cxt
|| !cxt
->label
)
1383 rc
= (fdisk_label_require_geometry(cxt
->label
) &&
1384 (!cxt
->geom
.heads
|| !cxt
->geom
.sectors
1385 || !cxt
->geom
.cylinders
));
1387 if (rc
&& !fdisk_is_listonly(cxt
))
1388 fdisk_warnx(cxt
, _("Incomplete geometry setting."));