storage_cdb.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:23k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 2003 Mihai RUSU (dizzy@rdsnet.ro)
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #include "common/setup_before.h"
  19. #include <stdio.h>
  20. #ifdef HAVE_STDDEF_H
  21. # include <stddef.h>
  22. #else
  23. # ifndef NULL
  24. #  define NULL ((void *)0)
  25. # endif
  26. #endif
  27. #ifdef STDC_HEADERS
  28. # include <stdlib.h>
  29. #else
  30. # ifdef HAVE_MALLOC_H
  31. #  include <malloc.h>
  32. # endif
  33. #endif
  34. #ifdef HAVE_STRING_H
  35. # include <string.h>
  36. #else
  37. # ifdef HAVE_STRINGS_H
  38. #  include <strings.h>
  39. # endif
  40. #endif
  41. #include "compat/strchr.h"
  42. #include "compat/strdup.h"
  43. #include "compat/strcasecmp.h"
  44. #include "compat/strncasecmp.h"
  45. #include <ctype.h>
  46. #ifdef HAVE_LIMITS_H
  47. # include <limits.h>
  48. #endif
  49. #include "compat/char_bit.h"
  50. #ifdef TIME_WITH_SYS_TIME
  51. # include <sys/time.h>
  52. # include <time.h>
  53. #else
  54. # ifdef HAVE_SYS_TIME_H
  55. #  include <sys/time.h>
  56. # else
  57. #  include <time.h>
  58. # endif
  59. #endif
  60. #include <errno.h>
  61. #include "compat/strerror.h"
  62. #ifdef HAVE_SYS_TYPES_H
  63. # include <sys/types.h>
  64. #endif
  65. #ifdef HAVE_UNISTD_H
  66. # include <unistd.h>
  67. #else
  68. # ifdef WIN32
  69. #  include <io.h>
  70. # endif
  71. #endif
  72. #include "compat/pdir.h"
  73. #include "common/eventlog.h"
  74. #include "prefs.h"
  75. #include "common/util.h"
  76. #include "common/field_sizes.h"
  77. #include "common/bnethash.h"
  78. #include "common/introtate.h"
  79. #define CLAN_INTERNAL_ACCESS
  80. #define ACCOUNT_INTERNAL_ACCESS
  81. #include "account.h"
  82. #include "common/hashtable.h"
  83. #include "storage.h"
  84. #include "common/list.h"
  85. #include "connection.h"
  86. #include "watch.h"
  87. #include "clan.h"
  88. #undef ACCOUNT_INTERNAL_ACCESS
  89. #undef CLAN_INTERNAL_ACCESS
  90. #include "common/tag.h"
  91. #ifdef HAVE_FCNTL_H
  92. # include <fcntl.h>
  93. #else
  94. # ifdef HAVE_SYS_FILE_H
  95. #  include <sys/file.h>
  96. # endif
  97. #endif
  98. #include "tinycdb/cdb.h"
  99. #include "common/setup_after.h"
  100. /* cdb storage API functions */
  101. static int cdbs_init(const char *);
  102. static int cdbs_close(void);
  103. static t_storage_info * cdb_create_account(char const *);
  104. static t_storage_info * cdb_get_defacct(void);
  105. static int cdb_free_info(t_storage_info *);
  106. static int cdb_read_attrs(t_storage_info *, t_read_attr_func, void *);
  107. static void * cdb_read_attr(t_storage_info *, const char *);
  108. static int cdb_write_attrs(t_storage_info *, void *);
  109. static int cdb_read_accounts(t_read_accounts_func, void *);
  110. static void * cdb_read_account(t_read_account_func, const char *);
  111. static int cdb_cmp_info(t_storage_info *, t_storage_info *);
  112. static const char * cdb_escape_key(const char *);
  113. static int cdb_load_clans(t_load_clans_func);
  114. static int cdb_write_clan(void *);
  115. static int cdb_remove_clan(int);
  116. static int cdb_remove_clanmember(int);
  117. /* storage struct populated with the functions above */
  118. t_storage storage_cdb = {
  119.     cdbs_init,
  120.     cdbs_close,
  121.     cdb_create_account,
  122.     cdb_get_defacct,
  123.     cdb_free_info,
  124.     cdb_read_attrs,
  125.     cdb_write_attrs,
  126.     cdb_read_attr,
  127.     cdb_read_accounts,
  128.     cdb_read_account,
  129.     cdb_cmp_info,
  130.     cdb_escape_key,
  131.     cdb_load_clans,
  132.     cdb_write_clan,
  133.     cdb_remove_clan,
  134.     cdb_remove_clanmember
  135. };
  136. /* start of actual cdb file storage code */
  137. static const char *cdbdir = NULL;
  138. static const char *clansdir = NULL;
  139. static const char *defacct = NULL;
  140. //#define CDB_ON_DEMAND 1
  141. static int cdbs_init(const char *path)
  142. {
  143.     char *tok, *copy, *tmp, *p;
  144.     const char *dir = NULL;
  145.     const char *clan = NULL;
  146.     const char *def = NULL;
  147.     if (path == NULL || path[0] == '') {
  148.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL or empty path");
  149.         return -1;
  150.     }
  151.     if ((copy = strdup(path)) == NULL) {
  152.         eventlog(eventlog_level_error, __FUNCTION__, "could not duplicate path");
  153.         return -1;
  154.     }
  155.     tmp = copy;
  156.     while((tok = strtok(tmp, ";")) != NULL) {
  157.         tmp = NULL;
  158.         if ((p = strchr(tok, '=')) == NULL) {
  159.             eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path, no '=' present in token");
  160.             free((void*)copy);
  161.             return -1;
  162.         }
  163.         *p = '';
  164.         if (strcasecmp(tok, "dir") == 0)
  165.             dir = p + 1;
  166.         else if (strcasecmp(tok, "clan") == 0)
  167.         clan = p + 1;
  168.         else if (strcasecmp(tok, "default") == 0)
  169.             def = p + 1;
  170.         else eventlog(eventlog_level_warn, __FUNCTION__, "unknown token in storage_path : '%s'", tok);
  171.     }
  172.     if (def == NULL || clan ==NULL || dir == NULL) {
  173.         eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path line for cdb file module (doesnt have a 'dir', a 'clan' and a 'default' token)");
  174.         free((void*)copy);
  175.         return -1;
  176.     }
  177.     if (cdbdir) cdbs_close();
  178.     if ((cdbdir = strdup(dir)) == NULL) {
  179.         eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store cdb accounts dir");
  180.         free((void*)copy);
  181.         return -1;
  182.     }
  183.     if ((clansdir = strdup(clan)) == NULL) {
  184. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store clans dir");
  185. free((void*)copy);
  186. return -1;
  187.     }
  188.     if ((defacct = strdup(def)) == NULL) {
  189.         eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store default cdb account path");
  190.         free((void*)cdbdir); cdbdir = NULL;
  191.         free((void*)copy);
  192.         return -1;
  193.     }
  194.     free((void*)copy);
  195.     return 0;
  196. }
  197. static int cdbs_close(void)
  198. {
  199.     if (cdbdir) free((void*)cdbdir);
  200.     cdbdir = NULL;
  201.     if (clansdir) free((void*)clansdir);
  202.     clansdir = NULL;
  203.     if (defacct) free((void*)defacct);
  204.     defacct = NULL;
  205.     return 0;
  206. }
  207. static t_storage_info * cdb_create_account(const char * username)
  208. {
  209.     char *temp;
  210.     if (cdbdir == NULL) {
  211. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  212. return NULL;
  213.     }
  214.     if (prefs_get_savebyname())
  215.     {
  216. char const * safename;
  217. if (!(safename = escape_fs_chars(username,strlen(username))))
  218. {
  219.     eventlog(eventlog_level_error, __FUNCTION__, "could not escape username");
  220.     return NULL;
  221. }
  222. if (!(temp = malloc(strlen(cdbdir)+1+strlen(safename)+1))) /* dir + / + name + NUL */
  223. {
  224.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for temp");
  225.     free((void *)safename);
  226.     return NULL;
  227. }
  228. sprintf(temp,"%s/%s",cdbdir,safename);
  229. free((void *)safename); /* avoid warning */
  230.     } else {
  231. if (!(temp = malloc(strlen(cdbdir)+1+8+1))) /* dir + / + uid + NUL */
  232. {
  233.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for temp");
  234.     return NULL;
  235. }
  236. sprintf(temp,"%s/%06u",cdbdir,maxuserid+1); /* FIXME: hmm, maybe up the %06 to %08... */
  237.     }
  238.     return temp;
  239. }
  240. static int cdb_write_attrs(t_storage_info *info, void *attributes)
  241. {
  242.     FILE           *cdbfile;
  243.     t_attribute * attr;
  244.     char *        tempname;
  245.     struct cdb_make cdbm;
  246.     if (cdbdir == NULL) {
  247. eventlog(eventlog_level_error, __FUNCTION__, "cdb storage not initilized");
  248. return -1;
  249.     }
  250.     if (info == NULL) {
  251. eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
  252. return -1;
  253.     }
  254.     if (attributes == NULL) {
  255. eventlog(eventlog_level_error, __FUNCTION__, "got NULL attributes");
  256. return -1;
  257.     }
  258.     if (!(tempname = malloc(strlen(cdbdir)+1+strlen(BNETD_ACCOUNT_TMP)+1))) {
  259. eventlog(eventlog_level_error, __FUNCTION__, "unable to allocate memory for tempname");
  260.         return -1;
  261.     }
  262.     sprintf(tempname,"%s/%s", cdbdir, BNETD_ACCOUNT_TMP);
  263.     if ((cdbfile = fopen(tempname, "w+b")) == NULL) {
  264. eventlog(eventlog_level_error, __FUNCTION__, "unable to open file "%s" for writing ",tempname);
  265. free(tempname);
  266. return -1;
  267.     }
  268.     cdb_make_start(&cdbm, cdbfile);
  269.     for (attr=(t_attribute *)attributes; attr; attr=attr->next) {
  270. if (attr->key && attr->val) {
  271.     if (strncmp("BNET\CharacterDefault\", attr->key, 20) == 0) {
  272. eventlog(eventlog_level_debug, __FUNCTION__, "skipping attribute key="%s"",attr->key);
  273.     } else {
  274. eventlog(eventlog_level_debug, __FUNCTION__, "saving attribute key="%s" val="%s"",attr->key,attr->val);
  275. cdb_make_add(&cdbm, attr->key, strlen(attr->key), attr->val, strlen(attr->val));
  276.     }
  277. } else eventlog(eventlog_level_error, __FUNCTION__,"could not save attribute key="%s"",attr->key);
  278.     }
  279.     cdb_make_finish(&cdbm);
  280.     fclose(cdbfile);
  281.    
  282. #ifdef WIN32
  283.    /* We are about to rename the temporary file
  284.     * to replace the existing account.  In Windows,
  285.     * we have to remove the previous file or the
  286.     * rename function will fail saying the file
  287.     * already exists.  This defeats the purpose of
  288.     * the rename which was to make this an atomic
  289.     * operation.  At least the race window is small.
  290.     */
  291.     if (access((const char *)info, 0) == 0) {
  292. if (remove((const char *)info)<0) {
  293.     eventlog(eventlog_level_error, __FUNCTION__, "could not delete account file "%s" (remove: %s)", (char *)info, strerror(errno));
  294.             free(tempname);
  295.     return -1;
  296. }
  297.     }
  298. #endif
  299.    
  300.     if (rename(tempname,(const char *)info)<0) {
  301. eventlog(eventlog_level_error, __FUNCTION__, "could not rename account file to "%s" (rename: %s)", (char *)info, strerror(errno));
  302. free(tempname);
  303. return -1;
  304.     }
  305.     free(tempname);
  306.     return 0;
  307. }
  308. #ifndef CDB_ON_DEMAND
  309. /* code adapted from tinycdb-0.73/cdb.c */
  310. static int fget(FILE * fd, unsigned char *b, cdbi_t len, cdbi_t *posp, cdbi_t limit)
  311. {
  312.     if (posp && limit - *posp < len) {
  313. eventlog(eventlog_level_error, __FUNCTION__, "invalid cdb database format");
  314. return -1;
  315.     }
  316.     if (fread(b, 1, len, fd) != len) {
  317. if (ferror(fd)) {
  318.     eventlog(eventlog_level_error, __FUNCTION__, "got error reading from db file");
  319.     return -1;
  320. }
  321. eventlog(eventlog_level_error, __FUNCTION__, "unable to read from cdb file, incomplete file");
  322. return -1;
  323.     }
  324.     if (posp) *posp += len;
  325.     return 0;
  326. }
  327. static const char * fcpy(FILE *fd, cdbi_t len, cdbi_t *posp, cdbi_t limit, unsigned char * buf)
  328. {
  329.     static char *str;
  330.     static unsigned strl;
  331.     unsigned int res = 0, no = 0;
  332.     if (strl < len + 1) {
  333. char *tmp;
  334. if ((tmp = malloc(len + 1)) == NULL) {
  335.     eventlog(eventlog_level_error, __FUNCTION__, "could not alloc memory to read from db");
  336.     return NULL;
  337. }
  338. if (str) free((void*)str);
  339. str = tmp;
  340. strl = len + 1;
  341.     }
  342.     while(len - res > 0) {
  343. if (len > 2048) no = 2048;
  344. else no = len;
  345. fget(fd, buf, no, posp, limit);
  346. memmove(str + res, buf, no);
  347. res += no;
  348.     }
  349.     if (res > strl - 1) {
  350. eventlog(eventlog_level_error, __FUNCTION__, "BUG, this should nto happen");
  351. return NULL;
  352.     }
  353.     str[res] = '';
  354.     return str;
  355. }
  356. static int cdb_read_attrs(t_storage_info *info, t_read_attr_func cb, void *data)
  357. {
  358.     cdbi_t eod, klen, vlen;
  359.     cdbi_t pos = 0;
  360.     const char *key;
  361.     const char *val;
  362.     unsigned char buf[2048];
  363.     FILE *f;
  364.     if (cdbdir == NULL) {
  365. eventlog(eventlog_level_error, __FUNCTION__, "cdb storage not initilized");
  366. return -1;
  367.     }
  368.     if (info == NULL) {
  369. eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
  370. return -1;
  371.     }
  372.     if (cb == NULL) {
  373. eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
  374. return -1;
  375.     }
  376.     if ((f = fopen(info, "rb")) == NULL) {
  377. eventlog(eventlog_level_error, __FUNCTION__, "got error opening file '%s'", (char *)info);
  378. return -1;
  379.     }
  380.     fget(f, buf, 2048, &pos, 2048);
  381.     eod = cdb_unpack(buf);
  382.     while(pos < eod) {
  383. fget(f, buf, 8, &pos, eod);
  384. klen = cdb_unpack(buf);
  385. vlen = cdb_unpack(buf + 4);
  386. if ((key = fcpy(f, klen, &pos, eod, buf)) == NULL) {
  387.     eventlog(eventlog_level_error, __FUNCTION__, "error reading attribute key");
  388.     fclose(f);
  389.     return -1;
  390. }
  391. if ((key = strdup(key)) == NULL) {
  392.     eventlog(eventlog_level_error, __FUNCTION__, "error duplicating attribute key");
  393.     fclose(f);
  394.     return -1;
  395. }
  396. if ((val = fcpy(f, vlen, &pos, eod, buf)) == NULL) {
  397.     eventlog(eventlog_level_error, __FUNCTION__, "error reading attribute val");
  398.     free((void *)key);
  399.     fclose(f);
  400.     return -1;
  401. }
  402. // eventlog(eventlog_level_trace, __FUNCTION__, "read atribute : '%s' -> '%s'", key, val);
  403. cb(key, val, data);
  404. free((void *)key);
  405.     }
  406.     fclose(f);
  407.     return 0;
  408. }
  409. #else /* CDB_ON_DEMAND */
  410. static int cdb_read_attrs(t_storage_info *info, t_read_attr_func cb, void *data)
  411. {
  412.     return 0;
  413. }
  414. #endif
  415. static void * cdb_read_attr(t_storage_info *info, const char *key)
  416. {
  417. #ifdef CDB_ON_DEMAND
  418.     FILE *cdbfile;
  419.     t_attribute *attr;
  420.     const char *filename = (const char *)info;
  421.     char *val;
  422.     unsigned vlen = 1;
  423.     if (!cdbdir) {
  424. eventlog(eventlog_level_error, __FUNCTION__, "cdb storage not initilized");
  425. return NULL;
  426.     }
  427.     if (key == NULL) {
  428. eventlog(eventlog_level_error, __FUNCTION__, "got NULL key");
  429. return NULL;
  430.     }
  431. //    eventlog(eventlog_level_trace, __FUNCTION__, "reading key '%s'", key);
  432.     if ((cdbfile = fopen(filename, "rb")) == NULL) {
  433. // eventlog(eventlog_level_debug, __FUNCTION__, "unable to open file "%s" for reading ",filename);
  434. return NULL;
  435.     }
  436.     if (cdb_seek(cdbfile, key, strlen(key), &vlen) <= 0) {
  437. // eventlog(eventlog_level_debug, __FUNCTION__, "could not find key '%s'", key);
  438. fclose(cdbfile);
  439. return NULL;
  440.     }
  441.     if ((attr = malloc(sizeof(t_attribute))) == NULL) {
  442. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory for attr result");
  443. fclose(cdbfile);
  444. return NULL;
  445.     }
  446.     if ((attr->key = strdup(key)) == NULL) {
  447. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory for attr key result");
  448. free((void*)attr);
  449. fclose(cdbfile);
  450. return NULL;
  451.     }
  452.     if ((val = malloc(vlen + 1)) == NULL) {
  453. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory for attr val result");
  454. free((void*)attr->key);
  455. free((void*)attr);
  456. fclose(cdbfile);
  457. return NULL;
  458.     }
  459.     cdb_bread(cdbfile, val, vlen);
  460. fclose(cdbfile);
  461.     val[vlen] = '';
  462.     attr->val = val;
  463.     attr->dirty = 0;
  464. //    eventlog(eventlog_level_trace, __FUNCTION__, "read key '%s' value '%s'", attr->key, attr->val);
  465.     return attr;
  466. #else
  467.     return NULL;
  468. #endif
  469. }
  470. static int cdb_free_info(t_storage_info *info)
  471. {
  472.     if (info) free((void*)info);
  473.     return 0;
  474. }
  475. static t_storage_info * cdb_get_defacct(void)
  476. {
  477.     t_storage_info * info;
  478.     if (defacct == NULL) {
  479.         eventlog(eventlog_level_error, __FUNCTION__, "cdb storage not initilized");
  480. return NULL;
  481.     }
  482.     if ((info = strdup(defacct)) == NULL) {
  483.         eventlog(eventlog_level_error, __FUNCTION__, "could not duplicate default account cdb filename");
  484. return NULL;
  485.     }
  486.     return info;
  487. }
  488. static int cdb_read_accounts(t_read_accounts_func cb, void *data)
  489. {
  490.     char const * dentry;
  491.     char *       pathname;
  492.     t_pdir *     accountdir;
  493.     if (cdbdir == NULL) {
  494. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  495. return -1;
  496.     }
  497.     if (cb == NULL) {
  498. eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
  499. return -1;
  500.     }
  501.     if (!(accountdir = p_opendir(cdbdir))) {
  502. eventlog(eventlog_level_error, __FUNCTION__, "unable to open user directory "%s" for reading (p_opendir: %s)",cdbdir,strerror(errno));
  503. return -1;
  504.     }
  505.     while ((dentry = p_readdir(accountdir))) {
  506. if (dentry[0]=='.') continue;
  507. if (!(pathname = malloc(strlen(cdbdir)+1+strlen(dentry)+1))) /* dir + / + file + NUL */
  508.  {
  509.    eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for pathname");
  510.    continue;
  511.  }
  512. sprintf(pathname,"%s/%s", cdbdir, dentry);
  513. cb(pathname, data);
  514.     }
  515.     if (p_closedir(accountdir)<0)
  516. eventlog(eventlog_level_error, __FUNCTION__,"unable to close user directory "%s" (p_closedir: %s)", cdbdir,strerror(errno));
  517.     return 0;
  518. }
  519. static void * cdb_read_account(t_read_account_func cb, const char * name)
  520. {
  521.     char *       pathname;
  522.     if (cdbdir == NULL) {
  523. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  524. return NULL;
  525.     }
  526.     if (cb == NULL) {
  527. eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
  528. return NULL;
  529.     }
  530.     if (!(pathname = malloc(strlen(cdbdir)+1+strlen(name)+1))) /* dir + / + file + NUL */
  531.     {
  532. eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for pathname");
  533. return NULL;
  534.     }
  535.     sprintf(pathname,"%s/%s", cdbdir, name);
  536.     if (access(pathname,0)) /* if it doesn't exist */
  537.     {
  538. free((void *) pathname);
  539. return NULL;
  540.     }
  541.     return cb(pathname);
  542. }
  543. static int cdb_cmp_info(t_storage_info *info1, t_storage_info *info2)
  544. {
  545.     return strcmp((const char *)info1, (const char *)info2);
  546. }
  547. static const char * cdb_escape_key(const char * key)
  548. {
  549.     return key;
  550. }
  551. static int cdb_load_clans(t_load_clans_func cb)
  552. {
  553.   char const *dentry;
  554.   t_pdir *clandir;
  555.   char *pathname;
  556.   int       clantag;
  557.   t_clan *clan;
  558.   FILE *fp;
  559.   char clanname[CLAN_NAME_MAX+1];
  560.   char motd[51];
  561.   int cid, creation_time;
  562.   int member_uid, member_join_time;
  563.   char member_status;
  564.   t_clanmember *member;
  565.   
  566.     if (cb == NULL) {
  567. eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
  568. return -1;
  569.     }
  570.   if (!(clandir = p_opendir(clansdir)))
  571.     {
  572.       eventlog(eventlog_level_error,__FUNCTION__,"unable to open clan directory "%s" for reading (p_opendir: %s)",clansdir,strerror(errno));
  573.       return -1;
  574.     }
  575.   eventlog(eventlog_level_trace,__FUNCTION__,"start reading clans");
  576.   if (!(pathname = malloc(strlen(clansdir)+1+4+1)))
  577. {
  578.   eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for pathname");
  579.   return -1;
  580. }
  581.     while ((dentry = p_readdir(clandir)) != NULL)
  582.     {
  583.       if (dentry[0]=='.') continue;
  584.     
  585.       sprintf(pathname,"%s/%s",clansdir,dentry);
  586.       if (strlen(dentry)>4)
  587. {
  588.   eventlog(eventlog_level_error,__FUNCTION__,"found too long clan filename in clandir "%s"",dentry);
  589.   continue;
  590. }
  591.     
  592.       clantag = str_to_clantag(dentry);
  593.   if ((fp = fopen(pathname,"r"))==NULL)
  594.     {
  595.       eventlog(eventlog_level_error,__FUNCTION__,"can't open clanfile "%s"",pathname);
  596.       continue;
  597.     }
  598.   if(!(clan = malloc(sizeof(t_clan))))
  599.   {
  600.     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for clan");
  601.     free((void *)pathname);
  602.     p_closedir(clandir);
  603.     return -1;
  604.   }
  605.   clan->clantag=clantag;
  606.   fscanf(fp,""%[^"]","%[^"]",%i,%in",clanname,motd,&cid,&creation_time);
  607.   clan->clanname = strdup(clanname);
  608.   clan->clan_motd = strdup(motd);
  609.   clan->clanid = cid;
  610.   clan->creation_time=(time_t)creation_time;
  611.   clan->created = 1;
  612.   clan->modified = 0;
  613.   clan->channel_type = prefs_get_clan_channel_default_private();
  614.  
  615.   eventlog(eventlog_level_trace,__FUNCTION__,"name: %s motd: %s clanid: %i time: %i",clanname,motd,cid,creation_time);
  616.   clan->members = list_create();
  617.   while (fscanf(fp,"%i,%c,%in",&member_uid,&member_status,&member_join_time)==3)
  618.     {
  619.       if (!(member = malloc(sizeof(t_clanmember))))
  620. {
  621.   eventlog(eventlog_level_error,__FUNCTION__,"cannot allocate memory for clan member");
  622.   clan_remove_all_members(clan);
  623.       if(clan->clanname)
  624.     free((void *)clan->clanname);
  625.       if(clan->clan_motd)
  626.         free((void *)clan->clan_motd);
  627.   free((void *)clan);
  628.       fclose(fp);
  629.       free((void *)pathname);
  630.       p_closedir(clandir);
  631.   return -1;
  632. }
  633.       if(!(member->memberacc   = accountlist_find_account_by_uid(member_uid)))
  634.       {
  635.     eventlog(eventlog_level_error,__FUNCTION__,"cannot find uid %u", member_uid);
  636.     free((void *)member);
  637.     continue;
  638.       }
  639.       member->memberconn  = NULL;
  640.       member->status    = member_status-'0';
  641.       member->join_time = member_join_time;
  642.       member->clan = clan;
  643.       if((member->status==CLAN_NEW)&&(time(NULL)-member->join_time>prefs_get_clan_newer_time()*3600))
  644.       {
  645.           member->status = CLAN_PEON;
  646.           clan->modified = 1;
  647.       }
  648.       if (list_append_data(clan->members,member)<0)
  649. {
  650.   eventlog(eventlog_level_error,__FUNCTION__,"could not append item");
  651.   free((void *)member);
  652.   clan_remove_all_members(clan);
  653.       if(clan->clanname)
  654.     free((void *)clan->clanname);
  655.       if(clan->clan_motd)
  656.     free((void *)clan->clan_motd);
  657.   free((void *)clan);
  658.       fclose(fp);
  659.       free((void *)pathname);
  660.       p_closedir(clandir);
  661.   return -1;
  662. }
  663.       account_set_clanmember(member->memberacc, member);
  664.       eventlog(eventlog_level_trace,__FUNCTION__,"added member: uid: %i status: %c join_time: %i",member_uid,member_status+'0',member_join_time);
  665.     }
  666.   fclose(fp);
  667.       cb(clan);
  668.     }
  669.       free((void *)pathname);
  670.   if (p_closedir(clandir)<0)
  671.     {
  672.       eventlog(eventlog_level_error,__FUNCTION__,"unable to close clan directory "%s" (p_closedir: %s)",clansdir,strerror(errno));
  673.     }
  674.   eventlog(eventlog_level_trace,__FUNCTION__,"finished reading clans");
  675.   return 0;
  676. }
  677. static int cdb_write_clan(void * data)
  678. {
  679.   FILE *fp;
  680.   t_elem *curr;
  681.   t_clanmember *member;
  682.   char *clanfile;
  683.   t_clan        *clan=(t_clan *)data;
  684.   if (!(clanfile = malloc(strlen(clansdir)+1+4+1)))
  685.     {
  686.       eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for filename");
  687.       return -1;
  688.     }
  689.   sprintf(clanfile,"%s/%c%c%c%c",clansdir,
  690.   clan->clantag>>24,(clan->clantag>>16)&0xff,
  691.   (clan->clantag>>8)&0xff,clan->clantag&0xff);
  692.   if ((fp = fopen(clanfile,"w"))==NULL)
  693.     {
  694.       eventlog(eventlog_level_error,__FUNCTION__,"can't open clanfile "%s"",clanfile);
  695.       free((void *)clanfile);
  696.       return -1;
  697.     }
  698.   fprintf(fp,""%s","%s",%i,%in",clan->clanname,clan->clan_motd,clan->clanid,(int)clan->creation_time);
  699.   LIST_TRAVERSE(clan->members,curr)
  700.     {
  701.       if (!(member = elem_get_data(curr)))
  702. {
  703.   eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list");
  704.   continue;
  705. }
  706.     if((member->status==CLAN_NEW)&&(time(NULL)-member->join_time>prefs_get_clan_newer_time()*3600))
  707.       member->status = CLAN_PEON;
  708.     fprintf(fp,"%i,%c,%un",account_get_uid(member->memberacc),member->status+'0',(unsigned)member->join_time);
  709.     }
  710.   fclose(fp);
  711.   free((void *)clanfile);
  712.   return 0;
  713. }
  714. static int cdb_remove_clan(int clantag)
  715. {
  716.     char * tempname;
  717.     if (!(tempname = malloc(strlen(clansdir)+1+4+1)))
  718. {
  719.   eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for pathname");
  720.   return -1;
  721. }
  722.     sprintf(tempname, "%s/%c%c%c%c", clansdir, clantag>>24, (clantag>>16)&0xff, (clantag>>8)&0xff, clantag&0xff);
  723. if (remove((const char *)tempname)<0) {
  724.     eventlog(eventlog_level_error, __FUNCTION__, "could not delete clan file "%s" (remove: %s)", (char *)tempname, strerror(errno));
  725.         free(tempname);
  726.     return -1;
  727. }
  728.     free(tempname);
  729.     return 0;
  730. }
  731. static int cdb_remove_clanmember(int uid)
  732. {
  733.     return 0;
  734. }