/*
 * This file is part of MultiROM.
 *
 * MultiROM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MultiROM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MultiROM.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#include "lib/log.h"
#include "rcadditions.h"

static void append_string_buffer(char **buf, const char *what) {
    size_t old_len = 0;
    if(*buf)
        old_len += strlen(*buf);

    *buf = realloc(*buf, old_len + strlen(what) + 1);
    (*buf)[old_len] = 0;
    strcat(*buf, what);
}

void rcadditions_append_trigger(struct rcadditions *r, const char *trigger, const char *what) {
    if(r->triggers == NULL)
        r->triggers = map_create();

    char **ref = (char**)map_get_ref(r->triggers, trigger);
    if(ref == NULL)
        map_add_not_exist(r->triggers, trigger, strdup(what));
    else
        append_string_buffer(ref, what);
}

void rcadditions_append_file(struct rcadditions *r, const char *what) {
    append_string_buffer(&r->eof_append, what);
}

void rcadditions_append_contexts(struct rcadditions *r, const char *what) {
    append_string_buffer(&r->file_contexts_append, what);
}

void rcadditions_free(struct rcadditions *r)
{
    free(r->eof_append);
    r->eof_append = NULL;

    free(r->file_contexts_append);
    r->file_contexts_append = NULL;

    map_destroy(r->triggers, &free);
    r->triggers = NULL;
}

void rcadditions_write_to_files(struct rcadditions *r)
{
    if(r->eof_append || r->triggers)
    {
        FILE *f = fopen("/init.multirom.rc", "we");
        if(!f)
        {
            ERROR("Failed to create init.multirom.rc: %s\n", strerror(errno));
            return;
        }

        fputs("# This file is autogenerated by MultiROM during boot\n\n", f);

        if(r->triggers)
        {
            size_t i = 0;
            for(; i < r->triggers->size; ++i)
            {
                fprintf(f, "on %s\n", r->triggers->keys[i]);
                fputs((char*)r->triggers->values[i], f);
                fputc('\n', f);
            }
        }

        if(r->eof_append)
        {
            fputc('\n', f);
            fputs(r->eof_append, f);
        }
        fclose(f);

        chmod("/init.multirom.rc", 0750);

        f = fopen("/init.rc", "ae");
        if(!f)
        {
            ERROR("Failed to open init.rc: %s\n", strerror(errno));
            return;
        }
        fputs("\n# Added by MultiROM\nimport /init.multirom.rc\n", f);
        fclose(f);
    }

    if(r->file_contexts_append)
    {
        FILE *f = fopen("/file_contexts", "ae");
        if(!f)
        {
            ERROR("Failed to open file_contexts: %s\n", strerror(errno));
            return;
        }
        fputs("\n# Added by multirom during boot\n", f);
        fputs(r->file_contexts_append, f);
        fclose(f);
    }
}
