| /* |
| * fdiskP.h - private library header file |
| * |
| * Copyright (C) 2012 Karel Zak <kzak@redhat.com> |
| * |
| * This file may be redistributed under the terms of the |
| * GNU Lesser General Public License. |
| */ |
| |
| #ifndef _LIBFDISK_PRIVATE_H |
| #define _LIBFDISK_PRIVATE_H |
| |
| #include <errno.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| |
| #include "c.h" |
| #include "libfdisk.h" |
| |
| #include "nls.h" /* temporary before dialog API will be implamented */ |
| #include "list.h" |
| #include "debug.h" |
| #include <stdio.h> |
| #include <stdarg.h> |
| |
| /* features */ |
| #define CONFIG_LIBFDISK_ASSERT |
| |
| #ifdef CONFIG_LIBFDISK_ASSERT |
| #include <assert.h> |
| #endif |
| |
| /* |
| * Debug |
| */ |
| #define LIBFDISK_DEBUG_HELP (1 << 0) |
| #define LIBFDISK_DEBUG_INIT (1 << 1) |
| #define LIBFDISK_DEBUG_CXT (1 << 2) |
| #define LIBFDISK_DEBUG_LABEL (1 << 3) |
| #define LIBFDISK_DEBUG_ASK (1 << 4) |
| #define LIBFDISK_DEBUG_PART (1 << 6) |
| #define LIBFDISK_DEBUG_PARTTYPE (1 << 7) |
| #define LIBFDISK_DEBUG_TAB (1 << 8) |
| #define LIBFDISK_DEBUG_SCRIPT (1 << 9) |
| #define LIBFDISK_DEBUG_ALL 0xFFFF |
| |
| UL_DEBUG_DECLARE_MASK(libfdisk); |
| #define DBG(m, x) __UL_DBG(libfdisk, LIBFDISK_DEBUG_, m, x) |
| #define ON_DBG(m, x) __UL_DBG_CALL(libfdisk, LIBFDISK_DEBUG_, m, x) |
| #define DBG_FLUSH __UL_DBG_FLUSH(libfdisk, LIBFDISK_DEBUG_) |
| |
| #ifdef TEST_PROGRAM |
| struct fdisk_test { |
| const char *name; |
| int (*body)(struct fdisk_test *ts, int argc, char *argv[]); |
| const char *usage; |
| }; |
| |
| /* test.c */ |
| extern int fdisk_run_test(struct fdisk_test *tests, int argc, char *argv[]); |
| #endif |
| |
| |
| /* |
| * Generic iterator |
| */ |
| struct fdisk_iter { |
| struct list_head *p; /* current position */ |
| struct list_head *head; /* start position */ |
| int direction; /* FDISK_ITER_{FOR,BACK}WARD */ |
| }; |
| |
| #define IS_ITER_FORWARD(_i) ((_i)->direction == FDISK_ITER_FORWARD) |
| #define IS_ITER_BACKWARD(_i) ((_i)->direction == FDISK_ITER_BACKWARD) |
| |
| #define FDISK_ITER_INIT(itr, list) \ |
| do { \ |
| (itr)->p = IS_ITER_FORWARD(itr) ? \ |
| (list)->next : (list)->prev; \ |
| (itr)->head = (list); \ |
| } while(0) |
| |
| #define FDISK_ITER_ITERATE(itr, res, restype, member) \ |
| do { \ |
| res = list_entry((itr)->p, restype, member); \ |
| (itr)->p = IS_ITER_FORWARD(itr) ? \ |
| (itr)->p->next : (itr)->p->prev; \ |
| } while(0) |
| |
| /* |
| * Partition types |
| */ |
| struct fdisk_parttype { |
| unsigned int code; /* type as number or zero */ |
| char *name; /* description */ |
| char *typestr; /* type as string or NULL */ |
| |
| unsigned int flags; /* FDISK_PARTTYPE_* flags */ |
| int refcount; /* reference counter for allocated types */ |
| }; |
| |
| enum { |
| FDISK_PARTTYPE_UNKNOWN = (1 << 1), |
| FDISK_PARTTYPE_INVISIBLE = (1 << 2), |
| FDISK_PARTTYPE_ALLOCATED = (1 << 3) |
| }; |
| |
| #define fdisk_parttype_is_invisible(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_INVISIBLE)) |
| #define fdisk_parttype_is_allocated(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED)) |
| |
| struct fdisk_partition { |
| int refcount; /* reference counter */ |
| |
| size_t partno; /* partition number */ |
| size_t parent_partno; /* for logical partitions */ |
| |
| fdisk_sector_t start; /* first sectors */ |
| fdisk_sector_t size; /* size in sectors */ |
| |
| char *name; /* partition name */ |
| char *uuid; /* partition UUID */ |
| char *attrs; /* partition flags/attributes converted to string */ |
| struct fdisk_parttype *type; /* partition type */ |
| |
| struct list_head parts; /* list of partitions */ |
| |
| /* extra fields for partition_to_string() */ |
| char start_post; /* start postfix (e.g. '+') */ |
| char end_post; /* end postfix */ |
| char size_post; /* size postfix */ |
| |
| uint64_t fsize; /* bsd junk */ |
| uint64_t bsize; |
| uint64_t cpg; |
| |
| char *start_chs; /* start C/H/S in string */ |
| char *end_chs; /* end C/H/S in string */ |
| |
| unsigned int boot; /* MBR: bootable */ |
| |
| unsigned int container : 1, /* container partition (e.g. extended partition) */ |
| end_follow_default : 1, /* use default end */ |
| freespace : 1, /* this is free space */ |
| partno_follow_default : 1, /* use default partno */ |
| size_explicit : 1, /* don't align the size */ |
| start_follow_default : 1, /* use default start */ |
| used : 1, /* partition already used */ |
| wholedisk : 1; /* special system partition */ |
| }; |
| |
| #define FDISK_INIT_UNDEF(_x) ((_x) = (__typeof__(_x)) -1) |
| #define FDISK_IS_UNDEF(_x) ((_x) == (__typeof__(_x)) -1) |
| |
| struct fdisk_table { |
| struct list_head parts; /* partitions */ |
| int refcount; |
| size_t nents; /* number of partitions */ |
| }; |
| |
| /* |
| * Legacy CHS based geometry |
| */ |
| struct fdisk_geometry { |
| unsigned int heads; |
| fdisk_sector_t sectors; |
| fdisk_sector_t cylinders; |
| }; |
| |
| /* |
| * Label specific operations |
| */ |
| struct fdisk_label_operations { |
| /* probe disk label */ |
| int (*probe)(struct fdisk_context *cxt); |
| /* write in-memory changes to disk */ |
| int (*write)(struct fdisk_context *cxt); |
| /* verify the partition table */ |
| int (*verify)(struct fdisk_context *cxt); |
| /* create new disk label */ |
| int (*create)(struct fdisk_context *cxt); |
| /* list disklabel details */ |
| int (*list)(struct fdisk_context *cxt); |
| /* returns offset and size of the 'n' part of the PT */ |
| int (*locate)(struct fdisk_context *cxt, int n, const char **name, off_t *offset, size_t *size); |
| /* reorder partitions */ |
| int (*reorder)(struct fdisk_context *cxt); |
| |
| /* get disk label ID */ |
| int (*get_id)(struct fdisk_context *cxt, char **id); |
| /* set disk label ID */ |
| int (*set_id)(struct fdisk_context *cxt); |
| |
| |
| /* new partition */ |
| int (*add_part)(struct fdisk_context *cxt, struct fdisk_partition *pa, |
| size_t *partno); |
| /* delete partition */ |
| int (*del_part)(struct fdisk_context *cxt, size_t partnum); |
| |
| /* fill in partition struct */ |
| int (*get_part)(struct fdisk_context *cxt, size_t n, |
| struct fdisk_partition *pa); |
| /* modify partition */ |
| int (*set_part)(struct fdisk_context *cxt, size_t n, |
| struct fdisk_partition *pa); |
| |
| /* return state of the partition */ |
| int (*part_is_used)(struct fdisk_context *cxt, size_t partnum); |
| |
| int (*part_toggle_flag)(struct fdisk_context *cxt, size_t i, unsigned long flag); |
| |
| /* refresh alignment setting */ |
| int (*reset_alignment)(struct fdisk_context *cxt); |
| |
| /* free in-memory label stuff */ |
| void (*free)(struct fdisk_label *lb); |
| |
| /* deinit in-memory label stuff */ |
| void (*deinit)(struct fdisk_label *lb); |
| }; |
| |
| /* |
| * The fields describes how to display libfdisk_partition |
| */ |
| struct fdisk_field { |
| int id; /* FDISK_FIELD_* */ |
| const char *name; /* field name */ |
| double width; /* field width (compatible with libsmartcols whint) */ |
| int flags; /* FDISK_FIELDFL_* */ |
| }; |
| |
| /* note that the defauls is to display a column always */ |
| enum { |
| FDISK_FIELDFL_DETAIL = (1 << 1), /* only display if fdisk_is_details() */ |
| FDISK_FIELDFL_EYECANDY = (1 << 2), /* don't display if fdisk_is_details() */ |
| FDISK_FIELDFL_NUMBER = (1 << 3), /* column display numbers */ |
| }; |
| |
| /* |
| * Generic label |
| */ |
| struct fdisk_label { |
| const char *name; /* label name */ |
| enum fdisk_labeltype id; /* FDISK_DISKLABEL_* */ |
| struct fdisk_parttype *parttypes; /* supported partitions types */ |
| size_t nparttypes; /* number of items in parttypes[] */ |
| |
| size_t nparts_max; /* maximal number of partitions */ |
| size_t nparts_cur; /* number of currently used partitions */ |
| |
| int flags; /* FDISK_LABEL_FL_* flags */ |
| |
| unsigned int changed:1, /* label has been modified */ |
| disabled:1; /* this driver is disabled at all */ |
| |
| const struct fdisk_field *fields; /* all possible fields */ |
| size_t nfields; |
| |
| const struct fdisk_label_operations *op; |
| }; |
| |
| |
| /* label driver flags */ |
| enum { |
| FDISK_LABEL_FL_REQUIRE_GEOMETRY = (1 << 2), |
| FDISK_LABEL_FL_INCHARS_PARTNO = (1 << 3) |
| }; |
| |
| /* label allocators */ |
| extern struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt); |
| extern struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt); |
| extern struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt); |
| extern struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt); |
| extern struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt); |
| |
| |
| struct ask_menuitem { |
| char key; |
| const char *name; |
| const char *desc; |
| |
| struct ask_menuitem *next; |
| }; |
| |
| /* fdisk dialog -- note that nothing from this stuff will be directly exported, |
| * we will have get/set() function for everything. |
| */ |
| struct fdisk_ask { |
| int type; /* FDISK_ASKTYPE_* */ |
| char *query; |
| |
| int refcount; |
| |
| union { |
| /* FDISK_ASKTYPE_{NUMBER,OFFSET} */ |
| struct ask_number { |
| uint64_t hig; /* high limit */ |
| uint64_t low; /* low limit */ |
| uint64_t dfl; /* default */ |
| uint64_t result; |
| uint64_t base; /* for relative results */ |
| uint64_t unit; /* unit for offsets */ |
| const char *range; /* by library generated list */ |
| unsigned int relative :1, |
| inchars :1; |
| } num; |
| /* FDISK_ASKTYPE_{WARN,WARNX,..} */ |
| struct ask_print { |
| const char *mesg; |
| int errnum; /* errno */ |
| } print; |
| /* FDISK_ASKTYPE_YESNO */ |
| struct ask_yesno { |
| int result; /* TRUE or FALSE */ |
| } yesno; |
| /* FDISK_ASKTYPE_STRING */ |
| struct ask_string { |
| char *result; /* allocated */ |
| } str; |
| /* FDISK_ASKTYPE_MENU */ |
| struct ask_menu { |
| int dfl; /* default meni item */ |
| int result; |
| struct ask_menuitem *first; |
| } menu; |
| } data; |
| }; |
| |
| struct fdisk_context { |
| int dev_fd; /* device descriptor */ |
| char *dev_path; /* device path */ |
| int refcount; |
| |
| unsigned char *firstsector; /* buffer with master boot record */ |
| unsigned long firstsector_bufsz; |
| |
| /* topology */ |
| unsigned long io_size; /* I/O size used by fdisk */ |
| unsigned long optimal_io_size; /* optional I/O returned by device */ |
| unsigned long min_io_size; /* minimal I/O size */ |
| unsigned long phy_sector_size; /* physical size */ |
| unsigned long sector_size; /* logical size */ |
| unsigned long alignment_offset; |
| |
| unsigned int readonly : 1, /* don't write to the device */ |
| display_in_cyl_units : 1, /* for obscure labels */ |
| display_details : 1, /* expert display mode */ |
| listonly : 1; /* list partition, nothing else */ |
| |
| /* alignment */ |
| unsigned long grain; /* alignment unit */ |
| fdisk_sector_t first_lba; /* recommended begin of the first partition */ |
| fdisk_sector_t last_lba; /* recomennded end of last partition */ |
| |
| /* geometry */ |
| fdisk_sector_t total_sectors; /* in logical sectors */ |
| struct fdisk_geometry geom; |
| |
| /* user setting to overwrite device default */ |
| struct fdisk_geometry user_geom; |
| unsigned long user_pyh_sector; |
| unsigned long user_log_sector; |
| |
| struct fdisk_label *label; /* current label, pointer to labels[] */ |
| |
| size_t nlabels; /* number of initialized label drivers */ |
| struct fdisk_label *labels[8]; /* all supported labels, |
| * FIXME: use any enum rather than hardcoded number */ |
| |
| int (*ask_cb)(struct fdisk_context *, struct fdisk_ask *, void *); /* fdisk dialogs callback */ |
| void *ask_data; /* ask_cb() data */ |
| |
| struct fdisk_context *parent; /* for nested PT */ |
| struct fdisk_script *script; /* what we want to follow */ |
| }; |
| |
| /* partition.c */ |
| int fdisk_partition_next_partno(struct fdisk_partition *pa, |
| struct fdisk_context *cxt, |
| size_t *n); |
| |
| /* context.c */ |
| extern int __fdisk_switch_label(struct fdisk_context *cxt, |
| struct fdisk_label *lb); |
| extern int fdisk_missing_geometry(struct fdisk_context *cxt); |
| |
| /* alignment.c */ |
| fdisk_sector_t fdisk_scround(struct fdisk_context *cxt, fdisk_sector_t num); |
| fdisk_sector_t fdisk_cround(struct fdisk_context *cxt, fdisk_sector_t num); |
| |
| extern int fdisk_discover_geometry(struct fdisk_context *cxt); |
| extern int fdisk_discover_topology(struct fdisk_context *cxt); |
| |
| extern int fdisk_apply_user_device_properties(struct fdisk_context *cxt); |
| extern void fdisk_zeroize_device_properties(struct fdisk_context *cxt); |
| |
| /* utils.c */ |
| extern int fdisk_init_firstsector_buffer(struct fdisk_context *cxt); |
| extern int fdisk_read_firstsector(struct fdisk_context *cxt); |
| extern char *fdisk_partname(const char *dev, size_t partno); |
| |
| /* label.c */ |
| extern int fdisk_probe_labels(struct fdisk_context *cxt); |
| extern void fdisk_deinit_label(struct fdisk_label *lb); |
| |
| /* ask.c */ |
| struct fdisk_ask *fdisk_new_ask(void); |
| void fdisk_reset_ask(struct fdisk_ask *ask); |
| int fdisk_ask_set_query(struct fdisk_ask *ask, const char *str); |
| int fdisk_ask_set_type(struct fdisk_ask *ask, int type); |
| int fdisk_do_ask(struct fdisk_context *cxt, struct fdisk_ask *ask); |
| int fdisk_ask_number_set_range(struct fdisk_ask *ask, const char *range); |
| int fdisk_ask_number_set_default(struct fdisk_ask *ask, uint64_t dflt); |
| int fdisk_ask_number_set_low(struct fdisk_ask *ask, uint64_t low); |
| int fdisk_ask_number_set_high(struct fdisk_ask *ask, uint64_t high); |
| int fdisk_ask_number_set_base(struct fdisk_ask *ask, uint64_t base); |
| int fdisk_ask_number_set_unit(struct fdisk_ask *ask, uint64_t unit); |
| int fdisk_ask_number_is_relative(struct fdisk_ask *ask); |
| int fdisk_ask_menu_set_default(struct fdisk_ask *ask, int dfl); |
| int fdisk_ask_menu_add_item(struct fdisk_ask *ask, int key, |
| const char *name, const char *desc); |
| int fdisk_ask_print_set_errno(struct fdisk_ask *ask, int errnum); |
| int fdisk_ask_print_set_mesg(struct fdisk_ask *ask, const char *mesg); |
| int fdisk_info_new_partition( |
| struct fdisk_context *cxt, |
| int num, fdisk_sector_t start, fdisk_sector_t stop, |
| struct fdisk_parttype *t); |
| |
| /* dos.c */ |
| extern struct dos_partition *fdisk_dos_get_partition( |
| struct fdisk_context *cxt, |
| size_t i); |
| |
| #endif /* _LIBFDISK_PRIVATE_H */ |