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 #include <uuid.h> 20 21 #include "c.h" 22 #include "libfdisk.h" 23 24 #include "list.h" 25 #include "debug.h" 26 #include <stdio.h> 27 #include <stdarg.h> 28 29 /* 30 * Debug 31 */ 32 #define LIBFDISK_DEBUG_HELP (1 << 0) 33 #define LIBFDISK_DEBUG_INIT (1 << 1) 34 #define LIBFDISK_DEBUG_CXT (1 << 2) 35 #define LIBFDISK_DEBUG_LABEL (1 << 3) 36 #define LIBFDISK_DEBUG_ASK (1 << 4) 37 #define LIBFDISK_DEBUG_PART (1 << 6) 38 #define LIBFDISK_DEBUG_PARTTYPE (1 << 7) 39 #define LIBFDISK_DEBUG_TAB (1 << 8) 40 #define LIBFDISK_DEBUG_SCRIPT (1 << 9) 41 #define LIBFDISK_DEBUG_WIPE (1 << 10) 42 #define LIBFDISK_DEBUG_ITEM (1 << 11) 43 #define LIBFDISK_DEBUG_GPT (1 << 12) 44 #define LIBFDISK_DEBUG_ALL 0xFFFF 45 46 UL_DEBUG_DECLARE_MASK(libfdisk); 47 #define DBG(m, x) __UL_DBG(libfdisk, LIBFDISK_DEBUG_, m, x) 48 #define ON_DBG(m, x) __UL_DBG_CALL(libfdisk, LIBFDISK_DEBUG_, m, x) 49 #define DBG_FLUSH __UL_DBG_FLUSH(libfdisk, LIBFDISK_DEBUG_) 50 51 #define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(libfdisk) 52 #include "debugobj.h" 53 54 /* 55 * NLS -- the library has to be independent on main program, so define 56 * UL_TEXTDOMAIN_EXPLICIT before you include nls.h. 57 * 58 * Now we use util-linux.po (=PACKAGE), rather than maintain the texts 59 * in the separate libfdisk.po file. 60 */ 61 #define LIBFDISK_TEXTDOMAIN PACKAGE 62 #define UL_TEXTDOMAIN_EXPLICIT LIBFDISK_TEXTDOMAIN 63 #include "nls.h" 64 65 66 #ifdef TEST_PROGRAM 67 struct fdisk_test { 68 const char *name; 69 int (*body)(struct fdisk_test *ts, int argc, char *argv[]); 70 const char *usage; 71 }; 72 73 /* test.c */ 74 extern int fdisk_run_test(struct fdisk_test *tests, int argc, char *argv[]); 75 #endif 76 77 #define FDISK_GPT_NPARTITIONS_DEFAULT 128 78 79 /* 80 * Generic iterator 81 */ 82 struct fdisk_iter { 83 struct list_head *p; /* current position */ 84 struct list_head *head; /* start position */ 85 int direction; /* FDISK_ITER_{FOR,BACK}WARD */ 86 }; 87 88 #define IS_ITER_FORWARD(_i) ((_i)->direction == FDISK_ITER_FORWARD) 89 #define IS_ITER_BACKWARD(_i) ((_i)->direction == FDISK_ITER_BACKWARD) 90 91 #define FDISK_ITER_INIT(itr, list) \ 92 do { \ 93 (itr)->p = IS_ITER_FORWARD(itr) ? \ 94 (list)->next : (list)->prev; \ 95 (itr)->head = (list); \ 96 } while(0) 97 98 #define FDISK_ITER_ITERATE(itr, res, restype, member) \ 99 do { \ 100 res = list_entry((itr)->p, restype, member); \ 101 (itr)->p = IS_ITER_FORWARD(itr) ? \ 102 (itr)->p->next : (itr)->p->prev; \ 103 } while(0) 104 105 /* 106 * Partition types 107 */ 108 struct fdisk_parttype { 109 unsigned int code; /* type as number or zero */ 110 char *name; /* description */ 111 char *typestr; /* type as string or NULL */ 112 113 unsigned int flags; /* FDISK_PARTTYPE_* flags */ 114 int refcount; /* reference counter for allocated types */ 115 }; 116 117 enum { 118 FDISK_PARTTYPE_UNKNOWN = (1 << 1), 119 FDISK_PARTTYPE_INVISIBLE = (1 << 2), 120 FDISK_PARTTYPE_ALLOCATED = (1 << 3) 121 }; 122 123 #define fdisk_parttype_is_invisible(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_INVISIBLE)) 124 #define fdisk_parttype_is_allocated(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED)) 125 126 /* 127 * Shortcut (used for partition types) 128 */ 129 struct fdisk_shortcut { 130 const char *shortcut; /* shortcut, usually one letter (e.h. "H") */ 131 const char *alias; /* human readable alias (e.g. "home") */ 132 const char *data; /* for example partition type */ 133 134 unsigned int deprecated : 1; 135 }; 136 137 struct fdisk_partition { 138 int refcount; /* reference counter */ 139 140 size_t partno; /* partition number */ 141 size_t parent_partno; /* for logical partitions */ 142 143 fdisk_sector_t start; /* first sectors */ 144 fdisk_sector_t size; /* size in sectors */ 145 146 int movestart; /* FDISK_MOVE_* (scripts only) */ 147 int resize; /* FDISK_RESIZE_* (scripts only) */ 148 149 char *name; /* partition name */ 150 char *uuid; /* partition UUID */ 151 char *attrs; /* partition flags/attributes converted to string */ 152 struct fdisk_parttype *type; /* partition type */ 153 154 char *fstype; /* filesystem type */ 155 char *fsuuid; /* filesystem uuid */ 156 char *fslabel; /* filesystem label */ 157 158 struct list_head parts; /* list of partitions */ 159 160 /* extra fields for partition_to_string() */ 161 char start_post; /* start postfix (e.g. '+') */ 162 char end_post; /* end postfix */ 163 char size_post; /* size postfix */ 164 165 uint64_t fsize; /* bsd junk */ 166 uint64_t bsize; 167 uint64_t cpg; 168 169 char *start_chs; /* start C/H/S in string */ 170 char *end_chs; /* end C/H/S in string */ 171 172 unsigned int boot; /* MBR: bootable */ 173 174 unsigned int container : 1, /* container partition (e.g. extended partition) */ 175 end_follow_default : 1, /* use default end */ 176 freespace : 1, /* this is free space */ 177 partno_follow_default : 1, /* use default partno */ 178 size_explicit : 1, /* don't align the size */ 179 start_follow_default : 1, /* use default start */ 180 fs_probed : 1, /* already probed by blkid */ 181 used : 1, /* partition already used */ 182 wholedisk : 1; /* special system partition */ 183 }; 184 185 enum { 186 FDISK_MOVE_NONE = 0, 187 FDISK_MOVE_DOWN = -1, 188 FDISK_MOVE_UP = 1 189 }; 190 191 enum { 192 FDISK_RESIZE_NONE = 0, 193 FDISK_RESIZE_REDUCE = -1, 194 FDISK_RESIZE_ENLARGE = 1 195 }; 196 197 #define FDISK_INIT_UNDEF(_x) ((_x) = (__typeof__(_x)) -1) 198 #define FDISK_IS_UNDEF(_x) ((_x) == (__typeof__(_x)) -1) 199 200 struct fdisk_table { 201 struct list_head parts; /* partitions */ 202 int refcount; 203 size_t nents; /* number of partitions */ 204 }; 205 206 /* 207 * Legacy CHS based geometry 208 */ 209 struct fdisk_geometry { 210 unsigned int heads; 211 fdisk_sector_t sectors; 212 fdisk_sector_t cylinders; 213 }; 214 215 /* 216 * Label specific operations 217 */ 218 struct fdisk_label_operations { 219 /* probe disk label */ 220 int (*probe)(struct fdisk_context *cxt); 221 /* write in-memory changes to disk */ 222 int (*write)(struct fdisk_context *cxt); 223 /* verify the partition table */ 224 int (*verify)(struct fdisk_context *cxt); 225 /* create new disk label */ 226 int (*create)(struct fdisk_context *cxt); 227 /* returns offset and size of the 'n' part of the PT */ 228 int (*locate)(struct fdisk_context *cxt, int n, const char **name, 229 uint64_t *offset, size_t *size); 230 /* reorder partitions */ 231 int (*reorder)(struct fdisk_context *cxt); 232 /* get details from label */ 233 int (*get_item)(struct fdisk_context *cxt, struct fdisk_labelitem *item); 234 /* set disk label ID */ 235 int (*set_id)(struct fdisk_context *cxt, const char *str); 236 237 238 /* new partition */ 239 int (*add_part)(struct fdisk_context *cxt, struct fdisk_partition *pa, 240 size_t *partno); 241 /* delete partition */ 242 int (*del_part)(struct fdisk_context *cxt, size_t partnum); 243 244 /* fill in partition struct */ 245 int (*get_part)(struct fdisk_context *cxt, size_t n, 246 struct fdisk_partition *pa); 247 /* modify partition */ 248 int (*set_part)(struct fdisk_context *cxt, size_t n, 249 struct fdisk_partition *pa); 250 251 /* return state of the partition */ 252 int (*part_is_used)(struct fdisk_context *cxt, size_t partnum); 253 254 int (*part_toggle_flag)(struct fdisk_context *cxt, size_t i, unsigned long flag); 255 256 /* refresh alignment setting */ 257 int (*reset_alignment)(struct fdisk_context *cxt); 258 259 /* free in-memory label stuff */ 260 void (*free)(struct fdisk_label *lb); 261 262 /* deinit in-memory label stuff */ 263 void (*deinit)(struct fdisk_label *lb); 264 }; 265 266 /* 267 * The fields describes how to display libfdisk_partition 268 */ 269 struct fdisk_field { 270 int id; /* FDISK_FIELD_* */ 271 const char *name; /* field name */ 272 double width; /* field width (compatible with libsmartcols whint) */ 273 int flags; /* FDISK_FIELDFL_* */ 274 }; 275 276 /* note that the defaults is to display a column always */ 277 enum { 278 FDISK_FIELDFL_DETAIL = (1 << 1), /* only display if fdisk_is_details() */ 279 FDISK_FIELDFL_EYECANDY = (1 << 2), /* don't display if fdisk_is_details() */ 280 FDISK_FIELDFL_NUMBER = (1 << 3), /* column display numbers */ 281 }; 282 283 /* 284 * Generic label 285 */ 286 struct fdisk_label { 287 const char *name; /* label name */ 288 enum fdisk_labeltype id; /* FDISK_DISKLABEL_* */ 289 struct fdisk_parttype *parttypes; /* supported partitions types */ 290 size_t nparttypes; /* number of items in parttypes[] */ 291 292 const struct fdisk_shortcut *parttype_cuts; /* partition type shortcuts */ 293 size_t nparttype_cuts; /* number of items in parttype_cuts */ 294 295 size_t nparts_max; /* maximal number of partitions */ 296 size_t nparts_cur; /* number of currently used partitions */ 297 298 int flags; /* FDISK_LABEL_FL_* flags */ 299 300 struct fdisk_geometry geom_min; /* minimal geometry */ 301 struct fdisk_geometry geom_max; /* maximal geometry */ 302 303 unsigned int changed:1, /* label has been modified */ 304 disabled:1; /* this driver is disabled at all */ 305 306 const struct fdisk_field *fields; /* all possible fields */ 307 size_t nfields; 308 309 const struct fdisk_label_operations *op; 310 }; 311 312 313 /* label driver flags */ 314 enum { 315 FDISK_LABEL_FL_REQUIRE_GEOMETRY = (1 << 2), 316 FDISK_LABEL_FL_INCHARS_PARTNO = (1 << 3) 317 }; 318 319 /* label allocators */ 320 extern struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt); 321 extern struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt); 322 extern struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt); 323 extern struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt); 324 extern struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt); 325 326 327 struct ask_menuitem { 328 char key; 329 const char *name; 330 const char *desc; 331 332 struct ask_menuitem *next; 333 }; 334 335 /* fdisk dialog -- note that nothing from this stuff will be directly exported, 336 * we will have get/set() function for everything. 337 */ 338 struct fdisk_ask { 339 int type; /* FDISK_ASKTYPE_* */ 340 char *query; 341 342 int refcount; 343 344 union { 345 /* FDISK_ASKTYPE_{NUMBER,OFFSET} */ 346 struct ask_number { 347 uint64_t hig; /* high limit */ 348 uint64_t low; /* low limit */ 349 uint64_t dfl; /* default */ 350 uint64_t result; 351 uint64_t base; /* for relative results */ 352 uint64_t unit; /* unit for offsets */ 353 const char *range; /* by library generated list */ 354 unsigned int relative :1, 355 inchars :1, 356 wrap_negative :1; 357 } num; 358 /* FDISK_ASKTYPE_{WARN,WARNX,..} */ 359 struct ask_print { 360 const char *mesg; 361 int errnum; /* errno */ 362 } print; 363 /* FDISK_ASKTYPE_YESNO */ 364 struct ask_yesno { 365 int result; /* TRUE or FALSE */ 366 } yesno; 367 /* FDISK_ASKTYPE_STRING */ 368 struct ask_string { 369 char *result; /* allocated */ 370 } str; 371 /* FDISK_ASKTYPE_MENU */ 372 struct ask_menu { 373 int dfl; /* default menu item */ 374 int result; 375 struct ask_menuitem *first; 376 } menu; 377 } data; 378 }; 379 380 struct fdisk_context { 381 int dev_fd; /* device descriptor */ 382 char *dev_path; /* device path */ 383 char *dev_model; /* on linux /sys/block/<name>/device/model or NULL */ 384 struct stat dev_st; /* stat(2) result */ 385 386 int refcount; 387 388 unsigned char *firstsector; /* buffer with master boot record */ 389 unsigned long firstsector_bufsz; 390 391 392 /* topology */ 393 unsigned long io_size; /* I/O size used by fdisk */ 394 unsigned long optimal_io_size; /* optional I/O returned by device */ 395 unsigned long min_io_size; /* minimal I/O size */ 396 unsigned long phy_sector_size; /* physical size */ 397 unsigned long sector_size; /* logical size */ 398 unsigned long alignment_offset; 399 400 unsigned int readonly : 1, /* don't write to the device */ 401 display_in_cyl_units : 1, /* for obscure labels */ 402 display_details : 1, /* expert display mode */ 403 protect_bootbits : 1, /* don't zeroize first sector */ 404 pt_collision : 1, /* another PT detected by libblkid */ 405 no_disalogs : 1, /* disable dialog-driven partititoning */ 406 dev_model_probed : 1, /* tried to read from sys */ 407 private_fd : 1, /* open by libfdisk */ 408 listonly : 1; /* list partition, nothing else */ 409 410 char *collision; /* name of already existing FS/PT */ 411 struct list_head wipes; /* list of areas to wipe before write */ 412 413 int sizeunit; /* SIZE fields, FDISK_SIZEUNIT_* */ 414 415 /* alignment */ 416 unsigned long grain; /* alignment unit */ 417 fdisk_sector_t first_lba; /* recommended begin of the first partition */ 418 fdisk_sector_t last_lba; /* recommended end of last partition */ 419 420 /* geometry */ 421 fdisk_sector_t total_sectors; /* in logical sectors */ 422 struct fdisk_geometry geom; 423 424 /* user setting to overwrite device default */ 425 struct fdisk_geometry user_geom; 426 unsigned long user_pyh_sector; 427 unsigned long user_log_sector; 428 unsigned long user_grain; 429 430 struct fdisk_label *label; /* current label, pointer to labels[] */ 431 432 size_t nlabels; /* number of initialized label drivers */ 433 struct fdisk_label *labels[8]; /* all supported labels, 434 * FIXME: use any enum rather than hardcoded number */ 435 436 int (*ask_cb)(struct fdisk_context *, struct fdisk_ask *, void *); /* fdisk dialogs callback */ 437 void *ask_data; /* ask_cb() data */ 438 439 struct fdisk_context *parent; /* for nested PT */ 440 struct fdisk_script *script; /* what we want to follow */ 441 }; 442 443 /* table */ 444 enum { 445 FDISK_DIFF_UNCHANGED = 0, 446 FDISK_DIFF_REMOVED, 447 FDISK_DIFF_ADDED, 448 FDISK_DIFF_MOVED, 449 FDISK_DIFF_RESIZED 450 }; 451 extern int fdisk_diff_tables(struct fdisk_table *a, struct fdisk_table *b, 452 struct fdisk_iter *itr, 453 struct fdisk_partition **res, int *change); 454 extern void fdisk_debug_print_table(struct fdisk_table *tb); 455 456 457 /* context.c */ 458 extern int __fdisk_switch_label(struct fdisk_context *cxt, 459 struct fdisk_label *lb); 460 extern int fdisk_missing_geometry(struct fdisk_context *cxt); 461 462 /* alignment.c */ 463 fdisk_sector_t fdisk_scround(struct fdisk_context *cxt, fdisk_sector_t num); 464 fdisk_sector_t fdisk_cround(struct fdisk_context *cxt, fdisk_sector_t num); 465 466 extern int fdisk_discover_geometry(struct fdisk_context *cxt); 467 extern int fdisk_discover_topology(struct fdisk_context *cxt); 468 469 extern int fdisk_has_user_device_geometry(struct fdisk_context *cxt); 470 extern int fdisk_apply_user_device_properties(struct fdisk_context *cxt); 471 extern int fdisk_apply_label_device_properties(struct fdisk_context *cxt); 472 extern void fdisk_zeroize_device_properties(struct fdisk_context *cxt); 473 474 /* utils.c */ 475 extern int fdisk_init_firstsector_buffer(struct fdisk_context *cxt, 476 unsigned int protect_off, unsigned int protect_size); 477 extern int fdisk_read_firstsector(struct fdisk_context *cxt); 478 479 /* label.c */ 480 extern int fdisk_probe_labels(struct fdisk_context *cxt); 481 extern void fdisk_deinit_label(struct fdisk_label *lb); 482 483 struct fdisk_labelitem { 484 int refcount; /* reference counter */ 485 int id; /* <label>_ITEM_* */ 486 char type; /* s = string, j = uint64 */ 487 const char *name; /* human readable name */ 488 489 union { 490 char *str; 491 uint64_t num64; 492 } data; 493 }; 494 495 /* Use only internally for non-allocated items, never use 496 * refcouting for such items! 497 */ 498 #define FDISK_LABELITEM_INIT { .type = 0, .refcount = 0 } 499 500 /* ask.c */ 501 struct fdisk_ask *fdisk_new_ask(void); 502 void fdisk_reset_ask(struct fdisk_ask *ask); 503 int fdisk_ask_set_query(struct fdisk_ask *ask, const char *str); 504 int fdisk_ask_set_type(struct fdisk_ask *ask, int type); 505 int fdisk_do_ask(struct fdisk_context *cxt, struct fdisk_ask *ask); 506 int fdisk_ask_number_set_range(struct fdisk_ask *ask, const char *range); 507 int fdisk_ask_number_set_default(struct fdisk_ask *ask, uint64_t dflt); 508 int fdisk_ask_number_set_low(struct fdisk_ask *ask, uint64_t low); 509 int fdisk_ask_number_set_high(struct fdisk_ask *ask, uint64_t high); 510 int fdisk_ask_number_set_base(struct fdisk_ask *ask, uint64_t base); 511 int fdisk_ask_number_set_unit(struct fdisk_ask *ask, uint64_t unit); 512 int fdisk_ask_number_is_relative(struct fdisk_ask *ask); 513 int fdisk_ask_number_set_wrap_negative(struct fdisk_ask *ask, int wrap_negative); 514 int fdisk_ask_menu_set_default(struct fdisk_ask *ask, int dfl); 515 int fdisk_ask_menu_add_item(struct fdisk_ask *ask, int key, 516 const char *name, const char *desc); 517 int fdisk_ask_print_set_errno(struct fdisk_ask *ask, int errnum); 518 int fdisk_ask_print_set_mesg(struct fdisk_ask *ask, const char *mesg); 519 int fdisk_info_new_partition( 520 struct fdisk_context *cxt, 521 int num, fdisk_sector_t start, fdisk_sector_t stop, 522 struct fdisk_parttype *t); 523 524 /* dos.c */ 525 extern struct dos_partition *fdisk_dos_get_partition( 526 struct fdisk_context *cxt, 527 size_t i); 528 529 /* wipe.c */ 530 void fdisk_free_wipe_areas(struct fdisk_context *cxt); 531 int fdisk_set_wipe_area(struct fdisk_context *cxt, uint64_t start, uint64_t size, int enable); 532 int fdisk_do_wipe(struct fdisk_context *cxt); 533 int fdisk_has_wipe_area(struct fdisk_context *cxt, uint64_t start, uint64_t size); 534 int fdisk_check_collisions(struct fdisk_context *cxt); 535 536 /* parttype.c */ 537 const char *fdisk_label_translate_type_shortcut(const struct fdisk_label *lb, char *cut); 538 539 #endif /* _LIBFDISK_PRIVATE_H */ 540