Replacing parts of a file

Replacing lines that are between BEGIN INSERT and END INSERT


#include <stdio.h>

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


inline bool fread2(void* buffer, size_t size, size_t count, FILE* stream, size_t* sz)
{
    *sz = 0;//out

    bool result = false;
    size_t n = fread(buffer, size, count, stream);
    if (n == count) {
        *sz = n;
        result = true;
    }
    else if (n < count) {
        if (feof(stream))
        {
            *sz = n;
            result = true;
        }
    }
    return result;
}

char* readfile(const char* path)
{
    char* result = NULL;

    struct stat info;
    if (stat(path, &info) == 0)
    {
        char* data = (char*)malloc(sizeof(char) * info.st_size + 1);
        if (data != NULL)
        {
            FILE* file = fopen(path, "r");
            if (file != NULL)
            {
                if (info.st_size >= 3)
                {
                    size_t n = 0;
                    if (fread2(data, 1, 3, file, &n))
                    {
                        if (n == 3)
                        {
                            if (data[0] == (char)0xEF &&
                                data[1] == (char)0xBB &&
                                data[2] == (char)0xBF)
                            {
                                if (fread2(data, 1, info.st_size - 3, file, &n))
                                {
                                    //ok
                                    data[n] = 0;
                                    result = data; data = 0;
                                }
                            }
                            else if (fread2(data + 3, 1, info.st_size - 3, file, &n))
                            {
                                data[3 + n] = 0;
                                result = data; data = 0;
                            }
                        }
                        else
                        {
                            data[n] = 0;
                            result = data; data = 0;
                        }
                    }
                }
                else
                {
                    size_t n = 0;
                    if (fread2(data, 1, info.st_size, file, &n))
                    {
                        data[n] = 0;
                        result = data; data = 0;
                    }
                }
                fclose(file);
            }
            free(data);
        }
    }
    return result;
}


struct osstream
{
    char* c_str;
    int size;
    int capacity;
};


int osstream_putc(int ch, struct osstream* sb)
{
    if (sb->size + 1 > sb->capacity)
    {
        int n = sb->capacity + sb->capacity / 2;
        if (n < sb->size + 1)
        {
            n = sb->size + 1;
        }

        char* pnew = sb->c_str;
        pnew = (char*)realloc(pnew, (n + 1) * sizeof(char));
        if (pnew)
        {
            sb->c_str = pnew;
            sb->capacity = n;
        }
        else
        {
            errno = ENOMEM;
            ch = EOF;
        }
    }

    if (ch != EOF)
    {
        sb->c_str[sb->size] = ch;
        sb->c_str[sb->size + 1] = 0;
        sb->size++;
    }

    return ch;
}

int osstream_close(struct osstream* stream)
{
    free(stream->c_str);
    return 0;
}


int osstream_vafprintf(struct osstream* stream, const char* fmt, va_list args)
{
    int size = 0;
    va_list tmpa;

    va_copy(tmpa, args);

    size = vsnprintf(stream->c_str + stream->size, stream->capacity - stream->size, fmt, tmpa);

    va_end(tmpa);

    if (size < 0)
    {
        return -1;
    }

    if (stream->size + size > stream->capacity)
    {
        char* pnew = stream->c_str;
        pnew = (char*)realloc(pnew, (stream->size + size + 1) * sizeof(char));
        if (pnew)
        {
            stream->c_str = pnew;
            stream->capacity = stream->size + size;
        }
        else
        {
            errno = ENOMEM;
            size = -1;
        }
    }

    size = vsprintf(stream->c_str + stream->size, fmt, args);
    if (size > 0)
    {
        stream->size += size;
    }
    return size;
}

int osstream_printf(struct osstream* stream, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    int size = osstream_vafprintf(stream, fmt, args);
    va_end(args);
    return size;
}

int savefile(const char* filename, const char* content)
{
    int result = 0;

    FILE* f = fopen(filename, "w");
    if (f)
    {
        int count = strlen(content);
        int result = fwrite(content, sizeof(char), count, f);
        if (count != result)
        {
            //fwrite error
            result = ferror(f);
        }
        fclose(f);
    }
    else
    {
        //fopen error
        result = errno;
    }

    return result;
}

int change_text(const char* filename, const char* newcontent)
{
    char* s = readfile("file.txt");
    if (s != NULL)
    {
        struct osstream ss = { 0 };
        const char* p1 = strstr(s, "<!--BEGIN INSERT-->");
        if (p1)
        {
            osstream_printf(&ss, "%.*s", (int)(p1 - s), s);
            osstream_printf(&ss, "<!--BEGIN INSERT-->\n");

            const char* p2 = strstr(p1 + 1, "<!--END INSERT-->");
            if (p2)
            {
                osstream_printf(&ss, "%s\n", newcontent);

                osstream_printf(&ss, "<!--END INSERT-->\n");
                osstream_printf(&ss, "%s", p2 + sizeof("<!--END INSERT-->"));
            }
        }
        free(s);
        savefile("file.txt", ss.c_str);
        osstream_close(&ss);
    }
    else
    {
        printf("%s\n", strerror(errno));
    }
    return 0;
}

int main()
{
    change_text("file.txt", "new content");
}