2 rxpd_file.c - regex policy daemon
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.
25 rxpd_file_new (struct rxpd_base
* base
, const char* filename
)
28 struct rxpd_file
* self
= NULL
;
30 while (*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
:"");
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
;
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
);
62 rxpd_file_delete (struct rxpd_file
* self
)
66 rxpd_file_rules_delete (self
);
67 psplay_remove (&self
->base
->files
, &self
->node
);
68 free ((void*)self
->filename
);
74 rxpd_file_rules_delete (struct rxpd_file
* 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
);
90 rxpd_file_load (struct rxpd_file
* self
)
92 FILE* f
= fopen (self
->filename
, "r");
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
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')
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
);
128 rxpd_log (self
->base
, LOG_ERR
, "failed loading '%s'\n", self
->filename
);
135 rxpd_file_save (struct rxpd_file
* self
)
137 char* filename
= strdupa (self
->filename
);
139 char* slash
= filename
;
141 while ((slash
= strchr (slash
+1, '/')))
144 mkdir(filename
, 0777);
148 FILE* f
= fopen (filename
, "w");
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
);
161 fprintf (f
, "%s\n", node
->string
);
164 pth_rwlock_release (&self
->lock
);
166 rxpd_log (self
->base
, LOG_NOTICE
, "saved '%s'\n", filename
);
171 rxpd_log (self
->base
, LOG_ERR
, "failed saving '%s'\n", filename
);
177 rxpd_file_dump (struct rxpd_file
* self
, struct rxpd_buffer
* out
)
181 if (llist_is_empty (&self
->rules
))
182 rxpd_buffer_printf (out
, "#OK:\n");
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
);
195 rxpd_buffer_printf (out
, "%s\n", rule
->string
);
197 pth_rwlock_release (&self
->lock
);
205 rxpd_file_cmp (const void* A
, const void* B
)
207 return strcmp (A
, B
);