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