Welcome to little lamb

Code » ssp » master » tree

[master] / src / ssp / rename.c

/* This file is part of ssp                             https://lila.oss/ssp
 * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <errno.h>
#include <limb/command.h>
#include <limb/exitcode.h>
#include <limb/loadopt.h>
#include <limb/output.h>
#include <limb/stralloc.h>
#include "ssp.h"

struct rename {
    stralloc sa;
    size_t entoff;
    size_t newoff;
};

enum {
    ARGID_ENTRY = OPTID_FIRST,
    ARGID_NEWNAME,
};

COMMAND(rename, "Rename an entry", "<entry> <newname>", NULL);

static int
parse_cmdline(int argc, const char *argv[], const char usage[], struct rename *ctx)
{
    const struct option options[] = {
        LOADOPT_ARGUMENTS,
        ARGUMENT_REQ( "entry",                          OPT_PATH,   ARGID_ENTRY),
        ARGUMENT_REQ( "newname",                        OPT_PATH,   ARGID_NEWNAME),
        LOADOPT_DONE
    };
    struct loadopt lo = LOADOPT_ZERO;

    int c;
    while ((c = loadopt(&ctx->sa, argc, argv, options, 0, NULL, 0, &lo))) switch (c) {

        case ARGID_ENTRY:
            ctx->entoff = LO_OFF(&lo);
            break;
        case ARGID_NEWNAME:
            ctx->newoff = LO_OFF(&lo);
            break;

        case -1:
            diecmdusage(EX_USAGE, usage, &command_rename);
        default:
            die(EX_SOFTWARE, "unexpected return value ", PMINT(c), " from loadopt");
    };

    return LO_CUR(&lo);
}

int
rename_main(int argc, const char *argv[], const char *env[], const char usage[], void *ssp_)
{
    struct ssp *ssp = ssp_;
    struct rename ctx = { .sa = STRALLOC_ZERO };

    (void) env;
    parse_cmdline(argc, argv, usage, &ctx);

    const char *entry = ctx.sa.s + ctx.entoff;
    const char *newname = ctx.sa.s + ctx.newoff;

    if (!strcmp(entry, newname))
        diefu(EX_DATA_ERR, "rename entry ", ESC, entry, ESC, ": new name is the same");

    int r = open_db(ssp, 1);
    if (r < 0)
        diefu(exitcode_from_errno(errno), "open database");

    r = db_find(entry, ssp);
    if (r < 0)
        diefu(EX_DATA_ERR, "find entry ", ESC, entry, ESC);
    if (!r)
        dief(EX_DATA_ERR, "no entry ", ESC, entry, ESC, " in database");

    quiet("Renaming ", ESC, entry, ESC, " to ", ESC, newname, ESC, "...");
    rebuild_db(entry, newname, db_otp(ssp), ssp);

    dbg("showing renamed entry");
    close_db(ssp);
    const char *av[] = { NULL, newname };
    run_command("show", sizeof(av) / sizeof(*av), av, env, ssp);

    stralloc_free(&ctx.sa);
    return 0;
}