/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "alloc-util.h"
#include "extract-word.h"
#include "macro.h"
#include "parse-argument.h"
#include "path-util.h"
#include "string-util.h"
#include "vmspawn-mount.h"

static void runtime_mount_done(RuntimeMount *mount) {
        assert(mount);

        mount->source = mfree(mount->source);
        mount->target = mfree(mount->target);
}

void runtime_mount_context_done(RuntimeMountContext *ctx) {
        assert(ctx);

        FOREACH_ARRAY(mount, ctx->mounts, ctx->n_mounts)
                runtime_mount_done(mount);

        free(ctx->mounts);
}

int runtime_mount_parse(RuntimeMountContext *ctx, const char *s, bool read_only) {
        _cleanup_(runtime_mount_done) RuntimeMount mount = { .read_only = read_only };
        _cleanup_free_ char *source_rel = NULL;
        int r;

        assert(ctx);

        r = extract_first_word(&s, &source_rel, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
        if (r < 0)
                return r;
        if (r == 0)
                return -EINVAL;

        if (isempty(source_rel))
                return -EINVAL;

        r = path_make_absolute_cwd(source_rel, &mount.source);
        if (r < 0)
                return r;

        /* virtiofsd only supports directories */
        r = is_dir(mount.source, /* follow= */ true);
        if (r < 0)
                return r;
        if (!r)
                return -ENOTDIR;

        mount.target = s ? strdup(s) : TAKE_PTR(source_rel);
        if (!mount.target)
                return -ENOMEM;

        if (!path_is_absolute(mount.target))
                return -EINVAL;

        if (!GREEDY_REALLOC(ctx->mounts, ctx->n_mounts + 1))
                return -ENOMEM;

        ctx->mounts[ctx->n_mounts++] = TAKE_STRUCT(mount);

        return 0;
}
