summaryrefslogtreecommitdiffstats
path: root/src/Hooks/hooklib.cpp
blob: a722ef5f3f2c7f1b7b736b3423c823fea38090f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
    Copyright (C) 2009	RedHat inc.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "abrtlib.h"
#include "hooklib.h"
#include "DebugDump.h"
#include <sys/statvfs.h>

using namespace std;

void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore)
{
    FILE *fp = fopen(CONF_DIR"/abrt.conf", "r");
    if (!fp)
        return;

    char line[256];
    while (1)
    {
        if (fgets(line, sizeof(line), fp) == NULL)
        {
            fclose(fp);
            if (additional_conf)
            {
                /* Next .conf file plz */
                fp = fopen(additional_conf, "r");
                if (fp)
                {
                    additional_conf = NULL;
                    continue;
                }
            }
            break;
        }

        strchrnul(line, '\n')[0] = '\0';
        const char *p = skip_whitespace(line);
#undef DIRECTIVE
#define DIRECTIVE "MaxCrashReportsSize"
        if (setting_MaxCrashReportsSize && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)
        {
            p = skip_whitespace(p + sizeof(DIRECTIVE)-1);
            if (*p != '=')
                continue;
            p = skip_whitespace(p + 1);
            if (isdigit(*p))
            {
                /* x1.25: go a bit up, so that usual in-daemon trimming
                 * kicks in first, and we don't "fight" with it. */
                *setting_MaxCrashReportsSize = (unsigned long)xatou(p) * 5 / 4;
            }
            continue;
        }
#undef DIRECTIVE
#define DIRECTIVE "MakeCompatCore"
        if (setting_MakeCompatCore && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)
        {
            p = skip_whitespace(p + sizeof(DIRECTIVE)-1);
            if (*p != '=')
                continue;
            p = skip_whitespace(p + 1);
            *setting_MakeCompatCore = string_to_bool(p);
            continue;
        }
#undef DIRECTIVE
        /* add more 'if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)' here... */
    }
}

void check_free_space(unsigned setting_MaxCrashReportsSize)
{
    struct statvfs vfs;
    if (statvfs(DEBUG_DUMPS_DIR, &vfs) != 0)
    {
        perror_msg_and_die("statvfs('%s')", DEBUG_DUMPS_DIR);
    }

    /* Check that at least MaxCrashReportsSize/4 MBs are free */

    /* fs_free_mb_x4 ~= vfs.f_bfree * vfs.f_bsize * 4, expressed in MBytes.
     * Need to neither overflow nor round f_bfree down too much. */
    unsigned long fs_free_mb_x4 = ((unsigned long long)vfs.f_bfree / (1024/4)) * vfs.f_bsize / 1024;
    if (fs_free_mb_x4 < setting_MaxCrashReportsSize)
    {
        error_msg_and_die("aborting dump: only %luMiB is available on %s\n", fs_free_mb_x4 / 4, DEBUG_DUMPS_DIR);
    }
}

/* rhbz#539551: "abrt going crazy when crashing process is respawned".
 * Check total size of dump dir, if it overflows,
 * delete oldest/biggest dumps.
 */
void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path)
{
    int count = 10;
    string worst_dir;
    while (--count >= 0)
    {
        const char *base_dirname = strrchr(exclude_path, '/') + 1; /* never NULL */
        /* We exclude our own dump from candidates for deletion (3rd param): */
        double dirsize = get_dirsize_find_largest_dir(DEBUG_DUMPS_DIR, &worst_dir, base_dirname);
        if (dirsize / (1024*1024) < setting_MaxCrashReportsSize || worst_dir == "")
            break;
        log("size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, setting_MaxCrashReportsSize, worst_dir.c_str());
        delete_debug_dump_dir(concat_path_file(DEBUG_DUMPS_DIR, worst_dir.c_str()).c_str());
        worst_dir = "";
    }
}