WIP: pth, cleanup, transistion mostly done
[rxpd] / src / rxpd_file.c
1 /*
2     rxpd_file.c - regex policy daemon
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
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.
11
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.
16
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.
20 */
21
22 #include "rxpd.h"
23
24 struct rxpd_file*
25 rxpd_file_new (struct rxpd_base* base, const char* filename)
26 {
27   char buf[4096];
28   struct rxpd_file* self = NULL;
29
30   if (!filename ||
31       strcspn(filename, RXPD_FILE_ILG_CHARS) != strlen (filename) ||
32       strlen (filename) + strlen (base->basedir) > 4095)
33     {
34       rxpd_log (base, LOG_ERR, "illegal filename: '%s'\n", filename?filename:"");
35       return NULL;
36     }
37
38   strcpy (buf, base->basedir);
39   strcat (buf, filename);
40   filename = rxpd_strdup (buf);
41
42   self = rxpd_malloc (sizeof (struct rxpd_file));
43   self->filename = filename;
44   self->base = base;
45   const char* basename = strrchr (filename, '/');
46   if (basename)
47     ++basename;
48   else
49     basename = filename;
50   psplay_init (&self->node, basename);
51   llist_init (&self->rules);
52
53   psplay_insert (&base->files, &self->node);
54
55   rxpd_log (base, LOG_INFO, "new file: '%s'\n", filename);
56   return self;
57 }
58
59 void
60 rxpd_file_delete (struct rxpd_file* self)
61 {
62   if (self)
63     {
64       rxpd_file_rules_delete (self);
65       psplay_remove (&self->base->files, &self->node);
66       free ((void*)self->filename);
67       free (self);
68     }
69 }
70
71 struct rxpd_file*
72 rxpd_file_rules_delete (struct rxpd_file* self)
73 {
74   if (self)
75     {
76       LLIST_WHILE_HEAD (&self->rules, n)
77         {
78           struct rxpd_rule* node = (struct rxpd_rule*)n;
79           rxpd_rule_delete (node);
80         }
81     }
82   return self;
83 }
84
85 int
86 rxpd_file_load (struct rxpd_file* self)
87 {
88   FILE* f = fopen (self->filename, "r");
89   // TODO error handling
90   if (f)
91     {
92       /* First purge old rules */
93       LLIST_WHILE_HEAD (&self->rules, n)
94         {
95           struct rxpd_rule* node = (struct rxpd_rule*)n;
96           rxpd_rule_delete (node);
97         }
98
99       // TODO test excess line length = error
100       char buf[4096];
101
102       rxpd_log (self->base, LOG_NOTICE, "loading '%s'\n", self->filename);
103
104       while (fgets (buf, 4096, f))
105         {
106           size_t last = strlen(buf);
107           if (buf[last-1] == '\n')
108             buf[last-1] = '\0';
109
110           struct rxpd_rule* rule;
111           rule = rxpd_rule_new (buf);
112           if (!rule)
113             abort();
114
115           rxpd_log (self->base, LOG_DEBUG, "new rule '%s'\n", rule->string);
116
117           llist_insert_tail (&self->rules, &rule->node);
118         }
119
120       fclose (f);
121       return 1;
122     }
123   else
124     {
125       rxpd_log (self->base, LOG_ERR, "failed loading '%s'\n", self->filename);
126       return 0;
127     }
128 }
129
130 int
131 rxpd_file_save (struct rxpd_file* self)
132 {
133   FILE* f = fopen (self->filename, "w");
134   // TODO error handling
135   if (f)
136     {
137       LLIST_FOREACH (&self->rules, n)
138         {
139           struct rxpd_rule* node = (struct rxpd_rule*)n;
140           if (node->atime != (time_t)-1)
141             fprintf (f, "%ld:%s\n", node->atime, node->string);
142           else if (*node->string != '#')
143             fprintf (f, ":%s\n", node->string);
144           else
145             fprintf (f, "%s\n", node->string);
146         }
147
148       fclose (f);
149       rxpd_log (self->base, LOG_NOTICE, "saved '%s'\n", self->filename);
150       return 1;
151     }
152   else
153     {
154       rxpd_log (self->base, LOG_ERR, "failed saving '%s'\n", self->filename);
155       return 0;
156     }
157 }
158
159 int
160 rxpd_file_cmp (const void* A, const void* B)
161 {
162   return strcmp (A, B);
163 }
164
165