diff options
Diffstat (limited to 'lib/libdisk/chunk.c')
-rw-r--r-- | lib/libdisk/chunk.c | 595 |
1 files changed, 0 insertions, 595 deletions
diff --git a/lib/libdisk/chunk.c b/lib/libdisk/chunk.c deleted file mode 100644 index fb43ef5..0000000 --- a/lib/libdisk/chunk.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <err.h> -#include "libdisk.h" - -struct chunk * -New_Chunk(void) -{ - struct chunk *c; - - c = malloc(sizeof *c); - if (c != NULL) - memset(c, 0, sizeof *c); - return (c); -} - -/* Is c2 completely inside c1 ? */ - -static int -Chunk_Inside(const struct chunk *c1, const struct chunk *c2) -{ - /* if c1 ends before c2 do */ - if (c1->end < c2->end) - return 0; - /* if c1 starts after c2 do */ - if (c1->offset > c2->offset) - return 0; - return 1; -} - -static struct chunk * -Find_Mother_Chunk(struct chunk *chunks, daddr_t offset, daddr_t end, - chunk_e type) -{ - struct chunk *c1, *c2, ct; - - ct.offset = offset; - ct.end = end; - switch (type) { - case whole: - if (Chunk_Inside(chunks, &ct)) - return chunks; - case extended: - for (c1 = chunks->part; c1; c1 = c1->next) { - if (c1->type != type) - continue; - if (Chunk_Inside(c1, &ct)) - return c1; - } - return 0; - case freebsd: - for (c1 = chunks->part; c1; c1 = c1->next) { - if (c1->type == type) - if (Chunk_Inside(c1, &ct)) - return c1; - if (c1->type != extended) - continue; - for (c2 = c1->part; c2; c2 = c2->next) - if (c2->type == type && Chunk_Inside(c2, &ct)) - return c2; - } - return 0; -#ifdef __powerpc__ - case apple: - for (c1 = chunks->part; c1; c1 = c1->next) { - if (c1->type == type) - if (Chunk_Inside(c1, &ct)) - return c1; - } - return 0; -#endif - default: - warn("Unsupported mother type in Find_Mother_Chunk"); - return 0; - } -} - -void -Free_Chunk(struct chunk *c1) -{ - if(c1 == NULL) - return; - if(c1->private_data && c1->private_free) - (*c1->private_free)(c1->private_data); - if(c1->part != NULL) - Free_Chunk(c1->part); - if(c1->next != NULL) - Free_Chunk(c1->next); - if (c1->name != NULL) - free(c1->name); - if (c1->sname != NULL) - free(c1->sname); - free(c1); -} - -struct chunk * -Clone_Chunk(const struct chunk *c1) -{ - struct chunk *c2; - - if(!c1) - return NULL; - c2 = New_Chunk(); - if (c2 == NULL) - return NULL; - *c2 = *c1; - if (c1->private_data && c1->private_clone) - c2->private_data = c2->private_clone(c2->private_data); - c2->name = strdup(c2->name); - if (c2->sname != NULL) - c2->sname = strdup(c2->sname); - c2->next = Clone_Chunk(c2->next); - c2->part = Clone_Chunk(c2->part); - return c2; -} - -int -Insert_Chunk(struct chunk *c2, daddr_t offset, daddr_t size, const char *name, - chunk_e type, int subtype, u_long flags, const char *sname) -{ - struct chunk *ct,*cs; - - /* We will only insert into empty spaces */ - if (c2->type != unused) - return __LINE__; - - ct = New_Chunk(); - if (ct == NULL) - return __LINE__; - ct->disk = c2->disk; - ct->offset = offset; - ct->size = size; - ct->end = offset + size - 1; - ct->type = type; - if (sname != NULL) - ct->sname = strdup(sname); - ct->name = strdup(name); - ct->subtype = subtype; - ct->flags = flags; - - if (!Chunk_Inside(c2, ct)) { - Free_Chunk(ct); - return __LINE__; - } - - if ((type == freebsd || type == extended || type == apple)) { - cs = New_Chunk(); - if (cs == NULL) - return __LINE__; - cs->disk = c2->disk; - cs->offset = offset; - cs->size = size; - cs->end = offset + size - 1; - cs->type = unused; - if (sname != NULL) - cs->sname = strdup(sname); - cs->name = strdup("-"); - ct->part = cs; - } - - /* Make a new chunk for any trailing unused space */ - if (c2->end > ct->end) { - cs = New_Chunk(); - if (cs == NULL) - return __LINE__; - *cs = *c2; - cs->disk = c2->disk; - cs->offset = ct->end + 1; - cs->size = c2->end - ct->end; - if (c2->sname != NULL) - cs->sname = strdup(c2->sname); - if (c2->name) - cs->name = strdup(c2->name); - c2->next = cs; - c2->size -= c2->end - ct->end; - c2->end = ct->end; - } - /* If no leading unused space just occupy the old chunk */ - if (c2->offset == ct->offset) { - c2->sname = ct->sname; - c2->name = ct->name; - c2->type = ct->type; - c2->part = ct->part; - c2->subtype = ct->subtype; - c2->flags = ct->flags; - ct->sname = NULL; - ct->name = NULL; - ct->part = 0; - Free_Chunk(ct); - return 0; - } - /* else insert new chunk and adjust old one */ - c2->end = ct->offset - 1; - c2->size -= ct->size; - ct->next = c2->next; - c2->next = ct; - return 0; -} - -int -Add_Chunk(struct disk *d, daddr_t offset, daddr_t size, const char *name, - chunk_e type, int subtype, u_long flags, const char *sname) -{ - struct chunk *c1, *c2, ct; - daddr_t end = offset + size - 1; - ct.offset = offset; - ct.end = end; - ct.size = size; - - if (type == whole) { - d->chunks = c1 = New_Chunk(); - if (c1 == NULL) - return __LINE__; - c2 = c1->part = New_Chunk(); - if (c2 == NULL) - return __LINE__; - c2->disk = c1->disk = d; - c2->offset = c1->offset = offset; - c2->size = c1->size = size; - c2->end = c1->end = end; - c1->sname = strdup(sname); - c2->sname = strdup("-"); - c1->name = strdup(name); - c2->name = strdup("-"); - c1->type = type; - c2->type = unused; - c1->flags = flags; - c1->subtype = subtype; - return 0; - } - - c1 = 0; - /* PLATFORM POLICY BEGIN ------------------------------------- */ - switch(platform) { - case p_i386: - case p_amd64: - switch (type) { - case fat: - case gpt: - case mbr: - case extended: - case freebsd: - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); - break; - case part: - c1 = Find_Mother_Chunk(d->chunks, offset, end, freebsd); - break; - default: - return(-1); - } - break; - case p_ia64: - switch (type) { - case freebsd: - subtype = 0xa5; - /* FALL THROUGH */ - case fat: - case efi: - case mbr: - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); - break; - case part: - c1 = Find_Mother_Chunk(d->chunks, offset, end, - freebsd); - if (!c1) - c1 = Find_Mother_Chunk(d->chunks, offset, end, - whole); - break; - default: - return (-1); - } - break; - case p_pc98: - switch (type) { - case fat: - case pc98: - case freebsd: - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); - break; - case part: - c1 = Find_Mother_Chunk(d->chunks, offset, end, freebsd); - break; - default: - return(-1); - } - break; - case p_sparc64: - case p_alpha: - switch (type) { - case freebsd: - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); - break; - case part: - c1 = Find_Mother_Chunk(d->chunks, offset, end, freebsd); - break; - default: - return(-1); - } - break; - case p_ppc: - switch (type) { - case apple: - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); - break; - case part: - c1 = Find_Mother_Chunk(d->chunks, offset, end, apple); - break; - default: - return (-1); - } - break; - default: - return (-1); - } - /* PLATFORM POLICY END ---------------------------------------- */ - - if(!c1) - return __LINE__; - for(c2 = c1->part; c2; c2 = c2->next) { - if (c2->type != unused) - continue; - if(!Chunk_Inside(c2, &ct)) - continue; -/* PLATFORM POLICY BEGIN ------------------------------------- */ - if (platform == p_sparc64) { - offset = Prev_Cyl_Aligned(d, offset); - size = Next_Cyl_Aligned(d, size); - } else if (platform == p_i386 || platform == p_pc98 || - platform == p_amd64) { - if (type != freebsd) - break; - if (!(flags & CHUNK_ALIGN)) - break; - if (offset == d->chunks->offset && - end == d->chunks->end) - break; - - /* Round down to prev cylinder */ - offset = Prev_Cyl_Aligned(d,offset); - /* Stay inside the parent */ - if (offset < c2->offset) - offset = c2->offset; - /* Round up to next cylinder */ - offset = Next_Cyl_Aligned(d, offset); - /* Keep one track clear in front of parent */ - if (offset == c1->offset) - offset = Next_Track_Aligned(d, offset + 1); - /* Work on the (end+1) */ - size += offset; - /* Round up to cylinder */ - size = Next_Cyl_Aligned(d, size); - /* Stay inside parent */ - if ((size-1) > c2->end) - size = c2->end + 1; - /* Round down to cylinder */ - size = Prev_Cyl_Aligned(d, size); - - /* Convert back to size */ - size -= offset; - } - break; - -/* PLATFORM POLICY END ------------------------------------- */ - } - if (c2 == NULL) - return (__LINE__); - return Insert_Chunk(c2, offset, size, name, type, subtype, flags, - sname); -} - -char * -ShowChunkFlags(struct chunk *c) -{ - static char ret[10]; - int i = 0; - - if (c->flags & CHUNK_ACTIVE) - ret[i++] = 'A'; - if (c->flags & CHUNK_ALIGN) - ret[i++] = '='; - if (c->flags & CHUNK_IS_ROOT) - ret[i++] = 'R'; - ret[i++] = '\0'; - - return ret; -} - -static void -Print_Chunk(struct chunk *c1, int offset) -{ - int i; - - if (!c1) - return; - for (i = 0; i < offset - 2; i++) - putchar(' '); - for (; i < offset; i++) - putchar('-'); - putchar('>'); - for (; i < 10; i++) - putchar(' '); -#ifndef __ia64__ - printf("%p ", c1); -#endif - printf("%8jd %8jd %8jd %-8s %-16s %-8s 0x%02x %s", - (intmax_t)c1->offset, (intmax_t)c1->size, (intmax_t)c1->end, - c1->name, c1->sname, chunk_name(c1->type), c1->subtype, - ShowChunkFlags(c1)); - putchar('\n'); - Print_Chunk(c1->part, offset + 2); - Print_Chunk(c1->next, offset); -} - -void -Debug_Chunk(struct chunk *c1) -{ - - Print_Chunk(c1, 2); -} - -int -Delete_Chunk(struct disk *d, struct chunk *c) -{ - - return (Delete_Chunk2(d, c, 0)); -} - -int -Delete_Chunk2(struct disk *d, struct chunk *c, int rflags) -{ - struct chunk *c1, *c2, *c3; - daddr_t offset = c->offset; - - switch (c->type) { - case whole: - case unused: - return 1; - case extended: - c1 = Find_Mother_Chunk(d->chunks, c->offset, c->end, whole); - break; - case part: - c1 = Find_Mother_Chunk(d->chunks, c->offset, c->end, freebsd); -#ifdef __ia64__ - if (c1 == NULL) - c1 = Find_Mother_Chunk(d->chunks, c->offset, c->end, - whole); -#endif -#ifdef __powerpc__ - if (c1 == NULL) - c1 = Find_Mother_Chunk(d->chunks, c->offset, c->end, - apple); -#endif - break; - default: - c1 = Find_Mother_Chunk(d->chunks, c->offset, c->end, extended); - if (c1 == NULL) - c1 = Find_Mother_Chunk(d->chunks, c->offset, c->end, - whole); - break; - } - if (c1 == NULL) - return 1; - for (c2 = c1->part; c2; c2 = c2->next) { - if (c2 == c) { - c2->type = unused; - c2->subtype = 0; - c2->flags = 0; - if (c2->sname != NULL) - free(c2->sname); - c2->sname = strdup("-"); - free(c2->name); - c2->name = strdup("-"); - Free_Chunk(c2->part); - c2->part =0; - goto scan; - } - } - return 1; -scan: - /* - * Collapse multiple unused elements together, and attempt - * to extend the previous chunk into the freed chunk. - * - * We only extend non-unused elements which are marked - * for newfs (we can't extend working filesystems), and - * only if we are called with DELCHUNK_RECOVER. - */ - for (c2 = c1->part; c2; c2 = c2->next) { - if (c2->type != unused) { - if (c2->offset + c2->size != offset || - (rflags & DELCHUNK_RECOVER) == 0 || - (c2->flags & CHUNK_NEWFS) == 0) { - continue; - } - /* else extend into free area */ - } - if (!c2->next) - continue; - if (c2->next->type != unused) - continue; - c3 = c2->next; - c2->size += c3->size; - c2->end = c3->end; - c2->next = c3->next; - c3->next = 0; - Free_Chunk(c3); - goto scan; - } - Fixup_Names(d); - return 0; -} - -#if 0 -int -Collapse_Chunk(struct disk *d, struct chunk *c1) -{ - struct chunk *c2, *c3; - - if (c1->next && Collapse_Chunk(d, c1->next)) - return 1; - - if (c1->type == unused && c1->next && c1->next->type == unused) { - c3 = c1->next; - c1->size += c3->size; - c1->end = c3->end; - c1->next = c3->next; - c3->next = 0; - Free_Chunk(c3); - return 1; - } - c3 = c1->part; - if (!c3) - return 0; - if (Collapse_Chunk(d, c1->part)) - return 1; - - if (c1->type == whole) - return 0; - - if (c3->type == unused && c3->size == c1->size) { - Delete_Chunk(d, c1); - return 1; - } - if (c3->type == unused) { - c2 = New_Chunk(); - if (c2 == NULL) - barfout(1, "malloc failed"); - *c2 = *c1; - c1->next = c2; - c1->disk = d; - c1->sname = strdup("-"); - c1->name = strdup("-"); - c1->part = 0; - c1->type = unused; - c1->flags = 0; - c1->subtype = 0; - c1->size = c3->size; - c1->end = c3->end; - c2->offset += c1->size; - c2->size -= c1->size; - c2->part = c3->next; - c3->next = 0; - Free_Chunk(c3); - return 1; - } - for (c2 = c3; c2->next; c2 = c2->next) - c3 = c2; - if (c2 && c2->type == unused) { - c3->next = 0; - c2->next = c1->next; - c1->next = c2; - c1->size -= c2->size; - c1->end -= c2->size; - return 1; - } - - return 0; -} -#endif |