cleaned up some code, removed/improved few comments, better logging
[rxpd.git] / src / rxpd_file.c
blobca6155f090975b8ad9d33e2c2d28e048ae39c4f7
1 /*
2 rxpd_file.c - regex policy daemon
4 Copyright (C)
5 2007, Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "rxpd.h"
24 struct rxpd_file*
25 rxpd_file_new (struct rxpd_base* base, const char* filename)
27 char buf[4096];
28 struct rxpd_file* self = NULL;
30 while (*filename == '/')
31 ++filename;
33 if (!filename ||
34 strcspn(filename, RXPD_FILE_ILG_CHARS) != strlen (filename) ||
35 strstr (filename, "../") ||
36 strstr (filename, "/./") ||
37 strlen (filename) + strlen (base->basedir) > 4095)
39 rxpd_log (base, LOG_ERR, "illegal filename: '%s'\n", filename?filename:"");
40 return NULL;
43 strcpy (buf, base->basedir);
44 strcat (buf, filename);
45 filename = rxpd_strdup (buf);
47 self = rxpd_malloc (sizeof (struct rxpd_file));
48 self->filename = filename;
49 self->base = base;
50 pth_rwlock_init (&self->lock);
52 psplay_init (&self->node, filename + strlen (base->basedir));
53 llist_init (&self->rules);
55 psplay_insert (&base->files, &self->node);
57 rxpd_log (base, LOG_INFO, "new file: '%s'\n", filename);
58 return self;
61 void
62 rxpd_file_delete (struct rxpd_file* self)
64 if (self)
66 rxpd_file_rules_delete (self);
67 psplay_remove (&self->base->files, &self->node);
68 free ((void*)self->filename);
69 free (self);
73 struct rxpd_file*
74 rxpd_file_rules_delete (struct rxpd_file* self)
76 if (self)
78 pth_rwlock_acquire (&self->lock, PTH_RWLOCK_RW, FALSE, NULL);
79 LLIST_WHILE_HEAD (&self->rules, n)
81 struct rxpd_rule* node = (struct rxpd_rule*)n;
82 rxpd_rule_delete (node);
84 pth_rwlock_release (&self->lock);
86 return self;
89 int
90 rxpd_file_load (struct rxpd_file* self)
92 FILE* f = fopen (self->filename, "r");
93 if (f)
95 pth_rwlock_acquire (&self->lock, PTH_RWLOCK_RW, FALSE, NULL);
97 /* First purge old rules */
98 LLIST_WHILE_HEAD (&self->rules, n)
100 struct rxpd_rule* node = (struct rxpd_rule*)n;
101 rxpd_rule_delete (node);
104 // TODO test excess line length = error
105 char buf[4096];
107 rxpd_log (self->base, LOG_NOTICE, "loading '%s'\n", self->filename);
109 while (fgets (buf, 4096, f))
111 size_t last = strlen(buf);
112 if (buf[last-1] == '\n')
113 buf[last-1] = '\0';
115 struct rxpd_rule* rule;
116 rule = rxpd_rule_new (buf);
117 rxpd_log (self->base, LOG_DEBUG, "new rule '%s'\n", rule->string);
119 llist_insert_tail (&self->rules, &rule->node);
122 pth_rwlock_release (&self->lock);
123 fclose (f);
124 return 1;
126 else
128 rxpd_log (self->base, LOG_ERR, "failed loading '%s'\n", self->filename);
129 return 0;
135 rxpd_file_save (struct rxpd_file* self)
137 char* filename = strdupa (self->filename);
139 char* slash = filename;
141 while ((slash = strchr (slash+1, '/')))
143 *slash = '\0';
144 mkdir(filename, 0777);
145 *slash = '/';
148 FILE* f = fopen (filename, "w");
149 if (f)
151 pth_rwlock_acquire (&self->lock, PTH_RWLOCK_RD, FALSE, NULL);
153 LLIST_FOREACH (&self->rules, n)
155 struct rxpd_rule* node = (struct rxpd_rule*)n;
156 if (node->atime != (time_t)-1)
157 fprintf (f, "%ld:%s\n", node->atime, node->string);
158 else if (*node->string != '#')
159 fprintf (f, ":%s\n", node->string);
160 else
161 fprintf (f, "%s\n", node->string);
164 pth_rwlock_release (&self->lock);
165 fclose (f);
166 rxpd_log (self->base, LOG_NOTICE, "saved '%s'\n", filename);
167 return 1;
169 else
171 rxpd_log (self->base, LOG_ERR, "failed saving '%s'\n", filename);
172 return 0;
176 struct rxpd_file*
177 rxpd_file_dump (struct rxpd_file* self, struct rxpd_buffer* out)
179 if (self)
181 if (llist_is_empty (&self->rules))
182 rxpd_buffer_printf (out, "#OK:\n");
183 else
185 pth_rwlock_acquire (&self->lock, PTH_RWLOCK_RD, FALSE, NULL);
187 LLIST_FOREACH (&self->rules, n)
189 struct rxpd_rule* rule = (struct rxpd_rule*)n;
190 if (rule->atime != (time_t)-1)
191 rxpd_buffer_printf (out, "%ld:%s\n", rule->atime, rule->string);
192 else if (*rule->string != '#')
193 rxpd_buffer_printf (out, ":%s\n", rule->string);
194 else
195 rxpd_buffer_printf (out, "%s\n", rule->string);
197 pth_rwlock_release (&self->lock);
201 return self;
205 rxpd_file_cmp (const void* A, const void* B)
207 return strcmp (A, B);