update copyright year
[claws.git] / src / plugins / libravatar / libravatar_cache.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2014-2015 Ricardo Mones and the Claws Mail Team
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include "config.h"
20
21 #include <sys/stat.h>
22
23 #include "libravatar_cache.h"
24 #include "file-utils.h"
25 #include "utils.h"
26
27 gchar *libravatar_cache_init(const char *dirs[], gint start, gint end)
28 {
29         gchar *subdir, *rootdir;
30         int i;
31
32         rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
33                                 LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
34                                 NULL);
35         if (!is_dir_exist(rootdir)) {
36                 if (make_dir(rootdir) < 0) {
37                         g_warning("cannot create root directory '%s'", rootdir);
38                         g_free(rootdir);
39                         return NULL;
40                 }
41         }
42         for (i = start; i <= end; ++i) {
43                 subdir = g_strconcat(rootdir, dirs[i], NULL);
44                 if (!is_dir_exist(subdir)) {
45                         if (make_dir(subdir) < 0) {
46                                 g_warning("cannot create directory '%s'", subdir);
47                                 g_free(subdir);
48                                 g_free(rootdir);
49                                 return NULL;
50                         }
51                 }
52                 g_free(subdir);
53         }
54
55         return rootdir;
56 }
57
58 static void cache_stat_item(gpointer filename, gpointer data)
59 {
60         GStatBuf                s;
61         const gchar             *fname = (const gchar *) filename;
62         AvatarCacheStats        *stats = (AvatarCacheStats *) data;
63
64         if (0 == g_stat(fname, &s)) {
65                 if (S_ISDIR(s.st_mode) != 0) {
66                         stats->dirs++;
67                 }
68                 else if (S_ISREG(s.st_mode) != 0) {
69                         stats->files++;
70                         stats->bytes += s.st_size;
71                 }
72                 else {
73                         stats->others++;
74                 }
75         }
76         else {
77                 g_warning("cannot stat '%s'", fname);
78                 stats->errors++;
79         }
80 }
81
82 static void cache_items_deep_first(const gchar *dir, GSList **items, guint *failed)
83 {
84         const gchar     *d;
85         GDir            *dp;
86         GError          *error = NULL;
87
88         cm_return_if_fail(dir != NULL);
89
90         if ((dp = g_dir_open(dir, 0, &error)) == NULL) {
91                 g_warning("cannot open directory '%s': %s (%d)",
92                                 dir, error->message, error->code);
93                 g_error_free(error);
94                 (*failed)++;
95                 return;
96         }
97         while ((d = g_dir_read_name(dp)) != NULL) {
98                 if (strcmp(d, ".") == 0 || strcmp(d, "..") == 0) {
99                         continue;
100                 }
101                 else {
102                         const gchar *fname = g_strconcat(dir, G_DIR_SEPARATOR_S, d, NULL);
103                         if (is_dir_exist(fname))
104                                 cache_items_deep_first(fname, items, failed);
105                         *items = g_slist_append(*items, (gpointer) fname);
106                 }
107         }
108         g_dir_close(dp);
109 }
110
111 AvatarCacheStats *libravatar_cache_stats()
112 {
113         gchar *rootdir;
114         AvatarCacheStats *stats;
115         GSList *items = NULL;
116         guint errors = 0;
117
118         stats = g_new0(AvatarCacheStats, 1);
119         cm_return_val_if_fail(stats != NULL, NULL);
120
121         rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
122                                 LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
123                                 NULL);
124         cache_items_deep_first(rootdir, &items, &errors);
125         stats->errors += errors;
126         g_slist_foreach(items, (GFunc) cache_stat_item, (gpointer) stats);
127         slist_free_strings_full(items);
128         g_free(rootdir);
129
130         return stats;
131 }
132
133 static void cache_delete_item(gpointer filename, gpointer errors)
134 {
135         const gchar *fname = (const gchar *) filename;
136         AvatarCleanupResult *acr = (AvatarCleanupResult *) errors;
137
138         if (!is_dir_exist(fname)) {
139                 if (claws_unlink(fname) < 0) {
140                         g_warning("couldn't delete file '%s'", fname);
141                         (acr->e_unlink)++;
142                 }
143                 else {
144                         (acr->removed)++;
145                 }
146         }
147 }
148
149 AvatarCleanupResult *libravatar_cache_clean()
150 {
151         gchar *rootdir;
152         AvatarCleanupResult *acr;
153         GSList *items = NULL;
154         guint errors = 0;
155
156         acr = g_new0(AvatarCleanupResult, 1);
157         cm_return_val_if_fail(acr != NULL, NULL);
158
159         rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
160                                 LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
161                                 NULL);
162         cache_items_deep_first(rootdir, &items, &errors);
163         acr->e_stat = (gint) errors;
164
165         g_slist_foreach(items, (GFunc) cache_delete_item, (gpointer) acr);
166
167         slist_free_strings_full(items);
168         g_free(rootdir);
169
170         return acr;
171 }