1 /* 2 * Copyright (c)2004,2015 The DragonFly Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * Neither the name of the DragonFly Project nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 * OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * diskutil.c 36 * Disk utility functions for installer. 37 * $Id: diskutil.c,v 1.44 2005/02/07 06:41:42 cpressey Exp $ 38 */ 39 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 45 #include "libaura/mem.h" 46 #include "libaura/fspred.h" 47 #include "libaura/popen.h" 48 49 #include "libdfui/dfui.h" 50 #include "libdfui/dump.h" 51 52 #define NEEDS_DISKUTIL_STRUCTURE_DEFINITIONS 53 #include "diskutil.h" 54 #undef NEEDS_DISKUTIL_STRUCTURE_DEFINITIONS 55 56 #include "commands.h" 57 #include "functions.h" 58 #include "sysids.h" 59 #include "uiutil.h" 60 61 static int disk_description_is_better(const char *, const char *); 62 63 /** STORAGE DESCRIPTORS **/ 64 65 struct storage * 66 storage_new(void) 67 { 68 struct storage *s; 69 70 AURA_MALLOC(s, storage); 71 72 s->disk_head = NULL; 73 s->disk_tail = NULL; 74 s->selected_disk = NULL; 75 s->selected_slice = NULL; 76 s->ram = -1; 77 78 return(s); 79 } 80 81 int 82 storage_get_tmpfs_status(const char *mountpoint, struct storage *s) 83 { 84 struct subpartition *sp; 85 sp = NULL; 86 for (sp = slice_subpartition_first(s->selected_slice); 87 sp != NULL; sp = subpartition_next(sp)) { 88 if(strcmp(subpartition_get_mountpoint(sp), mountpoint) == 0) { 89 if(subpartition_is_tmpfsbacked(sp) == 1) { 90 return 1; 91 } else { 92 return 0; 93 } 94 } 95 } 96 return 0; 97 } 98 99 void 100 storage_free(struct storage *s) 101 { 102 disks_free(s); 103 AURA_FREE(s, storage); 104 } 105 106 void 107 storage_set_memsize(struct storage *s, unsigned long memsize) 108 { 109 s->ram = memsize; 110 } 111 112 long 113 storage_get_memsize(const struct storage *s) 114 { 115 return(s->ram); 116 } 117 118 struct disk * 119 storage_disk_first(const struct storage *s) 120 { 121 return(s->disk_head); 122 } 123 124 void 125 storage_set_selected_disk(struct storage *s, struct disk *d) 126 { 127 s->selected_disk = d; 128 } 129 130 struct disk * 131 storage_get_selected_disk(const struct storage *s) 132 { 133 return(s->selected_disk); 134 } 135 136 void 137 storage_set_selected_slice(struct storage *s, struct slice *sl) 138 { 139 s->selected_slice = sl; 140 } 141 142 struct slice * 143 storage_get_selected_slice(const struct storage *s) 144 { 145 return(s->selected_slice); 146 } 147 148 /* 149 * Create a new disk description structure. 150 */ 151 struct disk * 152 disk_new(struct storage *s, const char *dev_name) 153 { 154 struct disk *d; 155 156 AURA_MALLOC(d, disk); 157 158 d->device = aura_strdup(dev_name); 159 d->desc = NULL; 160 d->serno = NULL; 161 d->we_formatted = 0; 162 d->capacity = 0; 163 164 d->cylinders = -1; /* -1 indicates "we don't know" */ 165 d->heads = -1; 166 d->sectors = -1; 167 168 d->slice_head = NULL; 169 d->slice_tail = NULL; 170 171 d->next = NULL; 172 if (s->disk_head == NULL) 173 s->disk_head = d; 174 else 175 s->disk_tail->next = d; 176 177 d->prev = s->disk_tail; 178 s->disk_tail = d; 179 180 return(d); 181 } 182 183 static int 184 disk_description_is_better(const char *existing, const char *new_desc __unused) 185 { 186 if (existing == NULL) 187 return(1); 188 return(0); 189 } 190 191 const char * 192 disk_get_desc(const struct disk *d) 193 { 194 return(d->desc); 195 } 196 197 unsigned long 198 disk_get_capacity(const struct disk *d) 199 { 200 return(d->capacity); 201 } 202 203 204 void 205 disk_set_desc(struct disk *d, const char *desc) 206 { 207 char *c; 208 209 if (!disk_description_is_better(d->desc, desc)) 210 return; 211 if (d->desc != NULL) 212 free(d->desc); 213 d->desc = aura_strdup(desc); 214 215 /* 216 * Get the disk's total capacity. 217 * XXX we should do this with C/H/S ? 218 */ 219 c = d->desc; 220 while (*c != ':' && *c != '\0') 221 c++; 222 if (*c == '\0') 223 d->capacity = 0; 224 else 225 d->capacity = strtoul(c + 1, NULL, 0); 226 } 227 228 /* 229 * Returns the name of the device node used to represent the disk. 230 * Note that the storage used for the returned string is static, 231 * and the string is overwritten each time this function is called. 232 */ 233 const char * 234 disk_get_device_name(const struct disk *d) 235 { 236 static char tmp_dev_name[256]; 237 238 snprintf(tmp_dev_name, 256, "%s", d->device); 239 return(tmp_dev_name); 240 } 241 242 const char * 243 disk_get_serno(const struct disk *d) 244 { 245 return(d->serno); 246 } 247 248 void 249 disk_set_serno(struct disk *d, const char *serno) 250 { 251 d->serno = aura_strdup(serno); 252 } 253 254 int 255 disk_get_number(const struct disk *d) 256 { 257 return(d->number); 258 } 259 260 void 261 disk_set_number(struct disk *d, const int number) 262 { 263 d->number = number; 264 } 265 266 /* 267 * Find the first disk description structure in the given 268 * storage description which matches the given device name 269 * prefix. Note that this means that if a storage 270 * description s contains disks named "ad0" and "ad1", 271 * disk_find(s, "ad0s1c") will return a pointer to the disk 272 * structure for "ad0". 273 */ 274 struct disk * 275 disk_find(const struct storage *s, const char *device) 276 { 277 struct disk *d = s->disk_head; 278 279 while (d != NULL) { 280 if (strncmp(device, d->device, strlen(d->device)) == 0 && 281 strlen(device) == strlen(d->device)) 282 return(d); 283 d = d->next; 284 } 285 286 return(NULL); 287 } 288 289 struct disk * 290 disk_next(const struct disk *d) 291 { 292 return(d->next); 293 } 294 295 struct slice * 296 disk_slice_first(const struct disk *d) 297 { 298 return(d->slice_head); 299 } 300 301 void 302 disk_set_formatted(struct disk *d, int formatted) 303 { 304 d->we_formatted = formatted; 305 } 306 307 int 308 disk_get_formatted(const struct disk *d) 309 { 310 return(d->we_formatted); 311 } 312 313 void 314 disk_set_geometry(struct disk *d, int cyl, int hd, int sec) 315 { 316 d->cylinders = cyl; 317 d->heads = hd; 318 d->sectors = sec; 319 } 320 321 void 322 disk_get_geometry(const struct disk *d, int *cyl, int *hd, int *sec) 323 { 324 *cyl = d->cylinders; 325 *hd = d->heads; 326 *sec = d->sectors; 327 } 328 329 /* 330 * Free the memory allocated to hold the set of disk descriptions. 331 */ 332 void 333 disks_free(struct storage *s) 334 { 335 struct disk *d = s->disk_head, *next; 336 337 while (d != NULL) { 338 next = d->next; 339 slices_free(d->slice_head); 340 free(d->desc); 341 free(d->device); 342 AURA_FREE(d, disk); 343 d = next; 344 } 345 346 s->disk_head = NULL; 347 s->disk_tail = NULL; 348 } 349 350 /* 351 * Create a new slice description and add it to a disk description. 352 */ 353 struct slice * 354 slice_new(struct disk *d, int number, int type, int flags, 355 unsigned long start, unsigned long size) 356 { 357 struct slice *s; 358 const char *sysid_desc = NULL; 359 char unknown[256]; 360 int i; 361 362 dfui_debug("** adding slice %d (start %ld, size %ld, sysid %d) " 363 "to disk %s\n", number, start, size, type, d->device); 364 365 AURA_MALLOC(s, slice); 366 367 s->parent = d; 368 369 s->subpartition_head = NULL; 370 s->subpartition_tail = NULL; 371 s->number = number; 372 373 s->type = type; 374 s->flags = flags; 375 s->start = start; 376 s->size = size; 377 378 for (i = 0; ; i++) { 379 if (part_types[i].type == type) { 380 sysid_desc = part_types[i].name; 381 break; 382 } 383 if (part_types[i].type == 255) 384 break; 385 } 386 if (sysid_desc == NULL) { 387 snprintf(unknown, 256, "??? Unknown, sysid = %d", type); 388 sysid_desc = unknown; 389 } 390 391 asprintf(&s->desc, "%ldM - %ldM: %s", 392 start / 2048, (start + size) / 2048, sysid_desc); 393 s->capacity = size / 2048; 394 395 s->next = NULL; 396 if (d->slice_head == NULL) 397 d->slice_head = s; 398 else 399 d->slice_tail->next = s; 400 401 s->prev = d->slice_tail; 402 d->slice_tail = s; 403 404 return(s); 405 } 406 407 /* 408 * Find a slice description on a given disk description given the 409 * slice number. 410 */ 411 struct slice * 412 slice_find(const struct disk *d, int number) 413 { 414 struct slice *s = d->slice_head; 415 416 while (s != NULL) { 417 if (s->number == number) 418 return(s); 419 s = s->next; 420 } 421 422 return(NULL); 423 } 424 425 struct slice * 426 slice_next(const struct slice *s) 427 { 428 return(s->next); 429 } 430 431 /* 432 * Returns the name of the device node used to represent the slice. 433 * Note that the storage used for the returned string is static, 434 * and the string is overwritten each time this function is called. 435 */ 436 const char * 437 slice_get_device_name(const struct slice *s) 438 { 439 static char tmp_dev_name[256]; 440 441 snprintf(tmp_dev_name, 256, "%ss%d", s->parent->device, s->number); 442 return(tmp_dev_name); 443 } 444 445 int 446 slice_get_number(const struct slice *s) 447 { 448 return(s->number); 449 } 450 451 const char * 452 slice_get_desc(const struct slice *s) 453 { 454 return(s->desc); 455 } 456 457 unsigned long 458 slice_get_capacity(const struct slice *s) 459 { 460 return(s->capacity); 461 } 462 463 unsigned long 464 slice_get_start(const struct slice *s) 465 { 466 return(s->start); 467 } 468 469 unsigned long 470 slice_get_size(const struct slice *s) 471 { 472 return(s->size); 473 } 474 475 int 476 slice_get_type(const struct slice *s) 477 { 478 return(s->type); 479 } 480 481 int 482 slice_get_flags(const struct slice *s) 483 { 484 return(s->flags); 485 } 486 487 struct subpartition * 488 slice_subpartition_first(const struct slice *s) 489 { 490 return(s->subpartition_head); 491 } 492 493 /* 494 * Free all memory for a list of slice descriptions. 495 */ 496 void 497 slices_free(struct slice *head) 498 { 499 struct slice *next; 500 501 while (head != NULL) { 502 next = head->next; 503 subpartitions_free(head); 504 free(head->desc); 505 AURA_FREE(head, slice); 506 head = next; 507 } 508 } 509 510 struct subpartition * 511 subpartition_new_hammer(struct slice *s, const char *mountpoint, 512 long capacity, int encrypted) 513 { 514 struct subpartition *sp; 515 struct subpartition *last = s->subpartition_tail; 516 517 AURA_MALLOC(sp, subpartition); 518 519 sp->parent = s; 520 521 if (last == NULL) { 522 sp->letter = 'a'; 523 } else if (last->letter == 'b') { 524 sp->letter = 'd'; 525 } else { 526 sp->letter = (char)(last->letter + 1); 527 } 528 if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0) 529 sp->letter = 'd'; 530 531 sp->mountpoint = aura_strdup(mountpoint); 532 sp->capacity = capacity; 533 sp->encrypted = encrypted; 534 sp->type = FS_HAMMER; 535 536 /* 537 * We need this here, because a UFS /boot needs valid values 538 */ 539 if (sp->capacity < 1024) 540 sp->fsize = 1024; 541 else 542 sp->fsize = 2048; 543 544 if (sp->capacity < 1024) 545 sp->bsize = 8192; 546 else 547 sp->bsize = 16384; 548 549 sp->is_swap = 0; 550 #if 0 551 sp->pfs = 0; 552 #endif 553 if (strcasecmp(mountpoint, "swap") == 0) 554 sp->is_swap = 1; 555 #if 0 556 if (strcmp(mountpoint, "/") != 0 && strcmp(mountpoint, "/boot") != 0 && 557 strcmp(mountpoint, "swap") != 0) 558 sp->pfs = 1; 559 #endif 560 561 sp->next = NULL; 562 if (s->subpartition_head == NULL) 563 s->subpartition_head = sp; 564 else 565 s->subpartition_tail->next = sp; 566 567 sp->prev = s->subpartition_tail; 568 s->subpartition_tail = sp; 569 570 return(sp); 571 } 572 573 struct subpartition * 574 subpartition_new_hammer2(struct slice *s, const char *mountpoint, 575 long capacity, int encrypted) 576 { 577 struct subpartition *sp; 578 struct subpartition *last = s->subpartition_tail; 579 580 AURA_MALLOC(sp, subpartition); 581 582 sp->parent = s; 583 584 if (last == NULL) { 585 sp->letter = 'a'; 586 } else if (last->letter == 'b') { 587 sp->letter = 'd'; 588 } else { 589 sp->letter = (char)(last->letter + 1); 590 } 591 if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0) 592 sp->letter = 'd'; 593 594 sp->mountpoint = aura_strdup(mountpoint); 595 sp->capacity = capacity; 596 sp->encrypted = encrypted; 597 sp->type = FS_HAMMER2; 598 599 /* 600 * We need this here, because a UFS /boot needs valid values 601 */ 602 if (sp->capacity < 1024) 603 sp->fsize = 1024; 604 else 605 sp->fsize = 2048; 606 607 if (sp->capacity < 1024) 608 sp->bsize = 8192; 609 else 610 sp->bsize = 16384; 611 612 sp->is_swap = 0; 613 #if 0 614 sp->pfs = 0; 615 #endif 616 if (strcasecmp(mountpoint, "swap") == 0) 617 sp->is_swap = 1; 618 #if 0 619 if (strcmp(mountpoint, "/") != 0 && strcmp(mountpoint, "/boot") != 0 && 620 strcmp(mountpoint, "swap") != 0) 621 sp->pfs = 1; 622 #endif 623 624 sp->next = NULL; 625 if (s->subpartition_head == NULL) 626 s->subpartition_head = sp; 627 else 628 s->subpartition_tail->next = sp; 629 630 sp->prev = s->subpartition_tail; 631 s->subpartition_tail = sp; 632 633 return(sp); 634 } 635 636 /* 637 * NOTE: arguments to this function are not checked for sanity. 638 * 639 * fsize and/or bsize may both be -1, indicating 640 * "choose a reasonable default." 641 */ 642 struct subpartition * 643 subpartition_new_ufs(struct slice *s, const char *mountpoint, long capacity, 644 int encrypted, int softupdates, long fsize, long bsize, int tmpfsbacked) 645 { 646 struct subpartition *sp; 647 struct subpartition *last = s->subpartition_tail; 648 649 AURA_MALLOC(sp, subpartition); 650 651 if (tmpfsbacked) { 652 sp->letter = '@'; 653 } else { 654 while (last && last->letter == '@') 655 last = last->prev; 656 if (last == NULL) { 657 sp->letter = 'a'; 658 } else if (last->letter == 'b') { 659 sp->letter = 'd'; 660 } else { 661 sp->letter = (char)(last->letter + 1); 662 } 663 if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0) 664 sp->letter = 'd'; 665 } 666 667 sp->parent = s; 668 669 sp->mountpoint = aura_strdup(mountpoint); 670 sp->capacity = capacity; 671 sp->encrypted = encrypted; 672 sp->type = FS_UFS; 673 674 if (fsize == -1) { 675 if (sp->capacity < 1024) 676 sp->fsize = 1024; 677 else 678 sp->fsize = 2048; 679 } else { 680 sp->fsize = fsize; 681 } 682 683 if (bsize == -1) { 684 if (sp->capacity < 1024) 685 sp->bsize = 8192; 686 else 687 sp->bsize = 16384; 688 } else { 689 sp->bsize = bsize; 690 } 691 692 if (softupdates == -1) { 693 if (strcmp(mountpoint, "/") == 0) 694 sp->softupdates = 0; 695 else 696 sp->softupdates = 1; 697 } else { 698 sp->softupdates = softupdates; 699 } 700 701 sp->tmpfsbacked = tmpfsbacked; 702 703 sp->is_swap = 0; 704 if (strcasecmp(mountpoint, "swap") == 0) 705 sp->is_swap = 1; 706 707 /* 708 * install 709 */ 710 sp->next = NULL; 711 if (s->subpartition_head == NULL) 712 s->subpartition_head = sp; 713 else 714 s->subpartition_tail->next = sp; 715 716 sp->prev = s->subpartition_tail; 717 s->subpartition_tail = sp; 718 719 #if 0 720 721 for (sptmp = s->subpartition_head; sptmp != NULL; 722 sptmp = sptmp->next) { 723 if (sptmp->tmpfsbacked) 724 sptmp->letter = '@'; 725 else if (strcmp(sptmp->mountpoint, "/") == 0 || 726 strcmp(sptmp->mountpoint, "/dummy") == 0) 727 sptmp->letter = 'a'; 728 else if (strcasecmp(sptmp->mountpoint, "swap") == 0) 729 sptmp->letter = 'b'; 730 else 731 sptmp->letter = letter++; 732 } 733 #endif 734 735 return(sp); 736 } 737 738 /* 739 * Find the subpartition description in the given storage 740 * description whose mountpoint matches the given string exactly. 741 */ 742 struct subpartition * 743 subpartition_find(const struct slice *s, const char *fmt, ...) 744 { 745 struct subpartition *sp = s->subpartition_head; 746 char *mountpoint; 747 va_list args; 748 749 va_start(args, fmt); 750 vasprintf(&mountpoint, fmt, args); 751 va_end(args); 752 753 while (sp != NULL) { 754 if (strcmp(mountpoint, sp->mountpoint) == 0) { 755 free(mountpoint); 756 return(sp); 757 } 758 sp = sp->next; 759 } 760 761 free(mountpoint); 762 return(NULL); 763 } 764 765 /* 766 * Find the subpartition description in the given storage 767 * description where the given filename would presumably 768 * reside. This is the subpartition whose mountpoint is 769 * the longest match for the given filename. 770 */ 771 struct subpartition * 772 subpartition_of(const struct slice *s, const char *fmt, ...) 773 { 774 struct subpartition *sp = s->subpartition_head; 775 struct subpartition *csp = NULL; 776 size_t len = 0; 777 char *filename; 778 va_list args; 779 780 va_start(args, fmt); 781 vasprintf(&filename, fmt, args); 782 va_end(args); 783 784 while (sp != NULL) { 785 if (strlen(sp->mountpoint) > len && 786 strlen(sp->mountpoint) <= strlen(filename) && 787 strncmp(filename, sp->mountpoint, strlen(sp->mountpoint)) == 0) { 788 csp = sp; 789 len = strlen(csp->mountpoint); 790 } 791 sp = sp->next; 792 } 793 794 free(filename); 795 return(csp); 796 } 797 798 struct subpartition * 799 subpartition_find_capacity(const struct slice *s, long capacity) 800 { 801 struct subpartition *sp = s->subpartition_head; 802 803 while (sp != NULL) { 804 if (sp->capacity == capacity) 805 return(sp); 806 sp = sp->next; 807 } 808 809 return(NULL); 810 } 811 812 struct subpartition * 813 subpartition_next(const struct subpartition *sp) 814 { 815 return(sp->next); 816 } 817 818 int 819 subpartition_get_pfs(const struct subpartition *sp) 820 { 821 return(sp->pfs); 822 } 823 824 /* 825 * Returns the name of the device node used to represent 826 * the subpartition, either by serial number or traditional style. 827 * Note that the storage used for the returned string is static, 828 * and the string is overwritten each time this function is called. 829 */ 830 const char * 831 subpartition_get_device_name(const struct subpartition *sp) 832 { 833 static char tmp_dev_name[256]; 834 835 if (sp->parent->parent->serno != NULL) 836 snprintf(tmp_dev_name, 256, "serno/%s.s%d%c", 837 sp->parent->parent->serno, sp->parent->number, sp->letter); 838 else 839 snprintf(tmp_dev_name, 256, "%ss%d%c", 840 sp->parent->parent->device, sp->parent->number, sp->letter); 841 return(tmp_dev_name); 842 } 843 844 /* 845 * /dev/mapper/ 846 * 847 * (result is persistant until next call) 848 */ 849 const char * 850 subpartition_get_mapper_name(const struct subpartition *sp, int withdev) 851 { 852 const char *src; 853 static char *save; 854 855 src = strrchr(sp->mountpoint, '/'); 856 if (src == NULL || src[1] == 0) 857 src = "root"; 858 else 859 ++src; 860 861 if (save) 862 free(save); 863 switch(withdev) { 864 case -1: 865 asprintf(&save, "%s", src); 866 break; 867 case 0: 868 asprintf(&save, "mapper/%s", src); 869 break; 870 case 1: 871 default: 872 asprintf(&save, "/dev/mapper/%s", src); 873 break; 874 } 875 return save; 876 } 877 878 const char * 879 subpartition_get_mountpoint(const struct subpartition *sp) 880 { 881 return(sp->mountpoint); 882 } 883 884 char 885 subpartition_get_letter(const struct subpartition *sp) 886 { 887 return(sp->letter); 888 } 889 890 unsigned long 891 subpartition_get_fsize(const struct subpartition *sp) 892 { 893 return(sp->fsize); 894 } 895 896 unsigned long 897 subpartition_get_bsize(const struct subpartition *sp) 898 { 899 return(sp->bsize); 900 } 901 902 long 903 subpartition_get_capacity(const struct subpartition *sp) 904 { 905 return(sp->capacity); 906 } 907 908 void 909 subpartition_clr_encrypted(struct subpartition *sp) 910 { 911 sp->encrypted = 0; 912 } 913 914 int 915 subpartition_is_encrypted(const struct subpartition *sp) 916 { 917 return(sp->encrypted); 918 } 919 920 int 921 subpartition_is_swap(const struct subpartition *sp) 922 { 923 return(sp->is_swap); 924 } 925 926 int 927 subpartition_is_softupdated(const struct subpartition *sp) 928 { 929 return(sp->softupdates); 930 } 931 int 932 subpartition_is_tmpfsbacked(const struct subpartition *sp) 933 { 934 return(sp->tmpfsbacked); 935 } 936 937 int 938 subpartition_count(const struct slice *s) 939 { 940 struct subpartition *sp = s->subpartition_head; 941 int count = 0; 942 943 while (sp != NULL) { 944 count++; 945 sp = sp->next; 946 } 947 948 return(count); 949 } 950 951 void 952 subpartitions_free(struct slice *s) 953 { 954 struct subpartition *sp = s->subpartition_head, *next; 955 956 while (sp != NULL) { 957 next = sp->next; 958 free(sp->mountpoint); 959 AURA_FREE(sp, subpartition); 960 sp = next; 961 } 962 963 s->subpartition_head = NULL; 964 s->subpartition_tail = NULL; 965 } 966 967 long 968 measure_activated_swap(const struct i_fn_args *a) 969 { 970 FILE *p; 971 char line[256]; 972 char *word; 973 long swap = 0; 974 975 if ((p = aura_popen("%s%s -k", "r", a->os_root, cmd_name(a, "SWAPINFO"))) == NULL) 976 return(0); 977 while (fgets(line, 255, p) != NULL) { 978 if ((word = strtok(line, " \t")) == NULL) 979 continue; 980 if (strcmp(word, "Device") == 0) 981 continue; 982 if ((word = strtok(NULL, " \t")) == NULL) 983 continue; 984 swap += atol(word); 985 } 986 aura_pclose(p); 987 988 return(swap / 1024); 989 } 990 991 long 992 measure_activated_swap_from_slice(const struct i_fn_args *a, 993 const struct disk *d, const struct slice *s) 994 { 995 FILE *p; 996 char *dev, *word; 997 char line[256]; 998 long swap = 0; 999 1000 if ((p = aura_popen("%s%s -k", "r", a->os_root, cmd_name(a, "SWAPINFO"))) == NULL) 1001 return(0); 1002 1003 asprintf(&dev, "/dev/%ss%d", d->device, s->number); 1004 1005 while (fgets(line, 255, p) != NULL) { 1006 if ((word = strtok(line, " \t")) == NULL) 1007 continue; 1008 if (strcmp(word, "Device") == 0) 1009 continue; 1010 if (strstr(word, dev) != word) 1011 continue; 1012 if ((word = strtok(NULL, " \t")) == NULL) 1013 continue; 1014 swap += atol(word); 1015 } 1016 aura_pclose(p); 1017 free(dev); 1018 1019 return(swap / 1024); 1020 } 1021 1022 long 1023 measure_activated_swap_from_disk(const struct i_fn_args *a, 1024 const struct disk *d) 1025 { 1026 struct slice *s; 1027 long swap = 0; 1028 1029 for (s = d->slice_head; s != NULL; s = s->next) 1030 swap += measure_activated_swap_from_slice(a, d, s); 1031 1032 return(swap); 1033 } 1034 1035 void * 1036 swapoff_all(const struct i_fn_args *a) 1037 { 1038 FILE *p; 1039 1040 if ((p = aura_popen("%s%s off; %s%s | %s%s \"^/dev\" | %s%s '{print $1;}' | %s%s %s%s", "r", 1041 a->os_root, cmd_name(a, "DUMPON"), 1042 a->os_root, cmd_name(a, "SWAPINFO"), 1043 a->os_root, cmd_name(a, "GREP"), 1044 a->os_root, cmd_name(a, "AWK"), 1045 a->os_root, cmd_name(a, "XARGS"), 1046 a->os_root, cmd_name(a, "SWAPOFF"))) != NULL) 1047 aura_pclose(p); 1048 1049 return(p); 1050 } 1051 1052 void * 1053 remove_all_mappings(const struct i_fn_args *a) 1054 { 1055 FILE *p; 1056 1057 if ((p = aura_popen("%s%s -1 /dev/mapper | %s%s -vw control | %s%s -n 1 %s%s luksClose", "r", 1058 a->os_root, cmd_name(a, "LS"), 1059 a->os_root, cmd_name(a, "GREP"), 1060 a->os_root, cmd_name(a, "XARGS"), 1061 a->os_root, cmd_name(a, "CRYPTSETUP"))) != NULL) 1062 aura_pclose(p); 1063 1064 return(p); 1065 } 1066