<commit_before>/**
 * @file ds_lyb.c
 * @author <NAME> <<EMAIL>>
 * @brief internal LYB datastore plugin
 *
 * @copyright
 * Copyright (c) 2021 Deutsche Telekom AG.
 * Copyright (c) 2021 CESNET, z.s.p.o.
 *
 * This source code is licensed under BSD 3-Clause License (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://opensource.org/licenses/BSD-3-Clause
 */

#define _GNU_SOURCE

#include "plugins_datastore.h"

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <libyang/libyang.h>

#include "compat.h"
#include "common_lyb.h"
#include "sysrepo.h"

#define srpds_name "LYB DS file"  /**< plugin name */

static int srpds_lyb_load(const struct lys_module *mod, sr_datastore_t ds, const char **xpaths, uint32_t xpath_count,
        struct lyd_node **mod_data);

static int srpds_lyb_candidate_modified(const struct lys_module *mod, int *modified);

static int srpds_lyb_access_get(const struct lys_module *mod, sr_datastore_t ds, char **owner, char **group,
        mode_t *perm);

static int
srpds_lyb_store_(const struct lys_module *mod, sr_datastore_t ds, const struct lyd_node *mod_data, const char *owner,
        const char *group, mode_t perm, int make_backup)
{
    int rc = SR_ERR_OK;
    struct stat st;
    char *path = NULL, *bck_path = NULL;
    int fd = -1, backup = 0;

    /* get path */
    if ((rc = srlyb_get_path(srpds_name, mod->name, ds, &path))) {
        goto cleanup;
    }

    if (make_backup && (ds == SR_DS_STARTUP)) {
        /* get original file perms */
        if (stat(path, &st) == -1) {
            if (errno == EACCES) {
                SRPLG_LOG_ERR(srpds_name, "Learning \"%s\" permissions failed.", mod->name);
                rc = SR_ERR_UNAUTHORIZED;
            } else {
                SRPLG_LOG_ERR(srpds_name, "Stat of \"%s\" failed (%s).", path, strerror(errno));
                rc = SR_ERR_SYS;
            }
            goto cleanup;
        }

        /* generate the backup path */
        if (asprintf(&bck_path, "%s%s", path, SRLYB_FILE_BACKUP_SUFFIX) == -1) {
            SRPLG_LOG_ERR(srpds_name, "Memory allocation failed.");
            rc = SR_ERR_NO_MEMORY;
            goto cleanup;
        }

        /* create backup file with same owner/group/perm */
        if ((fd = srlyb_open(bck_path, O_WRONLY | O_CREAT | O_EXCL, st.st_mode)) == -1) {
            SRPLG_LOG_ERR(srpds_name, "Opening \"%s\" failed (%s).", bck_path, strerror(errno));
            rc = SR_ERR_SYS;
            goto cleanup;
        }
        if (fchown(fd, st.st_uid, st.st_gid) == -1) {
            SRPLG_LOG_ERR(srpds_name, "Changing owner of \"%s\" failed (%s).", bck_path, strerror(errno));
            if ((errno == EACCES) || (errno == EPERM)) {
                rc = SR_ERR_UNAUTHORIZED;
            } else {
                rc = SR_ERR_INTERNAL;
            }
            goto cleanup;
        }

        /* close */
        close(fd);
        fd = -1;

        /* back up any existing file */
        if ((rc = srlyb_cp_path(srpds_name, bck_path, path))) {
            goto cleanup;
        }

        backup = 1;
    }

    /* open the file */
    if ((fd = srlyb_open(path, O_WRONLY | O_CREAT, perm)) == -1) {
        rc = srlyb_open_error(srpds_name, path);
        goto cleanup;
    }

    if (owner || group) {
        /* change the owner of the file */
        if ((rc = srlyb_chmodown(srpds_name, path, owner, group, 0))) {
            goto cleanup;
        }
    }

    /* print data */
    if (lyd_print_fd(fd, mod_data, LYD_LYB, LYD_PRINT_WITHSIBLINGS)) {
        srplyb_log_err_ly(srpds_name, LYD_CTX(mod_data));
        SRPLG_LOG_ERR(srpds_name, "Failed to store data into \"%s\".", path);
        rc = SR_ERR_INTERNAL;
        goto cleanup;
    }

    /* delete the backup file */
    if (backup && (unlink(bck_path) == -1)) {
        SRPLG_LOG_ERR(srpds_name, "Failed to remove backup \"%s\" (%s).", bck_path, strerror(errno));
        rc = SR_ERR_SYS;
        goto cleanup;
    }

cleanup:
    if (fd > -1) {
        close(fd);
    }
    free(path);
    free(bck_path);
    return rc;
}

static int
srpds_lyb_init(const struct lys_module *mod, sr_datastore_t ds, const char *owner, const char *group, mode_t perm)
{
    int rc = SR_ERR_OK;
    struct lyd_node *root = NULL;
    char *path = NULL;

    assert(perm);

    if (ds == SR_DS_CANDIDATE) {
        /* no need to initialize anything */
        return rc;<commit_msg>ds lyb BUGFIX always remove data backup<commit_after>/**
 * @file ds_lyb.c
 * @author <NAME> <<EMAIL>>
 * @brief internal LYB datastore plugin
 *
 * @copyright
 * Copyright (c) 2021 Deutsche Telekom AG.
 * Copyright (c) 2021 CESNET, z.s.p.o.
 *
 * This source code is licensed under BSD 3-Clause License (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://opensource.org/licenses/BSD-3-Clause
 */

#define _GNU_SOURCE

#include "plugins_datastore.h"

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <libyang/libyang.h>

#include "compat.h"
#include "common_lyb.h"
#include "sysrepo.h"

#define srpds_name "LYB DS file"  /**< plugin name */

static int srpds_lyb_load(const struct lys_module *mod, sr_datastore_t ds, const char **xpaths, uint32_t xpath_count,
        struct lyd_node **mod_data);

static int srpds_lyb_candidate_modified(const struct lys_module *mod, int *modified);

static int srpds_lyb_access_get(const struct lys_module *mod, sr_datastore_t ds, char **owner, char **group,
        mode_t *perm);

static int
srpds_lyb_store_(const struct lys_module *mod, sr_datastore_t ds, const struct lyd_node *mod_data, const char *owner,
        const char *group, mode_t perm, int make_backup)
{
    int rc = SR_ERR_OK;
    struct stat st;
    char *path = NULL, *bck_path = NULL;
    int fd = -1, backup = 0;

    /* get path */
    if ((rc = srlyb_get_path(srpds_name, mod->name, ds, &path))) {
        goto cleanup;
    }

    if (make_backup && (ds == SR_DS_STARTUP)) {
        /* get original file perms */
        if (stat(path, &st) == -1) {
            if (errno == EACCES) {
                SRPLG_LOG_ERR(srpds_name, "Learning \"%s\" permissions failed.", mod->name);
                rc = SR_ERR_UNAUTHORIZED;
            } else {
                SRPLG_LOG_ERR(srpds_name, "Stat of \"%s\" failed (%s).", path, strerror(errno));
                rc = SR_ERR_SYS;
            }
            goto cleanup;
        }

        /* generate the backup path */
        if (asprintf(&bck_path, "%s%s", path, SRLYB_FILE_BACKUP_SUFFIX) == -1) {
            SRPLG_LOG_ERR(srpds_name, "Memory allocation failed.");
            rc = SR_ERR_NO_MEMORY;
            goto cleanup;
        }

        /* create backup file with same owner/group/perm */
        if ((fd = srlyb_open(bck_path, O_WRONLY | O_CREAT | O_EXCL, st.st_mode)) == -1) {
            SRPLG_LOG_ERR(srpds_name, "Opening \"%s\" failed (%s).", bck_path, strerror(errno));
            rc = SR_ERR_SYS;
            goto cleanup;
        }
        backup = 1;
        if (fchown(fd, st.st_uid, st.st_gid) == -1) {
            SRPLG_LOG_ERR(srpds_name, "Changing owner of \"%s\" failed (%s).", bck_path, strerror(errno));
            if ((errno == EACCES) || (errno == EPERM)) {
                rc = SR_ERR_UNAUTHORIZED;
            } else {
                rc = SR_ERR_INTERNAL;
            }
            goto cleanup;
        }

        /* close */
        close(fd);
        fd = -1;

        /* back up any existing file */
        if ((rc = srlyb_cp_path(srpds_name, bck_path, path))) {
            goto cleanup;
        }
    }

    /* open the file */
    if ((fd = srlyb_open(path, O_WRONLY | O_CREAT, perm)) == -1) {
        rc = srlyb_open_error(srpds_name, path);
        goto cleanup;
    }

    if (owner || group) {
        /* change the owner of the file */
        if ((rc = srlyb_chmodown(srpds_name, path, owner, group, 0))) {
            goto cleanup;
        }
    }

    /* print data */
    if (lyd_print_fd(fd, mod_data, LYD_LYB, LYD_PRINT_WITHSIBLINGS)) {
        srplyb_log_err_ly(srpds_name, LYD_CTX(mod_data));
        SRPLG_LOG_ERR(srpds_name, "Failed to store data into \"%s\".", path);
        rc = SR_ERR_INTERNAL;
        goto cleanup;
    }

cleanup:
    /* delete the backup file */
    if (backup && (unlink(bck_path) == -1)) {
        SRPLG_LOG_ERR(srpds_name, "Failed to remove backup \"%s\" (%s).", bck_path, strerror(errno));
        if (!rc) {
            rc = SR_ERR_SYS;
        }
    }

    if (fd > -1) {
        close(fd);
    }
    free(path);
    free(bck_path);
    return rc;
}

static int
srpds_lyb_init(const struct lys_module *mod, sr_datastore_t ds, const char *owner, const char *group, mode_t perm)
{
    int rc = SR_ERR_OK;
    struct lyd_node *root = NULL;
    char *path = NULL;

    assert(perm);

    if (ds == SR_DS_CANDIDATE) {
        /* no need to initialize anything */
        return rc;
{'fraction_non_alphanumeric': 0.1309883470004316, 'fraction_numerical': 0.005179110919292188, 'mean_word_length': 2.298576512455516, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '769739', 'n_tokens_mistral': 3424, 'n_tokens_neox': 3315, 'n_words': 851}