<commit_before>/**
 * @file sysrepoctl.c
 * @author <NAME> <<EMAIL>>, <NAME> <<EMAIL>>,
 *         <NAME> <<EMAIL>>
 * @brief Sysrepo control tool (sysrepoctl) implementation.
 *
 * @copyright
 * Copyright 2016 Cisco Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <libyang/libyang.h>

#include "sr_common.h"
#include "client_library.h"

/**
 * @brief Macro to iterate via all references to the module identified by NAME and REVISION
 *        inside the given libyang context. Use with opening curly bracket '{'.
 *
 * @param CTX libyang context.
 * @param NAME Module name.
 * @param REVISION Revision date.
 * @param ITER Iterator (pointer to lys_module struct)
 */
#define MODULE_ITER(CTX, NAME, REVISION, ITER)  \
    for (uint32_t idx = 0; NULL != (ITER = ly_ctx_get_module_iter(CTX, &idx)); )       \
        if ((NULL != ITER->name) && (0 == strcmp(ITER->name, NAME)))                   \
            if ((NULL == REVISION) ||                                                  \
                ((ITER->rev_size > 0) && (0 == strcmp(ITER->rev[0].date, REVISION))))  \

/**
 * @brief Helper structure used for storing uid and gid of module's owner
 * and group respectively.
 */
typedef struct srctl_module_owner_s {
    uid_t owner;
    gid_t group;
} srctl_module_owner_t;

static char *srctl_schema_search_dir = SR_SCHEMA_SEARCH_DIR;
static char *srctl_data_search_dir = SR_DATA_SEARCH_DIR;
static bool custom_repository = false;
const char * const data_files_ext[] = { SR_STARTUP_FILE_EXT,
                                        SR_RUNNING_FILE_EXT,
                                        SR_STARTUP_FILE_EXT SR_LOCK_FILE_EXT,
                                        SR_RUNNING_FILE_EXT SR_LOCK_FILE_EXT,
                                        SR_PERSIST_FILE_EXT,
                                        SR_CANDIDATE_FILE_EXT SR_LOCK_FILE_EXT};


/**
 * @brief Connects to sysrepo and starts a session.
 */
static int
srctl_open_session(sr_conn_ctx_t **connection_p, sr_session_ctx_t **session_p)
{
    int rc = SR_ERR_OK;

    rc = sr_connect("sysrepoctl", SR_CONN_DEFAULT, connection_p);
    if (SR_ERR_OK == rc) {
        rc = sr_session_start(*connection_p, SR_DS_STARTUP, SR_SESS_DEFAULT, session_p);
    }
    return rc;
}

/**
 * @brief Reports (prints to stderr) the error stored within the session or given one.
 */
static void
srctl_report_error(sr_session_ctx_t *session, int rc)
{
    const sr_error_info_t *error = NULL;

    if (NULL == session) {
        fprintf(stderr, "Error: %s\n", sr_strerror(rc));
    } else {
        sr_get_last_error(session, &error);
        fprintf(stderr, "Error: %s\n", error->message);
    }
}

/**
 * @brief Prints the owner user and group ot the model installed in sysrepo.
 */
static void
srctl_print_module_owner(const char *module_name, char *buff)
{
    char file_name[PATH_MAX] = { 0, };
    struct stat info;
    int ret = 0;

    snprintf(file_name, PATH_MAX, "%s%s%s", srctl_data_search_dir, module_name, SR_STARTUP_FILE_EXT);

    ret = stat(file_name, &info);
    if (0 == ret) {
        struct passwd *pw = getpwuid(info.st_uid);
        struct group  *gr = getgrgid(info.st_gid);
        snprintf(buff, PATH_MAX, "%s:%s", pw->pw_name, gr->gr_name);
    } else {
        snprintf(buff, PATH_MAX, " ");
    }<commit_msg>fix for sysrepoctl crash when owner of schema file does not exist<commit_after>/**
 * @file sysrepoctl.c
 * @author <NAME> <<EMAIL>>, <NAME> <<EMAIL>>,
 *         <NAME> <<EMAIL>>
 * @brief Sysrepo control tool (sysrepoctl) implementation.
 *
 * @copyright
 * Copyright 2016 Cisco Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <libyang/libyang.h>

#include "sr_common.h"
#include "client_library.h"

/**
 * @brief Macro to iterate via all references to the module identified by NAME and REVISION
 *        inside the given libyang context. Use with opening curly bracket '{'.
 *
 * @param CTX libyang context.
 * @param NAME Module name.
 * @param REVISION Revision date.
 * @param ITER Iterator (pointer to lys_module struct)
 */
#define MODULE_ITER(CTX, NAME, REVISION, ITER)  \
    for (uint32_t idx = 0; NULL != (ITER = ly_ctx_get_module_iter(CTX, &idx)); )       \
        if ((NULL != ITER->name) && (0 == strcmp(ITER->name, NAME)))                   \
            if ((NULL == REVISION) ||                                                  \
                ((ITER->rev_size > 0) && (0 == strcmp(ITER->rev[0].date, REVISION))))  \

/**
 * @brief Helper structure used for storing uid and gid of module's owner
 * and group respectively.
 */
typedef struct srctl_module_owner_s {
    uid_t owner;
    gid_t group;
} srctl_module_owner_t;

static char *srctl_schema_search_dir = SR_SCHEMA_SEARCH_DIR;
static char *srctl_data_search_dir = SR_DATA_SEARCH_DIR;
static bool custom_repository = false;
const char * const data_files_ext[] = { SR_STARTUP_FILE_EXT,
                                        SR_RUNNING_FILE_EXT,
                                        SR_STARTUP_FILE_EXT SR_LOCK_FILE_EXT,
                                        SR_RUNNING_FILE_EXT SR_LOCK_FILE_EXT,
                                        SR_PERSIST_FILE_EXT,
                                        SR_CANDIDATE_FILE_EXT SR_LOCK_FILE_EXT};


/**
 * @brief Connects to sysrepo and starts a session.
 */
static int
srctl_open_session(sr_conn_ctx_t **connection_p, sr_session_ctx_t **session_p)
{
    int rc = SR_ERR_OK;

    rc = sr_connect("sysrepoctl", SR_CONN_DEFAULT, connection_p);
    if (SR_ERR_OK == rc) {
        rc = sr_session_start(*connection_p, SR_DS_STARTUP, SR_SESS_DEFAULT, session_p);
    }
    return rc;
}

/**
 * @brief Reports (prints to stderr) the error stored within the session or given one.
 */
static void
srctl_report_error(sr_session_ctx_t *session, int rc)
{
    const sr_error_info_t *error = NULL;

    if (NULL == session) {
        fprintf(stderr, "Error: %s\n", sr_strerror(rc));
    } else {
        sr_get_last_error(session, &error);
        fprintf(stderr, "Error: %s\n", error->message);
    }
}

/**
 * @brief Prints the owner user and group ot the model installed in sysrepo.
 */
static void
srctl_print_module_owner(const char *module_name, char *buff)
{
    char file_name[PATH_MAX] = { 0, };
    struct stat info;
    int ret = 0;

    snprintf(file_name, PATH_MAX, "%s%s%s", srctl_data_search_dir, module_name, SR_STARTUP_FILE_EXT);

    ret = stat(file_name, &info);
    if (0 == ret) {
        struct passwd *pw = getpwuid(info.st_uid);
        struct group  *gr = getgrgid(info.st_gid);
        if(pw && gr) {
            snprintf(buff, PATH_MAX, "%s:%s", pw->pw_name, gr->gr_name);
        } else {
            snprintf(buff, PATH_MAX, "%d:%d", info.st_uid, in.st_gid);
        }
    } else {
        snprintf(buff, PATH_MAX, " ");
    }
{'fraction_non_alphanumeric': 0.11325799003524122, 'fraction_numerical': 0.004374772147283996, 'mean_word_length': 2.7562756732085805, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5259327', 'n_tokens_mistral': 2733, 'n_tokens_neox': 2635, 'n_words': 761}