installer - Add hammer2 support to the installer
[dragonfly.git] / usr.sbin / installer / libinstaller / diskutil.c
blob5bf11018e3ca20f0eba0bf961937903f7d5651c2
1 /*
2 * Copyright (c)2004,2015 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
35 * diskutil.c
36 * Disk utility functions for installer.
37 * $Id: diskutil.c,v 1.44 2005/02/07 06:41:42 cpressey Exp $
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
45 #include "libaura/mem.h"
46 #include "libaura/fspred.h"
47 #include "libaura/popen.h"
49 #include "libdfui/dfui.h"
50 #include "libdfui/dump.h"
52 #define NEEDS_DISKUTIL_STRUCTURE_DEFINITIONS
53 #include "diskutil.h"
54 #undef NEEDS_DISKUTIL_STRUCTURE_DEFINITIONS
56 #include "commands.h"
57 #include "functions.h"
58 #include "sysids.h"
59 #include "uiutil.h"
61 static int disk_description_is_better(const char *, const char *);
63 /** STORAGE DESCRIPTORS **/
65 struct storage *
66 storage_new(void)
68 struct storage *s;
70 AURA_MALLOC(s, storage);
72 s->disk_head = NULL;
73 s->disk_tail = NULL;
74 s->selected_disk = NULL;
75 s->selected_slice = NULL;
76 s->ram = -1;
78 return(s);
81 int
82 storage_get_tmpfs_status(const char *mountpoint, struct storage *s)
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;
96 return 0;
99 void
100 storage_free(struct storage *s)
102 disks_free(s);
103 AURA_FREE(s, storage);
106 void
107 storage_set_memsize(struct storage *s, unsigned long memsize)
109 s->ram = memsize;
112 long
113 storage_get_memsize(const struct storage *s)
115 return(s->ram);
118 struct disk *
119 storage_disk_first(const struct storage *s)
121 return(s->disk_head);
124 void
125 storage_set_selected_disk(struct storage *s, struct disk *d)
127 s->selected_disk = d;
130 struct disk *
131 storage_get_selected_disk(const struct storage *s)
133 return(s->selected_disk);
136 void
137 storage_set_selected_slice(struct storage *s, struct slice *sl)
139 s->selected_slice = sl;
142 struct slice *
143 storage_get_selected_slice(const struct storage *s)
145 return(s->selected_slice);
149 * Create a new disk description structure.
151 struct disk *
152 disk_new(struct storage *s, const char *dev_name)
154 struct disk *d;
156 AURA_MALLOC(d, disk);
158 d->device = aura_strdup(dev_name);
159 d->desc = NULL;
160 d->serno = NULL;
161 d->we_formatted = 0;
162 d->capacity = 0;
164 d->cylinders = -1; /* -1 indicates "we don't know" */
165 d->heads = -1;
166 d->sectors = -1;
168 d->slice_head = NULL;
169 d->slice_tail = NULL;
171 d->next = NULL;
172 if (s->disk_head == NULL)
173 s->disk_head = d;
174 else
175 s->disk_tail->next = d;
177 d->prev = s->disk_tail;
178 s->disk_tail = d;
180 return(d);
183 static int
184 disk_description_is_better(const char *existing, const char *new_desc __unused)
186 if (existing == NULL)
187 return(1);
188 return(0);
191 const char *
192 disk_get_desc(const struct disk *d)
194 return(d->desc);
197 unsigned long
198 disk_get_capacity(const struct disk *d)
200 return(d->capacity);
204 void
205 disk_set_desc(struct disk *d, const char *desc)
207 char *c;
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);
216 * Get the disk's total capacity.
217 * XXX we should do this with C/H/S ?
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);
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.
233 const char *
234 disk_get_device_name(const struct disk *d)
236 static char tmp_dev_name[256];
238 snprintf(tmp_dev_name, 256, "%s", d->device);
239 return(tmp_dev_name);
242 const char *
243 disk_get_serno(const struct disk *d)
245 return(d->serno);
248 void
249 disk_set_serno(struct disk *d, const char *serno)
251 d->serno = aura_strdup(serno);
255 disk_get_number(const struct disk *d)
257 return(d->number);
260 void
261 disk_set_number(struct disk *d, const int number)
263 d->number = number;
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".
274 struct disk *
275 disk_find(const struct storage *s, const char *device)
277 struct disk *d = s->disk_head;
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;
286 return(NULL);
289 struct disk *
290 disk_next(const struct disk *d)
292 return(d->next);
295 struct slice *
296 disk_slice_first(const struct disk *d)
298 return(d->slice_head);
301 void
302 disk_set_formatted(struct disk *d, int formatted)
304 d->we_formatted = formatted;
308 disk_get_formatted(const struct disk *d)
310 return(d->we_formatted);
313 void
314 disk_set_geometry(struct disk *d, int cyl, int hd, int sec)
316 d->cylinders = cyl;
317 d->heads = hd;
318 d->sectors = sec;
321 void
322 disk_get_geometry(const struct disk *d, int *cyl, int *hd, int *sec)
324 *cyl = d->cylinders;
325 *hd = d->heads;
326 *sec = d->sectors;
330 * Free the memory allocated to hold the set of disk descriptions.
332 void
333 disks_free(struct storage *s)
335 struct disk *d = s->disk_head, *next;
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;
346 s->disk_head = NULL;
347 s->disk_tail = NULL;
351 * Create a new slice description and add it to a disk description.
353 struct slice *
354 slice_new(struct disk *d, int number, int type, int flags,
355 unsigned long start, unsigned long size)
357 struct slice *s;
358 const char *sysid_desc = NULL;
359 char unknown[256];
360 int i;
362 dfui_debug("** adding slice %d (start %ld, size %ld, sysid %d) "
363 "to disk %s\n", number, start, size, type, d->device);
365 AURA_MALLOC(s, slice);
367 s->parent = d;
369 s->subpartition_head = NULL;
370 s->subpartition_tail = NULL;
371 s->number = number;
373 s->type = type;
374 s->flags = flags;
375 s->start = start;
376 s->size = size;
378 for (i = 0; ; i++) {
379 if (part_types[i].type == type) {
380 sysid_desc = part_types[i].name;
381 break;
383 if (part_types[i].type == 255)
384 break;
386 if (sysid_desc == NULL) {
387 snprintf(unknown, 256, "??? Unknown, sysid = %d", type);
388 sysid_desc = unknown;
391 asprintf(&s->desc, "%ldM - %ldM: %s",
392 start / 2048, (start + size) / 2048, sysid_desc);
393 s->capacity = size / 2048;
395 s->next = NULL;
396 if (d->slice_head == NULL)
397 d->slice_head = s;
398 else
399 d->slice_tail->next = s;
401 s->prev = d->slice_tail;
402 d->slice_tail = s;
404 return(s);
408 * Find a slice description on a given disk description given the
409 * slice number.
411 struct slice *
412 slice_find(const struct disk *d, int number)
414 struct slice *s = d->slice_head;
416 while (s != NULL) {
417 if (s->number == number)
418 return(s);
419 s = s->next;
422 return(NULL);
425 struct slice *
426 slice_next(const struct slice *s)
428 return(s->next);
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.
436 const char *
437 slice_get_device_name(const struct slice *s)
439 static char tmp_dev_name[256];
441 snprintf(tmp_dev_name, 256, "%ss%d", s->parent->device, s->number);
442 return(tmp_dev_name);
446 slice_get_number(const struct slice *s)
448 return(s->number);
451 const char *
452 slice_get_desc(const struct slice *s)
454 return(s->desc);
457 unsigned long
458 slice_get_capacity(const struct slice *s)
460 return(s->capacity);
463 unsigned long
464 slice_get_start(const struct slice *s)
466 return(s->start);
469 unsigned long
470 slice_get_size(const struct slice *s)
472 return(s->size);
476 slice_get_type(const struct slice *s)
478 return(s->type);
482 slice_get_flags(const struct slice *s)
484 return(s->flags);
487 struct subpartition *
488 slice_subpartition_first(const struct slice *s)
490 return(s->subpartition_head);
494 * Free all memory for a list of slice descriptions.
496 void
497 slices_free(struct slice *head)
499 struct slice *next;
501 while (head != NULL) {
502 next = head->next;
503 subpartitions_free(head);
504 free(head->desc);
505 AURA_FREE(head, slice);
506 head = next;
510 struct subpartition *
511 subpartition_new_hammer(struct slice *s, const char *mountpoint,
512 long capacity, int encrypted)
514 struct subpartition *sp;
515 struct subpartition *last = s->subpartition_tail;
517 AURA_MALLOC(sp, subpartition);
519 sp->parent = s;
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);
528 if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0)
529 sp->letter = 'd';
531 sp->mountpoint = aura_strdup(mountpoint);
532 sp->capacity = capacity;
533 sp->encrypted = encrypted;
534 sp->type = FS_HAMMER;
537 * We need this here, because a UFS /boot needs valid values
539 if (sp->capacity < 1024)
540 sp->fsize = 1024;
541 else
542 sp->fsize = 2048;
544 if (sp->capacity < 1024)
545 sp->bsize = 8192;
546 else
547 sp->bsize = 16384;
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
561 sp->next = NULL;
562 if (s->subpartition_head == NULL)
563 s->subpartition_head = sp;
564 else
565 s->subpartition_tail->next = sp;
567 sp->prev = s->subpartition_tail;
568 s->subpartition_tail = sp;
570 return(sp);
573 struct subpartition *
574 subpartition_new_hammer2(struct slice *s, const char *mountpoint,
575 long capacity, int encrypted)
577 struct subpartition *sp;
578 struct subpartition *last = s->subpartition_tail;
580 AURA_MALLOC(sp, subpartition);
582 sp->parent = s;
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);
591 if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0)
592 sp->letter = 'd';
594 sp->mountpoint = aura_strdup(mountpoint);
595 sp->capacity = capacity;
596 sp->encrypted = encrypted;
597 sp->type = FS_HAMMER2;
600 * We need this here, because a UFS /boot needs valid values
602 if (sp->capacity < 1024)
603 sp->fsize = 1024;
604 else
605 sp->fsize = 2048;
607 if (sp->capacity < 1024)
608 sp->bsize = 8192;
609 else
610 sp->bsize = 16384;
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
624 sp->next = NULL;
625 if (s->subpartition_head == NULL)
626 s->subpartition_head = sp;
627 else
628 s->subpartition_tail->next = sp;
630 sp->prev = s->subpartition_tail;
631 s->subpartition_tail = sp;
633 return(sp);
637 * NOTE: arguments to this function are not checked for sanity.
639 * fsize and/or bsize may both be -1, indicating
640 * "choose a reasonable default."
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)
646 struct subpartition *sp;
647 struct subpartition *last = s->subpartition_tail;
649 AURA_MALLOC(sp, subpartition);
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);
663 if (sp->letter == 'b' && strcmp(mountpoint, "swap") != 0)
664 sp->letter = 'd';
667 sp->parent = s;
669 sp->mountpoint = aura_strdup(mountpoint);
670 sp->capacity = capacity;
671 sp->encrypted = encrypted;
672 sp->type = FS_UFS;
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;
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;
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;
701 sp->tmpfsbacked = tmpfsbacked;
703 sp->is_swap = 0;
704 if (strcasecmp(mountpoint, "swap") == 0)
705 sp->is_swap = 1;
708 * install
710 sp->next = NULL;
711 if (s->subpartition_head == NULL)
712 s->subpartition_head = sp;
713 else
714 s->subpartition_tail->next = sp;
716 sp->prev = s->subpartition_tail;
717 s->subpartition_tail = sp;
719 #if 0
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++;
733 #endif
735 return(sp);
739 * Find the subpartition description in the given storage
740 * description whose mountpoint matches the given string exactly.
742 struct subpartition *
743 subpartition_find(const struct slice *s, const char *fmt, ...)
745 struct subpartition *sp = s->subpartition_head;
746 char *mountpoint;
747 va_list args;
749 va_start(args, fmt);
750 vasprintf(&mountpoint, fmt, args);
751 va_end(args);
753 while (sp != NULL) {
754 if (strcmp(mountpoint, sp->mountpoint) == 0) {
755 free(mountpoint);
756 return(sp);
758 sp = sp->next;
761 free(mountpoint);
762 return(NULL);
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.
771 struct subpartition *
772 subpartition_of(const struct slice *s, const char *fmt, ...)
774 struct subpartition *sp = s->subpartition_head;
775 struct subpartition *csp = NULL;
776 size_t len = 0;
777 char *filename;
778 va_list args;
780 va_start(args, fmt);
781 vasprintf(&filename, fmt, args);
782 va_end(args);
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);
791 sp = sp->next;
794 free(filename);
795 return(csp);
798 struct subpartition *
799 subpartition_find_capacity(const struct slice *s, long capacity)
801 struct subpartition *sp = s->subpartition_head;
803 while (sp != NULL) {
804 if (sp->capacity == capacity)
805 return(sp);
806 sp = sp->next;
809 return(NULL);
812 struct subpartition *
813 subpartition_next(const struct subpartition *sp)
815 return(sp->next);
819 subpartition_get_pfs(const struct subpartition *sp)
821 return(sp->pfs);
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.
830 const char *
831 subpartition_get_device_name(const struct subpartition *sp)
833 static char tmp_dev_name[256];
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);
845 * /dev/mapper/
847 * (result is persistant until next call)
849 const char *
850 subpartition_get_mapper_name(const struct subpartition *sp, int withdev)
852 const char *src;
853 static char *save;
855 src = strrchr(sp->mountpoint, '/');
856 if (src == NULL || src[1] == 0)
857 src = "root";
858 else
859 ++src;
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;
875 return save;
878 const char *
879 subpartition_get_mountpoint(const struct subpartition *sp)
881 return(sp->mountpoint);
884 char
885 subpartition_get_letter(const struct subpartition *sp)
887 return(sp->letter);
890 unsigned long
891 subpartition_get_fsize(const struct subpartition *sp)
893 return(sp->fsize);
896 unsigned long
897 subpartition_get_bsize(const struct subpartition *sp)
899 return(sp->bsize);
902 long
903 subpartition_get_capacity(const struct subpartition *sp)
905 return(sp->capacity);
908 void
909 subpartition_clr_encrypted(struct subpartition *sp)
911 sp->encrypted = 0;
915 subpartition_is_encrypted(const struct subpartition *sp)
917 return(sp->encrypted);
921 subpartition_is_swap(const struct subpartition *sp)
923 return(sp->is_swap);
927 subpartition_is_softupdated(const struct subpartition *sp)
929 return(sp->softupdates);
932 subpartition_is_tmpfsbacked(const struct subpartition *sp)
934 return(sp->tmpfsbacked);
938 subpartition_count(const struct slice *s)
940 struct subpartition *sp = s->subpartition_head;
941 int count = 0;
943 while (sp != NULL) {
944 count++;
945 sp = sp->next;
948 return(count);
951 void
952 subpartitions_free(struct slice *s)
954 struct subpartition *sp = s->subpartition_head, *next;
956 while (sp != NULL) {
957 next = sp->next;
958 free(sp->mountpoint);
959 AURA_FREE(sp, subpartition);
960 sp = next;
963 s->subpartition_head = NULL;
964 s->subpartition_tail = NULL;
967 long
968 measure_activated_swap(const struct i_fn_args *a)
970 FILE *p;
971 char line[256];
972 char *word;
973 long swap = 0;
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);
986 aura_pclose(p);
988 return(swap / 1024);
991 long
992 measure_activated_swap_from_slice(const struct i_fn_args *a,
993 const struct disk *d, const struct slice *s)
995 FILE *p;
996 char *dev, *word;
997 char line[256];
998 long swap = 0;
1000 if ((p = aura_popen("%s%s -k", "r", a->os_root, cmd_name(a, "SWAPINFO"))) == NULL)
1001 return(0);
1003 asprintf(&dev, "/dev/%ss%d", d->device, s->number);
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);
1016 aura_pclose(p);
1017 free(dev);
1019 return(swap / 1024);
1022 long
1023 measure_activated_swap_from_disk(const struct i_fn_args *a,
1024 const struct disk *d)
1026 struct slice *s;
1027 long swap = 0;
1029 for (s = d->slice_head; s != NULL; s = s->next)
1030 swap += measure_activated_swap_from_slice(a, d, s);
1032 return(swap);
1035 void *
1036 swapoff_all(const struct i_fn_args *a)
1038 FILE *p;
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);
1049 return(p);
1052 void *
1053 remove_all_mappings(const struct i_fn_args *a)
1055 FILE *p;
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);
1064 return(p);