Blame src/lib/problem_api.c

Packit Service 8a8a03
/*
Packit Service 8a8a03
    Copyright (C) ABRT Team
Packit Service 8a8a03
    Copyright (C) RedHat inc.
Packit Service 8a8a03
Packit Service 8a8a03
    This program is free software; you can redistribute it and/or modify
Packit Service 8a8a03
    it under the terms of the GNU General Public License as published by
Packit Service 8a8a03
    the Free Software Foundation; either version 2 of the License, or
Packit Service 8a8a03
    (at your option) any later version.
Packit Service 8a8a03
Packit Service 8a8a03
    This program is distributed in the hope that it will be useful,
Packit Service 8a8a03
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8a8a03
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 8a8a03
    GNU General Public License for more details.
Packit Service 8a8a03
Packit Service 8a8a03
    You should have received a copy of the GNU General Public License along
Packit Service 8a8a03
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 8a8a03
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 8a8a03
*/
Packit Service 8a8a03
Packit Service 8a8a03
#include <glib.h>
Packit Service 8a8a03
#include <sys/time.h>
Packit Service 8a8a03
#include "problem_api.h"
Packit Service 8a8a03
Packit Service 8a8a03
/*
Packit Service 8a8a03
 * Goes through all problems and for problems accessible by caller_uid
Packit Service 8a8a03
 * calls callback. If callback returns non-0, returns that value.
Packit Service 8a8a03
 */
Packit Service 8a8a03
int for_each_problem_in_dir(const char *path,
Packit Service 8a8a03
                        uid_t caller_uid,
Packit Service 8a8a03
                        int (*callback)(struct dump_dir *dd, void *arg),
Packit Service 8a8a03
                        void *arg)
Packit Service 8a8a03
{
Packit Service 8a8a03
    DIR *dp = opendir(path);
Packit Service 8a8a03
    if (!dp)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        /* We don't want to yell if, say, $XDG_CACHE_DIR/abrt/spool doesn't exist */
Packit Service 8a8a03
        //perror_msg("Can't open directory '%s'", path);
Packit Service 8a8a03
        return 0;
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    int brk = 0;
Packit Service 8a8a03
    struct dirent *dent;
Packit Service 8a8a03
    while ((dent = readdir(dp)) != NULL)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        if (dot_or_dotdot(dent->d_name))
Packit Service 8a8a03
            continue; /* skip "." and ".." */
Packit Service 8a8a03
Packit Service 8a8a03
        char *full_name = concat_path_file(path, dent->d_name);
Packit Service 8a8a03
Packit Service 8a8a03
        struct dump_dir *dd = dd_opendir(full_name,   DD_OPEN_FD_ONLY
Packit Service 8a8a03
                                                    | DD_FAIL_QUIETLY_ENOENT
Packit Service 8a8a03
                                                    | DD_FAIL_QUIETLY_EACCES);
Packit Service 8a8a03
        if (dd == NULL)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            VERB2 perror_msg("can't open problem directory '%s'", full_name);
Packit Service 8a8a03
            free(full_name);
Packit Service 8a8a03
            continue;
Packit Service 8a8a03
        }
Packit Service 8a8a03
Packit Service 8a8a03
        if (caller_uid == -1 || dd_accessible_by_uid(dd, caller_uid))
Packit Service 8a8a03
        {
Packit Service 8a8a03
            /* Silently ignore *any* errors, not only EACCES.
Packit Service 8a8a03
             * We saw "lock file is locked by process PID" error
Packit Service 8a8a03
             * when we raced with wizard.
Packit Service 8a8a03
             */
Packit Service 8a8a03
            int sv_logmode = logmode;
Packit Service 8a8a03
            /* Silently ignore errors only in the silent log level. */
Packit Service 8a8a03
            logmode = g_verbose == 0 ? 0: sv_logmode;
Packit Service 8a8a03
            dd = dd_fdopendir(dd, DD_OPEN_READONLY | DD_DONT_WAIT_FOR_LOCK);
Packit Service 8a8a03
            logmode = sv_logmode;
Packit Service 8a8a03
            if (dd)
Packit Service 8a8a03
                brk = callback ? callback(dd, arg) : 0;
Packit Service 8a8a03
        }
Packit Service 8a8a03
Packit Service 8a8a03
        if (dd)
Packit Service 8a8a03
            dd_close(dd);
Packit Service 8a8a03
Packit Service 8a8a03
        free(full_name);
Packit Service 8a8a03
        if (brk)
Packit Service 8a8a03
            break;
Packit Service 8a8a03
    }
Packit Service 8a8a03
    closedir(dp);
Packit Service 8a8a03
Packit Service 8a8a03
    return brk;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
/* get_problem_dirs_for_uid and its helpers */
Packit Service 8a8a03
Packit Service 8a8a03
static int add_dirname_to_GList(struct dump_dir *dd, void *arg)
Packit Service 8a8a03
{
Packit Service 8a8a03
    if (!dir_has_correct_permissions(dd->dd_dirname, DD_PERM_DAEMONS))
Packit Service 8a8a03
    {
Packit Service 8a8a03
        log_warning("Ignoring '%s': invalid owner, group or mode", dd->dd_dirname);
Packit Service 8a8a03
        /*Do not break*/
Packit Service 8a8a03
        return 0;
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    GList **list = arg;
Packit Service 8a8a03
    *list = g_list_prepend(*list, xstrdup(dd->dd_dirname));
Packit Service 8a8a03
    return 0;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
GList *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
Packit Service 8a8a03
{
Packit Service 8a8a03
    GList *list = NULL;
Packit Service 8a8a03
    for_each_problem_in_dir(dump_location, uid, add_dirname_to_GList, &list);
Packit Service 8a8a03
    /*
Packit Service 8a8a03
     * Why reverse?
Packit Service 8a8a03
     * Because N*prepend+reverse is faster than N*append
Packit Service 8a8a03
     */
Packit Service 8a8a03
    return g_list_reverse(list);
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
/* get_problem_dirs_not_accessible_by_uid and its helpers */
Packit Service 8a8a03
struct add_dirname_to_GList_if_not_accessible_args
Packit Service 8a8a03
{
Packit Service 8a8a03
    uid_t uid;
Packit Service 8a8a03
    GList *list;
Packit Service 8a8a03
};
Packit Service 8a8a03
Packit Service 8a8a03
static int add_dirname_to_GList_if_not_accessible(struct dump_dir *dd, void *args)
Packit Service 8a8a03
{
Packit Service 8a8a03
    struct add_dirname_to_GList_if_not_accessible_args *param = (struct add_dirname_to_GList_if_not_accessible_args *)args;
Packit Service 8a8a03
    /* Append if not accessible */
Packit Service 8a8a03
    if (!dump_dir_accessible_by_uid(dd->dd_dirname, param->uid))
Packit Service 8a8a03
        param->list = g_list_prepend(param->list, xstrdup(dd->dd_dirname));
Packit Service 8a8a03
Packit Service 8a8a03
    return 0;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
GList *get_problem_dirs_not_accessible_by_uid(uid_t uid, const char *dump_location)
Packit Service 8a8a03
{
Packit Service 8a8a03
    struct add_dirname_to_GList_if_not_accessible_args args = {
Packit Service 8a8a03
        .uid = uid,
Packit Service 8a8a03
        .list = NULL,
Packit Service 8a8a03
    };
Packit Service 8a8a03
Packit Service 8a8a03
    for_each_problem_in_dir(dump_location, /*disable default uid check*/-1, add_dirname_to_GList_if_not_accessible, &args);
Packit Service 8a8a03
    return g_list_reverse(args.list);
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
Packit Service 8a8a03
/* get_problem_storages */
Packit Service 8a8a03
Packit Service 8a8a03
GList *get_problem_storages(void)
Packit Service 8a8a03
{
Packit Service 8a8a03
    GList *paths = NULL;
Packit Service 8a8a03
    load_abrt_conf();
Packit Service 8a8a03
    paths = g_list_append(paths, xstrdup(g_settings_dump_location));
Packit Service 8a8a03
    free_abrt_conf_data();
Packit Service 8a8a03
Packit Service 8a8a03
    return paths;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
int problem_dump_dir_is_complete(struct dump_dir *dd)
Packit Service 8a8a03
{
Packit Service 8a8a03
    return dd_exist(dd, FILENAME_COUNT);
Packit Service 8a8a03
}