bigbiff | 7b4c7a6 | 2015-01-01 19:44:14 -0500 | [diff] [blame] | 1 | /* |
| 2 | * fdiskP.h - private library header file |
| 3 | * |
| 4 | * Copyright (C) 2012 Karel Zak <kzak@redhat.com> |
| 5 | * |
| 6 | * This file may be redistributed under the terms of the |
| 7 | * GNU Lesser General Public License. |
| 8 | */ |
| 9 | |
| 10 | #ifndef _LIBFDISK_PRIVATE_H |
| 11 | #define _LIBFDISK_PRIVATE_H |
| 12 | |
| 13 | #include <errno.h> |
| 14 | #include <stdlib.h> |
| 15 | #include <string.h> |
| 16 | #include <sys/stat.h> |
| 17 | #include <sys/types.h> |
| 18 | #include <unistd.h> |
| 19 | |
| 20 | |
| 21 | #include "c.h" |
| 22 | #include "libfdisk.h" |
| 23 | |
| 24 | #include "nls.h" /* temporary before dialog API will be implamented */ |
| 25 | #include "list.h" |
| 26 | #include "debug.h" |
| 27 | #include <stdio.h> |
| 28 | #include <stdarg.h> |
| 29 | |
| 30 | /* features */ |
| 31 | #define CONFIG_LIBFDISK_ASSERT |
| 32 | |
| 33 | #ifdef CONFIG_LIBFDISK_ASSERT |
| 34 | #include <assert.h> |
| 35 | #endif |
| 36 | |
| 37 | /* |
| 38 | * Debug |
| 39 | */ |
| 40 | #define LIBFDISK_DEBUG_HELP (1 << 0) |
| 41 | #define LIBFDISK_DEBUG_INIT (1 << 1) |
| 42 | #define LIBFDISK_DEBUG_CXT (1 << 2) |
| 43 | #define LIBFDISK_DEBUG_LABEL (1 << 3) |
| 44 | #define LIBFDISK_DEBUG_ASK (1 << 4) |
| 45 | #define LIBFDISK_DEBUG_PART (1 << 6) |
| 46 | #define LIBFDISK_DEBUG_PARTTYPE (1 << 7) |
| 47 | #define LIBFDISK_DEBUG_TAB (1 << 8) |
| 48 | #define LIBFDISK_DEBUG_SCRIPT (1 << 9) |
| 49 | #define LIBFDISK_DEBUG_ALL 0xFFFF |
| 50 | |
| 51 | UL_DEBUG_DECLARE_MASK(libfdisk); |
| 52 | #define DBG(m, x) __UL_DBG(libfdisk, LIBFDISK_DEBUG_, m, x) |
| 53 | #define ON_DBG(m, x) __UL_DBG_CALL(libfdisk, LIBFDISK_DEBUG_, m, x) |
| 54 | #define DBG_FLUSH __UL_DBG_FLUSH(libfdisk, LIBFDISK_DEBUG_) |
| 55 | |
| 56 | #ifdef TEST_PROGRAM |
| 57 | struct fdisk_test { |
| 58 | const char *name; |
| 59 | int (*body)(struct fdisk_test *ts, int argc, char *argv[]); |
| 60 | const char *usage; |
| 61 | }; |
| 62 | |
| 63 | /* test.c */ |
| 64 | extern int fdisk_run_test(struct fdisk_test *tests, int argc, char *argv[]); |
| 65 | #endif |
| 66 | |
| 67 | |
| 68 | /* |
| 69 | * Generic iterator |
| 70 | */ |
| 71 | struct fdisk_iter { |
| 72 | struct list_head *p; /* current position */ |
| 73 | struct list_head *head; /* start position */ |
| 74 | int direction; /* FDISK_ITER_{FOR,BACK}WARD */ |
| 75 | }; |
| 76 | |
| 77 | #define IS_ITER_FORWARD(_i) ((_i)->direction == FDISK_ITER_FORWARD) |
| 78 | #define IS_ITER_BACKWARD(_i) ((_i)->direction == FDISK_ITER_BACKWARD) |
| 79 | |
| 80 | #define FDISK_ITER_INIT(itr, list) \ |
| 81 | do { \ |
| 82 | (itr)->p = IS_ITER_FORWARD(itr) ? \ |
| 83 | (list)->next : (list)->prev; \ |
| 84 | (itr)->head = (list); \ |
| 85 | } while(0) |
| 86 | |
| 87 | #define FDISK_ITER_ITERATE(itr, res, restype, member) \ |
| 88 | do { \ |
| 89 | res = list_entry((itr)->p, restype, member); \ |
| 90 | (itr)->p = IS_ITER_FORWARD(itr) ? \ |
| 91 | (itr)->p->next : (itr)->p->prev; \ |
| 92 | } while(0) |
| 93 | |
| 94 | /* |
| 95 | * Partition types |
| 96 | */ |
| 97 | struct fdisk_parttype { |
| 98 | unsigned int code; /* type as number or zero */ |
| 99 | char *name; /* description */ |
| 100 | char *typestr; /* type as string or NULL */ |
| 101 | |
| 102 | unsigned int flags; /* FDISK_PARTTYPE_* flags */ |
| 103 | int refcount; /* reference counter for allocated types */ |
| 104 | }; |
| 105 | |
| 106 | enum { |
| 107 | FDISK_PARTTYPE_UNKNOWN = (1 << 1), |
| 108 | FDISK_PARTTYPE_INVISIBLE = (1 << 2), |
| 109 | FDISK_PARTTYPE_ALLOCATED = (1 << 3) |
| 110 | }; |
| 111 | |
| 112 | #define fdisk_parttype_is_invisible(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_INVISIBLE)) |
| 113 | #define fdisk_parttype_is_allocated(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED)) |
| 114 | |
| 115 | struct fdisk_partition { |
| 116 | int refcount; /* reference counter */ |
| 117 | |
| 118 | size_t partno; /* partition number */ |
| 119 | size_t parent_partno; /* for logical partitions */ |
| 120 | |
| 121 | fdisk_sector_t start; /* first sectors */ |
| 122 | fdisk_sector_t size; /* size in sectors */ |
| 123 | |
| 124 | char *name; /* partition name */ |
| 125 | char *uuid; /* partition UUID */ |
| 126 | char *attrs; /* partition flags/attributes converted to string */ |
| 127 | struct fdisk_parttype *type; /* partition type */ |
| 128 | |
| 129 | struct list_head parts; /* list of partitions */ |
| 130 | |
| 131 | /* extra fields for partition_to_string() */ |
| 132 | char start_post; /* start postfix (e.g. '+') */ |
| 133 | char end_post; /* end postfix */ |
| 134 | char size_post; /* size postfix */ |
| 135 | |
| 136 | uint64_t fsize; /* bsd junk */ |
| 137 | uint64_t bsize; |
| 138 | uint64_t cpg; |
| 139 | |
| 140 | char *start_chs; /* start C/H/S in string */ |
| 141 | char *end_chs; /* end C/H/S in string */ |
| 142 | |
| 143 | unsigned int boot; /* MBR: bootable */ |
| 144 | |
| 145 | unsigned int container : 1, /* container partition (e.g. extended partition) */ |
| 146 | end_follow_default : 1, /* use default end */ |
| 147 | freespace : 1, /* this is free space */ |
| 148 | partno_follow_default : 1, /* use default partno */ |
| 149 | size_explicit : 1, /* don't align the size */ |
| 150 | start_follow_default : 1, /* use default start */ |
| 151 | used : 1, /* partition already used */ |
| 152 | wholedisk : 1; /* special system partition */ |
| 153 | }; |
| 154 | |
| 155 | #define FDISK_INIT_UNDEF(_x) ((_x) = (__typeof__(_x)) -1) |
| 156 | #define FDISK_IS_UNDEF(_x) ((_x) == (__typeof__(_x)) -1) |
| 157 | |
| 158 | struct fdisk_table { |
| 159 | struct list_head parts; /* partitions */ |
| 160 | int refcount; |
| 161 | size_t nents; /* number of partitions */ |
| 162 | }; |
| 163 | |
| 164 | /* |
| 165 | * Legacy CHS based geometry |
| 166 | */ |
| 167 | struct fdisk_geometry { |
| 168 | unsigned int heads; |
| 169 | fdisk_sector_t sectors; |
| 170 | fdisk_sector_t cylinders; |
| 171 | }; |
| 172 | |
| 173 | /* |
| 174 | * Label specific operations |
| 175 | */ |
| 176 | struct fdisk_label_operations { |
| 177 | /* probe disk label */ |
| 178 | int (*probe)(struct fdisk_context *cxt); |
| 179 | /* write in-memory changes to disk */ |
| 180 | int (*write)(struct fdisk_context *cxt); |
| 181 | /* verify the partition table */ |
| 182 | int (*verify)(struct fdisk_context *cxt); |
| 183 | /* create new disk label */ |
| 184 | int (*create)(struct fdisk_context *cxt); |
| 185 | /* list disklabel details */ |
| 186 | int (*list)(struct fdisk_context *cxt); |
| 187 | /* returns offset and size of the 'n' part of the PT */ |
| 188 | int (*locate)(struct fdisk_context *cxt, int n, const char **name, off_t *offset, size_t *size); |
| 189 | /* reorder partitions */ |
| 190 | int (*reorder)(struct fdisk_context *cxt); |
| 191 | |
| 192 | /* get disk label ID */ |
| 193 | int (*get_id)(struct fdisk_context *cxt, char **id); |
| 194 | /* set disk label ID */ |
| 195 | int (*set_id)(struct fdisk_context *cxt); |
| 196 | |
| 197 | |
| 198 | /* new partition */ |
| 199 | int (*add_part)(struct fdisk_context *cxt, struct fdisk_partition *pa, |
| 200 | size_t *partno); |
| 201 | /* delete partition */ |
| 202 | int (*del_part)(struct fdisk_context *cxt, size_t partnum); |
| 203 | |
| 204 | /* fill in partition struct */ |
| 205 | int (*get_part)(struct fdisk_context *cxt, size_t n, |
| 206 | struct fdisk_partition *pa); |
| 207 | /* modify partition */ |
| 208 | int (*set_part)(struct fdisk_context *cxt, size_t n, |
| 209 | struct fdisk_partition *pa); |
| 210 | |
| 211 | /* return state of the partition */ |
| 212 | int (*part_is_used)(struct fdisk_context *cxt, size_t partnum); |
| 213 | |
| 214 | int (*part_toggle_flag)(struct fdisk_context *cxt, size_t i, unsigned long flag); |
| 215 | |
| 216 | /* refresh alignment setting */ |
| 217 | int (*reset_alignment)(struct fdisk_context *cxt); |
| 218 | |
| 219 | /* free in-memory label stuff */ |
| 220 | void (*free)(struct fdisk_label *lb); |
| 221 | |
| 222 | /* deinit in-memory label stuff */ |
| 223 | void (*deinit)(struct fdisk_label *lb); |
| 224 | }; |
| 225 | |
| 226 | /* |
| 227 | * The fields describes how to display libfdisk_partition |
| 228 | */ |
| 229 | struct fdisk_field { |
| 230 | int id; /* FDISK_FIELD_* */ |
| 231 | const char *name; /* field name */ |
| 232 | double width; /* field width (compatible with libsmartcols whint) */ |
| 233 | int flags; /* FDISK_FIELDFL_* */ |
| 234 | }; |
| 235 | |
| 236 | /* note that the defauls is to display a column always */ |
| 237 | enum { |
| 238 | FDISK_FIELDFL_DETAIL = (1 << 1), /* only display if fdisk_is_details() */ |
| 239 | FDISK_FIELDFL_EYECANDY = (1 << 2), /* don't display if fdisk_is_details() */ |
| 240 | FDISK_FIELDFL_NUMBER = (1 << 3), /* column display numbers */ |
| 241 | }; |
| 242 | |
| 243 | /* |
| 244 | * Generic label |
| 245 | */ |
| 246 | struct fdisk_label { |
| 247 | const char *name; /* label name */ |
| 248 | enum fdisk_labeltype id; /* FDISK_DISKLABEL_* */ |
| 249 | struct fdisk_parttype *parttypes; /* supported partitions types */ |
| 250 | size_t nparttypes; /* number of items in parttypes[] */ |
| 251 | |
| 252 | size_t nparts_max; /* maximal number of partitions */ |
| 253 | size_t nparts_cur; /* number of currently used partitions */ |
| 254 | |
| 255 | int flags; /* FDISK_LABEL_FL_* flags */ |
| 256 | |
| 257 | unsigned int changed:1, /* label has been modified */ |
| 258 | disabled:1; /* this driver is disabled at all */ |
| 259 | |
| 260 | const struct fdisk_field *fields; /* all possible fields */ |
| 261 | size_t nfields; |
| 262 | |
| 263 | const struct fdisk_label_operations *op; |
| 264 | }; |
| 265 | |
| 266 | |
| 267 | /* label driver flags */ |
| 268 | enum { |
| 269 | FDISK_LABEL_FL_REQUIRE_GEOMETRY = (1 << 2), |
| 270 | FDISK_LABEL_FL_INCHARS_PARTNO = (1 << 3) |
| 271 | }; |
| 272 | |
| 273 | /* label allocators */ |
| 274 | extern struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt); |
| 275 | extern struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt); |
| 276 | extern struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt); |
| 277 | extern struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt); |
| 278 | extern struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt); |
| 279 | |
| 280 | |
| 281 | struct ask_menuitem { |
| 282 | char key; |
| 283 | const char *name; |
| 284 | const char *desc; |
| 285 | |
| 286 | struct ask_menuitem *next; |
| 287 | }; |
| 288 | |
| 289 | /* fdisk dialog -- note that nothing from this stuff will be directly exported, |
| 290 | * we will have get/set() function for everything. |
| 291 | */ |
| 292 | struct fdisk_ask { |
| 293 | int type; /* FDISK_ASKTYPE_* */ |
| 294 | char *query; |
| 295 | |
| 296 | int refcount; |
| 297 | |
| 298 | union { |
| 299 | /* FDISK_ASKTYPE_{NUMBER,OFFSET} */ |
| 300 | struct ask_number { |
| 301 | uint64_t hig; /* high limit */ |
| 302 | uint64_t low; /* low limit */ |
| 303 | uint64_t dfl; /* default */ |
| 304 | uint64_t result; |
| 305 | uint64_t base; /* for relative results */ |
| 306 | uint64_t unit; /* unit for offsets */ |
| 307 | const char *range; /* by library generated list */ |
| 308 | unsigned int relative :1, |
| 309 | inchars :1; |
| 310 | } num; |
| 311 | /* FDISK_ASKTYPE_{WARN,WARNX,..} */ |
| 312 | struct ask_print { |
| 313 | const char *mesg; |
| 314 | int errnum; /* errno */ |
| 315 | } print; |
| 316 | /* FDISK_ASKTYPE_YESNO */ |
| 317 | struct ask_yesno { |
| 318 | int result; /* TRUE or FALSE */ |
| 319 | } yesno; |
| 320 | /* FDISK_ASKTYPE_STRING */ |
| 321 | struct ask_string { |
| 322 | char *result; /* allocated */ |
| 323 | } str; |
| 324 | /* FDISK_ASKTYPE_MENU */ |
| 325 | struct ask_menu { |
| 326 | int dfl; /* default meni item */ |
| 327 | int result; |
| 328 | struct ask_menuitem *first; |
| 329 | } menu; |
| 330 | } data; |
| 331 | }; |
| 332 | |
| 333 | struct fdisk_context { |
| 334 | int dev_fd; /* device descriptor */ |
| 335 | char *dev_path; /* device path */ |
| 336 | int refcount; |
| 337 | |
| 338 | unsigned char *firstsector; /* buffer with master boot record */ |
| 339 | unsigned long firstsector_bufsz; |
| 340 | |
| 341 | /* topology */ |
| 342 | unsigned long io_size; /* I/O size used by fdisk */ |
| 343 | unsigned long optimal_io_size; /* optional I/O returned by device */ |
| 344 | unsigned long min_io_size; /* minimal I/O size */ |
| 345 | unsigned long phy_sector_size; /* physical size */ |
| 346 | unsigned long sector_size; /* logical size */ |
| 347 | unsigned long alignment_offset; |
| 348 | |
| 349 | unsigned int readonly : 1, /* don't write to the device */ |
| 350 | display_in_cyl_units : 1, /* for obscure labels */ |
| 351 | display_details : 1, /* expert display mode */ |
| 352 | listonly : 1; /* list partition, nothing else */ |
| 353 | |
| 354 | /* alignment */ |
| 355 | unsigned long grain; /* alignment unit */ |
| 356 | fdisk_sector_t first_lba; /* recommended begin of the first partition */ |
| 357 | fdisk_sector_t last_lba; /* recomennded end of last partition */ |
| 358 | |
| 359 | /* geometry */ |
| 360 | fdisk_sector_t total_sectors; /* in logical sectors */ |
| 361 | struct fdisk_geometry geom; |
| 362 | |
| 363 | /* user setting to overwrite device default */ |
| 364 | struct fdisk_geometry user_geom; |
| 365 | unsigned long user_pyh_sector; |
| 366 | unsigned long user_log_sector; |
| 367 | |
| 368 | struct fdisk_label *label; /* current label, pointer to labels[] */ |
| 369 | |
| 370 | size_t nlabels; /* number of initialized label drivers */ |
| 371 | struct fdisk_label *labels[8]; /* all supported labels, |
| 372 | * FIXME: use any enum rather than hardcoded number */ |
| 373 | |
| 374 | int (*ask_cb)(struct fdisk_context *, struct fdisk_ask *, void *); /* fdisk dialogs callback */ |
| 375 | void *ask_data; /* ask_cb() data */ |
| 376 | |
| 377 | struct fdisk_context *parent; /* for nested PT */ |
| 378 | struct fdisk_script *script; /* what we want to follow */ |
| 379 | }; |
| 380 | |
| 381 | /* partition.c */ |
| 382 | int fdisk_partition_next_partno(struct fdisk_partition *pa, |
| 383 | struct fdisk_context *cxt, |
| 384 | size_t *n); |
| 385 | |
| 386 | /* context.c */ |
| 387 | extern int __fdisk_switch_label(struct fdisk_context *cxt, |
| 388 | struct fdisk_label *lb); |
| 389 | extern int fdisk_missing_geometry(struct fdisk_context *cxt); |
| 390 | |
| 391 | /* alignment.c */ |
| 392 | fdisk_sector_t fdisk_scround(struct fdisk_context *cxt, fdisk_sector_t num); |
| 393 | fdisk_sector_t fdisk_cround(struct fdisk_context *cxt, fdisk_sector_t num); |
| 394 | |
| 395 | extern int fdisk_discover_geometry(struct fdisk_context *cxt); |
| 396 | extern int fdisk_discover_topology(struct fdisk_context *cxt); |
| 397 | |
| 398 | extern int fdisk_apply_user_device_properties(struct fdisk_context *cxt); |
| 399 | extern void fdisk_zeroize_device_properties(struct fdisk_context *cxt); |
| 400 | |
| 401 | /* utils.c */ |
| 402 | extern int fdisk_init_firstsector_buffer(struct fdisk_context *cxt); |
| 403 | extern int fdisk_read_firstsector(struct fdisk_context *cxt); |
| 404 | extern char *fdisk_partname(const char *dev, size_t partno); |
| 405 | |
| 406 | /* label.c */ |
| 407 | extern int fdisk_probe_labels(struct fdisk_context *cxt); |
| 408 | extern void fdisk_deinit_label(struct fdisk_label *lb); |
| 409 | |
| 410 | /* ask.c */ |
| 411 | struct fdisk_ask *fdisk_new_ask(void); |
| 412 | void fdisk_reset_ask(struct fdisk_ask *ask); |
| 413 | int fdisk_ask_set_query(struct fdisk_ask *ask, const char *str); |
| 414 | int fdisk_ask_set_type(struct fdisk_ask *ask, int type); |
| 415 | int fdisk_do_ask(struct fdisk_context *cxt, struct fdisk_ask *ask); |
| 416 | int fdisk_ask_number_set_range(struct fdisk_ask *ask, const char *range); |
| 417 | int fdisk_ask_number_set_default(struct fdisk_ask *ask, uint64_t dflt); |
| 418 | int fdisk_ask_number_set_low(struct fdisk_ask *ask, uint64_t low); |
| 419 | int fdisk_ask_number_set_high(struct fdisk_ask *ask, uint64_t high); |
| 420 | int fdisk_ask_number_set_base(struct fdisk_ask *ask, uint64_t base); |
| 421 | int fdisk_ask_number_set_unit(struct fdisk_ask *ask, uint64_t unit); |
| 422 | int fdisk_ask_number_is_relative(struct fdisk_ask *ask); |
| 423 | int fdisk_ask_menu_set_default(struct fdisk_ask *ask, int dfl); |
| 424 | int fdisk_ask_menu_add_item(struct fdisk_ask *ask, int key, |
| 425 | const char *name, const char *desc); |
| 426 | int fdisk_ask_print_set_errno(struct fdisk_ask *ask, int errnum); |
| 427 | int fdisk_ask_print_set_mesg(struct fdisk_ask *ask, const char *mesg); |
| 428 | int fdisk_info_new_partition( |
| 429 | struct fdisk_context *cxt, |
| 430 | int num, fdisk_sector_t start, fdisk_sector_t stop, |
| 431 | struct fdisk_parttype *t); |
| 432 | |
| 433 | /* dos.c */ |
| 434 | extern struct dos_partition *fdisk_dos_get_partition( |
| 435 | struct fdisk_context *cxt, |
| 436 | size_t i); |
| 437 | |
| 438 | #endif /* _LIBFDISK_PRIVATE_H */ |