Blame src/lib/problem_api.c

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