2
* jabberd - Jabber Open Source Server
3
* Copyright (c) 2002-2003 Jeremie Miller, Thomas Muldowney,
4
* Ryan Eatmon, Robert Norris
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
21
/** @file sm/storage_fs.c
22
* @brief filesystem storage module
23
* @author Robert Norris
24
* $Date: 2005/01/19 18:29:38 $
25
* $Revision: 1.8.2.8 $
29
* WARNING: this uses lots of static buffers, and doesn't do all the bounds
30
* checking that it should. it should not be used for anything other than
33
* !!! fix everything that makes this a problem
44
# define NAMELEN(dirent) strlen((dirent)->d_name)
46
# define dirent direct
47
# define NAMELEN(dirent) (dirent)->d_namelen
48
# ifdef HAVE_SYS_NDIR_H
49
# include <sys/ndir.h>
51
# ifdef HAVE_SYS_DIR_H
59
/** internal structure, holds our data */
60
typedef struct drvdata_st {
64
static st_ret_t _st_fs_add_type(st_driver_t drv, const char *type) {
65
drvdata_t data = (drvdata_t) drv->private;
70
snprintf(path, 1024, "%s/%s", data->path, type);
71
ret = stat(path, &sbuf);
74
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat '%s': %s", path, strerror(errno));
78
log_debug(ZONE, "creating new type dir '%s'", path);
80
ret = mkdir(path, 0755);
82
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't create directory '%s': %s", path, strerror(errno));
90
static st_ret_t _st_fs_put(st_driver_t drv, const char *type, const char *owner, os_t os) {
91
drvdata_t data = (drvdata_t) drv->private;
104
if(os_count(os) == 0)
107
snprintf(path, 1024, "%s/%s", data->path, type);
108
ret = stat(path, &sbuf);
110
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat '%s': %s", path, strerror(errno));
114
snprintf(path, 1024, "%s/%s/%s", data->path, type, owner);
115
ret = stat(path, &sbuf);
117
if(errno != ENOENT) {
118
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat '%s': %s", path, strerror(errno));
122
log_debug(ZONE, "creating new collection dir '%s'", path);
124
ret = mkdir(path, 0755);
126
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't create directory '%s': %s", path, strerror(errno));
133
if(os_iter_first(os))
135
for(file++; file < 999999; file++) {
136
snprintf(path, 1024, "%s/%s/%s/%d", data->path, type, owner, file);
138
ret = stat(path, &sbuf);
139
if(ret < 0 && errno == ENOENT)
143
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat '%s': %s", path, strerror(errno));
148
log_debug(ZONE, "will store object to %s", path);
150
f = fopen(path, "w");
152
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't open '%s' for writing: %s", path, strerror(errno));
156
o = os_iter_object(os);
158
if(os_object_iter_first(o))
160
os_object_iter_get(o, &key, &val, &ot);
162
log_debug(ZONE, "writing field %s type %d", key, ot);
165
case os_type_BOOLEAN:
166
fprintf(f, "%s %d %d\n", key, ot, (int) val == 0 ? 0 : 1);
169
case os_type_INTEGER:
170
fprintf(f, "%s %d %d\n", key, ot, (int) val);
174
fprintf(f, "%s %d %s\n", key, ot, (char *) val);
178
nad_print((nad_t) val, 0, &xml, &len);
179
fprintf(f, "%s %d %.*s\n", key, ot, len, xml);
182
case os_type_UNKNOWN:
186
} while(os_object_iter_next(o));
190
} while(os_iter_next(os));
195
static st_ret_t _st_fs_get(st_driver_t drv, const char *type, const char *owner, const char *filter, os_t *os) {
196
drvdata_t data = (drvdata_t) drv->private;
197
char path[1024], file[1024];
201
struct dirent *dirent;
203
char buf[4096], *otc, *val, *c;
210
snprintf(path, 1024, "%s/%s/%s", data->path, type, owner);
211
ret = stat(path, &sbuf);
215
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat '%s': %s", path, strerror(errno));
221
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't open directory '%s': %s", path, strerror(errno));
228
while((dirent = readdir(dir)) != NULL) {
229
if(!(isdigit(dirent->d_name[0])))
232
snprintf(file, 1024, "%s/%s", path, dirent->d_name);
233
f = fopen(file, "r");
235
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't open '%s' for reading: %s", path, strerror(errno));
241
o = os_object_new(*os);
243
while(fgets(buf, 4096, f) != NULL) {
244
otc = strchr(buf, ' ');
247
val = strchr(otc, ' ');
250
ot = (os_type_t) atoi(otc);
253
case os_type_BOOLEAN:
254
case os_type_INTEGER:
256
os_object_put(o, buf, &i, ot);
261
c = strchr(val, '\n');
262
if(c != NULL) *c = '\0';
263
os_object_put(o, buf, val, ot);
268
nad = nad_parse(drv->st->sm->router->nad_cache, val, 0);
270
log_write(drv->st->sm->log, LOG_ERR, "fs: unable to parse stored XML; type=%s, owner=%s", type, owner);
276
os_object_put(o, buf, nad, ot);
281
case os_type_UNKNOWN:
287
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't read from '%s': %s", path, strerror(errno));
300
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't read from directory '%s': %s", path, strerror(errno));
308
sf = storage_filter(filter);
310
if(os_iter_first(*os))
312
o = os_iter_object(*os);
313
if(!storage_match(sf, o, *os))
315
} while(os_iter_next(*os));
317
if(sf != NULL) pool_free(sf->p);
322
static st_ret_t _st_fs_delete(st_driver_t drv, const char *type, const char *owner, const char *filter) {
323
drvdata_t data = (drvdata_t) drv->private;
324
char path[1024], file[1024];
329
struct dirent *dirent;
331
char buf[4096], *otc, *val, *c;
338
snprintf(path, 1024, "%s/%s/%s", data->path, type, owner);
339
ret = stat(path, &sbuf);
343
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat '%s': %s", path, strerror(errno));
349
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't open directory '%s': %s", path, strerror(errno));
355
sf = storage_filter(filter);
358
while((dirent = readdir(dir)) != NULL) {
359
if(!(isdigit(dirent->d_name[0])))
362
snprintf(file, 1024, "%s/%s", path, dirent->d_name);
363
f = fopen(file, "r");
365
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't open '%s' for reading: %s", path, strerror(errno));
371
o = os_object_new(os);
373
while(fgets(buf, 4096, f) != NULL) {
374
otc = strchr(buf, ' ');
377
val = strchr(otc, ' ');
380
ot = (os_type_t) atoi(otc);
383
case os_type_BOOLEAN:
384
case os_type_INTEGER:
386
os_object_put(o, buf, &i, ot);
391
c = strchr(val, '\n');
392
if(c != NULL) *c = '\0';
393
os_object_put(o, buf, val, ot);
398
nad = nad_parse(drv->st->sm->router->nad_cache, val, 0);
400
log_write(drv->st->sm->log, LOG_ERR, "fs: unable to parse stored XML; type=%s, owner=%s", type, owner);
402
os_object_put(o, buf, nad, ot);
408
case os_type_UNKNOWN:
414
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't read from '%s': %s", path, strerror(errno));
423
if(storage_match(sf, o, os)) {
426
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't unlink '%s': %s", path, strerror(errno));
427
if(sf != NULL) pool_free(sf->p);
438
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't read from directory '%s': %s", path, strerror(errno));
444
if(sf != NULL) pool_free(sf->p);
453
static st_ret_t _st_fs_replace(st_driver_t drv, const char *type, const char *owner, const char *filter, os_t os) {
456
ret = _st_fs_delete(drv, type, owner, filter);
457
if(ret == st_SUCCESS || ret == st_NOTFOUND)
458
ret = _st_fs_put(drv, type, owner, os);
463
static void _st_fs_free(st_driver_t drv) {
464
drvdata_t data = (drvdata_t) drv->private;
469
st_ret_t st_fs_init(st_driver_t drv) {
475
path = config_get_one(drv->st->sm->config, "storage.fs.path", 0);
477
log_write(drv->st->sm->log, LOG_ERR, "fs: no path specified in config file");
481
ret = stat(path, &sbuf);
483
log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't stat path '%s': %s", path, strerror(errno));
487
data = (drvdata_t) malloc(sizeof(struct drvdata_st));
488
memset(data, 0, sizeof(struct drvdata_st));
492
drv->private = (void *) data;
494
drv->add_type = _st_fs_add_type;
495
drv->put = _st_fs_put;
496
drv->get = _st_fs_get;
497
drv->delete = _st_fs_delete;
498
drv->replace = _st_fs_replace;
499
drv->free = _st_fs_free;
501
log_write(drv->st->sm->log, LOG_WARNING, "fs: the filesystem storage driver should only be used for testing!");