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 <sys/stat.h>
20
21 #include "libravatar_cache.h"
22 #include "file-utils.h"
23 #include "utils.h"
24
libravatar_cache_init(const char * dirs[],gint start,gint end)25 gchar *libravatar_cache_init(const char *dirs[], gint start, gint end)
26 {
27 gchar *subdir, *rootdir;
28 int i;
29
30 rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
31 LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
32 NULL);
33 if (!is_dir_exist(rootdir)) {
34 if (make_dir(rootdir) < 0) {
35 g_warning("cannot create root directory '%s'", rootdir);
36 g_free(rootdir);
37 return NULL;
38 }
39 }
40 for (i = start; i <= end; ++i) {
41 subdir = g_strconcat(rootdir, dirs[i], NULL);
42 if (!is_dir_exist(subdir)) {
43 if (make_dir(subdir) < 0) {
44 g_warning("cannot create directory '%s'", subdir);
45 g_free(subdir);
46 g_free(rootdir);
47 return NULL;
48 }
49 }
50 g_free(subdir);
51 }
52
53 return rootdir;
54 }
55
cache_stat_item(gpointer filename,gpointer data)56 static void cache_stat_item(gpointer filename, gpointer data)
57 {
58 GStatBuf s;
59 const gchar *fname = (const gchar *) filename;
60 AvatarCacheStats *stats = (AvatarCacheStats *) data;
61
62 if (0 == g_stat(fname, &s)) {
63 if (S_ISDIR(s.st_mode) != 0) {
64 stats->dirs++;
65 }
66 else if (S_ISREG(s.st_mode) != 0) {
67 stats->files++;
68 stats->bytes += s.st_size;
69 }
70 else {
71 stats->others++;
72 }
73 }
74 else {
75 g_warning("cannot stat '%s'", fname);
76 stats->errors++;
77 }
78 }
79
cache_items_deep_first(const gchar * dir,GSList ** items,guint * failed)80 static void cache_items_deep_first(const gchar *dir, GSList **items, guint *failed)
81 {
82 const gchar *d;
83 GDir *dp;
84 GError *error = NULL;
85
86 cm_return_if_fail(dir != NULL);
87
88 if ((dp = g_dir_open(dir, 0, &error)) == NULL) {
89 g_warning("cannot open directory '%s': %s (%d)",
90 dir, error->message, error->code);
91 g_error_free(error);
92 (*failed)++;
93 return;
94 }
95 while ((d = g_dir_read_name(dp)) != NULL) {
96 if (strcmp(d, ".") == 0 || strcmp(d, "..") == 0) {
97 continue;
98 }
99 else {
100 const gchar *fname = g_strconcat(dir, G_DIR_SEPARATOR_S, d, NULL);
101 if (is_dir_exist(fname))
102 cache_items_deep_first(fname, items, failed);
103 *items = g_slist_append(*items, (gpointer) fname);
104 }
105 }
106 g_dir_close(dp);
107 }
108
libravatar_cache_stats()109 AvatarCacheStats *libravatar_cache_stats()
110 {
111 gchar *rootdir;
112 AvatarCacheStats *stats;
113 GSList *items = NULL;
114 guint errors = 0;
115
116 stats = g_new0(AvatarCacheStats, 1);
117 cm_return_val_if_fail(stats != NULL, NULL);
118
119 rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
120 LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
121 NULL);
122 cache_items_deep_first(rootdir, &items, &errors);
123 stats->errors += errors;
124 g_slist_foreach(items, (GFunc) cache_stat_item, (gpointer) stats);
125 slist_free_strings_full(items);
126 g_free(rootdir);
127
128 return stats;
129 }
130
cache_delete_item(gpointer filename,gpointer errors)131 static void cache_delete_item(gpointer filename, gpointer errors)
132 {
133 const gchar *fname = (const gchar *) filename;
134 AvatarCleanupResult *acr = (AvatarCleanupResult *) errors;
135
136 if (!is_dir_exist(fname)) {
137 if (claws_unlink(fname) < 0) {
138 g_warning("couldn't delete file '%s'", fname);
139 (acr->e_unlink)++;
140 }
141 else {
142 (acr->removed)++;
143 }
144 }
145 }
146
libravatar_cache_clean()147 AvatarCleanupResult *libravatar_cache_clean()
148 {
149 gchar *rootdir;
150 AvatarCleanupResult *acr;
151 GSList *items = NULL;
152 guint errors = 0;
153
154 acr = g_new0(AvatarCleanupResult, 1);
155 cm_return_val_if_fail(acr != NULL, NULL);
156
157 rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
158 LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
159 NULL);
160 cache_items_deep_first(rootdir, &items, &errors);
161 acr->e_stat = (gint) errors;
162
163 g_slist_foreach(items, (GFunc) cache_delete_item, (gpointer) acr);
164
165 slist_free_strings_full(items);
166 g_free(rootdir);
167
168 return acr;
169 }
170