/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/storage_file.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/bnetd/storage_file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 /*
2 * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu)
3 * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net)
4 * Copyright (C) 2002,2003,2004 Mihai RUSU (dizzy@rdsnet.ro)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
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.
15 *
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, MA 02111-1307, USA.
19 */
20 #include "common/setup_before.h"
21 #include <stdio.h>
22 #ifdef HAVE_STDDEF_H
23 # include <stddef.h>
24 #else
25 # ifndef NULL
26 # define NULL ((void *)0)
27 # endif
28 #endif
29 #ifdef STDC_HEADERS
30 # include <stdlib.h>
31 #else
32 # ifdef HAVE_MALLOC_H
33 # include <malloc.h>
34 # endif
35 #endif
36 #ifdef HAVE_STRING_H
37 # include <string.h>
38 #else
39 # ifdef HAVE_STRINGS_H
40 # include <strings.h>
41 # endif
42 #endif
43 #include "compat/strchr.h"
44 #include "compat/strdup.h"
45 #include "compat/strcasecmp.h"
46 #include "compat/strncasecmp.h"
47 #include <ctype.h>
48 #ifdef HAVE_LIMITS_H
49 # include <limits.h>
50 #endif
51 #include "compat/char_bit.h"
52 #ifdef TIME_WITH_SYS_TIME
53 # include <sys/time.h>
54 # include <time.h>
55 #else
56 # ifdef HAVE_SYS_TIME_H
57 # include <sys/time.h>
58 # else
59 # include <time.h>
60 # endif
61 #endif
62 #include <errno.h>
63 #include "compat/strerror.h"
64 #ifdef HAVE_SYS_TYPES_H
65 # include <sys/types.h>
66 #endif
67 #ifdef HAVE_UNISTD_H
68 # include <unistd.h>
69 #endif
70 #include "compat/access.h"
71 #include "compat/rename.h"
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 #define CLAN_INTERNAL_ACCESS
79 #define TEAM_INTERNAL_ACCESS
80 #define ACCOUNT_INTERNAL_ACCESS
81 #include "common/introtate.h"
82 #include "team.h"
83 #include "account.h"
84 #include "common/hashtable.h"
85 #include "storage.h"
86 #include "storage_file.h"
87 #include "file_plain.h"
88 #include "file_cdb.h"
89 #include "common/list.h"
90 #include "connection.h"
91 #include "watch.h"
92 #include "clan.h"
93 #undef ACCOUNT_INTERNAL_ACCESS
94 #undef TEAM_INTERNAL_ACCESS
95 #undef CLAN_INTERNAL_ACCESS
96 #include "common/tag.h"
97 #include "common/xalloc.h"
98 #include "common/setup_after.h"
99
100 /* file storage API functions */
101
102 static int file_init(const char *);
103 static int file_close(void);
104 static unsigned file_read_maxuserid(void);
105 static t_storage_info *file_create_account(char const *);
106 static t_storage_info *file_get_defacct(void);
107 static int file_free_info(t_storage_info *);
108 static int file_read_attrs(t_storage_info *, t_read_attr_func, void *);
109 static void *file_read_attr(t_storage_info *, const char *);
110 static int file_write_attrs(t_storage_info *, void *);
111 static int file_read_accounts(int,t_read_accounts_func, void *);
112 static t_storage_info *file_read_account(const char *, unsigned);
113 static int file_cmp_info(t_storage_info *, t_storage_info *);
114 static const char *file_escape_key(const char *);
115 static int file_load_clans(t_load_clans_func);
116 static int file_write_clan(void *);
117 static int file_remove_clan(int);
118 static int file_remove_clanmember(int);
119 static int file_load_teams(t_load_teams_func);
120 static int file_write_team(void *);
121 static int file_remove_team(unsigned int);
122
123 /* storage struct populated with the functions above */
124
125 t_storage storage_file = {
126 file_init,
127 file_close,
128 file_read_maxuserid,
129 file_create_account,
130 file_get_defacct,
131 file_free_info,
132 file_read_attrs,
133 file_write_attrs,
134 file_read_attr,
135 file_read_accounts,
136 file_read_account,
137 file_cmp_info,
138 file_escape_key,
139 file_load_clans,
140 file_write_clan,
141 file_remove_clan,
142 file_remove_clanmember,
143 file_load_teams,
144 file_write_team,
145 file_remove_team
146 };
147
148 /* start of actual file storage code */
149
150 static const char *accountsdir = NULL;
151 static const char *clansdir = NULL;
152 static const char *teamsdir = NULL;
153 static const char *defacct = NULL;
154 static t_file_engine *file = NULL;
155
156 static unsigned file_read_maxuserid(void)
157 {
158 return maxuserid;
159 }
160
161 static int file_init(const char *path)
162 {
163 char *tok, *copy, *tmp, *p;
164 const char *dir = NULL;
165 const char *clan = NULL;
166 const char *team = NULL;
167 const char *def = NULL;
168 const char *driver = NULL;
169
170 if (path == NULL || path[0] == '\0')
171 {
172 eventlog(eventlog_level_error, __FUNCTION__, "got NULL or empty path");
173 return -1;
174 }
175
176 copy = xstrdup(path);
177 tmp = copy;
178 while ((tok = strtok(tmp, ";")) != NULL)
179 {
180 tmp = NULL;
181 if ((p = strchr(tok, '=')) == NULL)
182 {
183 eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path, no '=' present in token");
184 xfree((void *) copy);
185 return -1;
186 }
187 *p = '\0';
188 if (strcasecmp(tok, "dir") == 0)
189 dir = p + 1;
190 else if (strcasecmp(tok, "clan") == 0)
191 clan = p + 1;
192 else if (strcasecmp(tok, "team") == 0)
193 team = p + 1;
194 else if (strcasecmp(tok, "default") == 0)
195 def = p + 1;
196 else if (strcasecmp(tok, "mode") == 0)
197 driver = p + 1;
198 else
199 eventlog(eventlog_level_warn, __FUNCTION__, "unknown token in storage_path : '%s'", tok);
200 }
201
202 if (def == NULL || clan == NULL || team == NULL || dir == NULL || driver == NULL)
203 {
204 eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path line for file module (doesnt have a 'dir', a 'clan', a 'team', a 'default' token and a 'mode' token)");
205 xfree((void *) copy);
206 return -1;
207 }
208
209 if (!strcasecmp(driver, "plain"))
210 file = &file_plain;
211 else if (!strcasecmp(driver, "cdb"))
212 file = &file_cdb;
213 else
214 {
215 eventlog(eventlog_level_error, __FUNCTION__, "unknown mode '%s' must be either plain or cdb", driver);
216 xfree((void *) copy);
217 return -1;
218 }
219
220 if (accountsdir)
221 file_close();
222
223 accountsdir = xstrdup(dir);
224 clansdir = xstrdup(clan);
225 teamsdir = xstrdup(team);
226 defacct = xstrdup(def);
227
228 xfree((void *) copy);
229
230 return 0;
231 }
232
233 static int file_close(void)
234 {
235 if (accountsdir)
236 xfree((void *) accountsdir);
237 accountsdir = NULL;
238
239 if (clansdir)
240 xfree((void *) clansdir);
241 clansdir = NULL;
242
243 if (teamsdir)
244 xfree((void *) teamsdir);
245 teamsdir = NULL;
246
247 if (defacct)
248 xfree((void *) defacct);
249 defacct = NULL;
250
251 file = NULL;
252
253 return 0;
254 }
255
256 static t_storage_info *file_create_account(const char *username)
257 {
258 char *temp;
259
260 if (accountsdir == NULL || file == NULL)
261 {
262 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
263 return NULL;
264 }
265
266 if (prefs_get_savebyname())
267 {
268 char const *safename;
269
270 if (!strcmp(username, defacct))
271 {
272 eventlog(eventlog_level_error, __FUNCTION__, "username as defacct not allowed");
273 return NULL;
274 }
275
276 if (!(safename = escape_fs_chars(username, strlen(username))))
277 {
278 eventlog(eventlog_level_error, __FUNCTION__, "could not escape username");
279 return NULL;
280 }
281 temp = xmalloc(strlen(accountsdir) + 1 + strlen(safename) + 1); /* dir + / + name + NUL */
282 sprintf(temp, "%s/%s", accountsdir, safename);
283 xfree((void *) safename); /* avoid warning */
284 } else
285 {
286 temp = xmalloc(strlen(accountsdir) + 1 + 8 + 1); /* dir + / + uid + NUL */
287 sprintf(temp, "%s/%06u", accountsdir, maxuserid + 1); /* FIXME: hmm, maybe up the %06 to %08... */
288 }
289
290 return temp;
291 }
292
293 static int file_write_attrs(t_storage_info * info, void *attributes)
294 {
295 char *tempname;
296
297 if (accountsdir == NULL || file == NULL)
298 {
299 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
300 return -1;
301 }
302
303 if (info == NULL)
304 {
305 eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
306 return -1;
307 }
308
309 if (attributes == NULL)
310 {
311 eventlog(eventlog_level_error, __FUNCTION__, "got NULL attributes");
312 return -1;
313 }
314
315 tempname = xmalloc(strlen(accountsdir) + 1 + strlen(BNETD_ACCOUNT_TMP) + 1);
316 sprintf(tempname, "%s/%s", accountsdir, BNETD_ACCOUNT_TMP);
317
318 if (file->write_attrs(tempname, attributes))
319 {
320 /* no eventlog here, it should be reported from the file layer */
321 xfree(tempname);
322 return -1;
323 }
324
325 if (p_rename(tempname, (const char *) info) < 0)
326 {
327 eventlog(eventlog_level_error, __FUNCTION__, "could not rename account file to \"%s\" (rename: %s)", (char *) info, pstrerror(errno));
328 xfree(tempname);
329 return -1;
330 }
331
332 xfree(tempname);
333
334 return 0;
335 }
336
337 static int file_read_attrs(t_storage_info * info, t_read_attr_func cb, void *data)
338 {
339 if (accountsdir == NULL || file == NULL)
340 {
341 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
342 return -1;
343 }
344
345 if (info == NULL)
346 {
347 eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
348 return -1;
349 }
350
351 if (cb == NULL)
352 {
353 eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
354 return -1;
355 }
356
357 eventlog(eventlog_level_debug, __FUNCTION__, "loading \"%s\"", (char *) info);
358
359 if (file->read_attrs((const char *) info, cb, data))
360 {
361 /* no eventlog, error reported earlier */
362 return -1;
363 }
364
365 return 0;
366 }
367
368 static void *file_read_attr(t_storage_info * info, const char *key)
369 {
370 if (accountsdir == NULL || file == NULL)
371 {
372 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
373 return NULL;
374 }
375
376 if (info == NULL)
377 {
378 eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
379 return NULL;
380 }
381
382 if (key == NULL)
383 {
384 eventlog(eventlog_level_error, __FUNCTION__, "got NULL key");
385 return NULL;
386 }
387
388 return file->read_attr((const char *) info, key);
389 }
390
391 static int file_free_info(t_storage_info * info)
392 {
393 if (info)
394 xfree((void *) info);
395 return 0;
396 }
397
398 static t_storage_info *file_get_defacct(void)
399 {
400 t_storage_info *info;
401
402 if (defacct == NULL)
403 {
404 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
405 return NULL;
406 }
407
408 info = xstrdup(defacct);
409
410 return info;
411 }
412
413 static int file_read_accounts(int flag,t_read_accounts_func cb, void *data)
414 {
415 char const *dentry;
416 char *pathname;
417 t_pdir *accountdir;
418
419 if (accountsdir == NULL)
420 {
421 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
422 return -1;
423 }
424
425 if (cb == NULL)
426 {
427 eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
428 return -1;
429 }
430
431 if (!(accountdir = p_opendir(accountsdir)))
432 {
433 eventlog(eventlog_level_error, __FUNCTION__, "unable to open user directory \"%s\" for reading (p_opendir: %s)", accountsdir, pstrerror(errno));
434 return -1;
435 }
436
437 while ((dentry = p_readdir(accountdir)))
438 {
439 if (dentry[0] == '.')
440 continue;
441
442 pathname = xmalloc(strlen(accountsdir) + 1 + strlen(dentry) + 1); /* dir + / + file + NUL */
443 sprintf(pathname, "%s/%s", accountsdir, dentry);
444
445 cb(pathname, data);
446 }
447
448 if (p_closedir(accountdir) < 0)
449 eventlog(eventlog_level_error, __FUNCTION__, "unable to close user directory \"%s\" (p_closedir: %s)", accountsdir, pstrerror(errno));
450
451 return 0;
452 }
453
454 static t_storage_info *file_read_account(const char *accname, unsigned uid)
455 {
456 char *pathname;
457
458 if (accountsdir == NULL)
459 {
460 eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
461 return NULL;
462 }
463
464 /* ONLY if requesting for a username and if savebyname() is true
465 * PS: yes its kind of a hack, we will make a proper index file
466 */
467 if (accname && prefs_get_savebyname()) {
468 pathname = xmalloc(strlen(accountsdir) + 1 + strlen(accname) + 1); /* dir + / + file + NUL */
469 sprintf(pathname, "%s/%s", accountsdir, accname);
470 if (access(pathname, F_OK)) /* if it doesn't exist */
471 {
472 xfree((void *) pathname);
473 return NULL;
474 }
475 return pathname;
476 }
477
478 return NULL;
479 }
480
481 static int file_cmp_info(t_storage_info * info1, t_storage_info * info2)
482 {
483 return strcmp((const char *) info1, (const char *) info2);
484 }
485
486 static const char *file_escape_key(const char *key)
487 {
488 return key;
489 }
490
491 static int file_load_clans(t_load_clans_func cb)
492 {
493 char const *dentry;
494 t_pdir *clandir;
495 char *pathname;
496 int clantag;
497 t_clan *clan;
498 FILE *fp;
499 char *clanname, *motd, *p;
500 char line[1024];
501 int cid, creation_time;
502 int member_uid, member_join_time;
503 char member_status;
504 t_clanmember *member;
505
506 if (cb == NULL)
507 {
508 eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
509 return -1;
510 }
511
512 if (!(clandir = p_opendir(clansdir)))
513 {
514 eventlog(eventlog_level_error, __FUNCTION__, "unable to open clan directory \"%s\" for reading (p_opendir: %s)", clansdir, pstrerror(errno));
515 return -1;
516 }
517 eventlog(eventlog_level_trace, __FUNCTION__, "start reading clans");
518
519 pathname = xmalloc(strlen(clansdir) + 1 + 4 + 1);
520 while ((dentry = p_readdir(clandir)) != NULL)
521 {
522 if (dentry[0] == '.')
523 continue;
524
525 if (strlen(dentry) > 4)
526 {
527 eventlog(eventlog_level_error, __FUNCTION__, "found too long clan filename in clandir \"%s\"", dentry);
528 continue;
529 }
530
531 sprintf(pathname, "%s/%s", clansdir, dentry);
532
533 clantag = str_to_clantag(dentry);
534
535 if ((fp = fopen(pathname, "r")) == NULL)
536 {
537 eventlog(eventlog_level_error, __FUNCTION__, "can't open clanfile \"%s\"", pathname);
538 continue;
539 }
540
541 clan = xmalloc(sizeof(t_clan));
542 clan->clantag = clantag;
543
544 if (!fgets(line, 1024, fp))
545 {
546 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: no first line");
547 xfree((void*)clan);
548 continue;
549 }
550
551 clanname = line;
552 if (*clanname != '"')
553 {
554 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
555 xfree((void*)clan);
556 continue;
557 }
558 clanname++;
559 p = strchr(clanname, '"');
560 if (!p)
561 {
562 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
563 xfree((void*)clan);
564 continue;
565 }
566 *p = '\0';
567 if (strlen(clanname) >= CLAN_NAME_MAX)
568 {
569 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
570 xfree((void*)clan);
571 continue;
572 }
573
574 p++;
575 if (*p != ',')
576 {
577 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
578 xfree((void*)clan);
579 continue;
580 }
581 p++;
582 if (*p != '"')
583 {
584 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
585 xfree((void*)clan);
586 continue;
587 }
588 motd = p + 1;
589 p = strchr(motd, '"');
590 if (!p)
591 {
592 eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
593 xfree((void*)clan);
594 continue;
595 }
596 *p = '\0';
597
598 if (sscanf(p + 1, ",%d,%d\n", &cid, &creation_time) != 2)
599 {
600 eventlog(eventlog_level_error, __FUNCTION__, "invalid first line in clanfile");
601 xfree((void*)clan);
602 continue;
603 }
604 clan->clanname = xstrdup(clanname);
605 clan->clan_motd = xstrdup(motd);
606 clan->clanid = cid;
607 clan->creation_time = (time_t) creation_time;
608 clan->created = 1;
609 clan->modified = 0;
610 clan->channel_type = prefs_get_clan_channel_default_private();
611
612 eventlog(eventlog_level_trace, __FUNCTION__, "name: %s motd: %s clanid: %i time: %i", clanname, motd, cid, creation_time);
613
614 clan->members = list_create();
615
616 while (fscanf(fp, "%i,%c,%i\n", &member_uid, &member_status, &member_join_time) == 3)
617 {
618 member = xmalloc(sizeof(t_clanmember));
619 if (!(member->memberacc = accountlist_find_account_by_uid(member_uid)))
620 {
621 eventlog(eventlog_level_error, __FUNCTION__, "cannot find uid %u", member_uid);
622 xfree((void *) member);
623 continue;
624 }
625 member->status = member_status - '0';
626 member->join_time = member_join_time;
627 member->clan = clan;
628
629 if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600))
630 {
631 member->status = CLAN_PEON;
632 clan->modified = 1;
633 }
634
635 list_append_data(clan->members, member);
636
637 account_set_clanmember(member->memberacc, member);
638 eventlog(eventlog_level_trace, __FUNCTION__, "added member: uid: %i status: %c join_time: %i", member_uid, member_status + '0', member_join_time);
639 }
640
641 fclose(fp);
642
643 cb(clan);
644
645 }
646
647 xfree((void *) pathname);
648
649 if (p_closedir(clandir) < 0)
650 {
651 eventlog(eventlog_level_error, __FUNCTION__, "unable to close clan directory \"%s\" (p_closedir: %s)", clansdir, pstrerror(errno));
652 }
653 eventlog(eventlog_level_trace, __FUNCTION__, "finished reading clans");
654
655 return 0;
656 }
657
658 static int file_write_clan(void *data)
659 {
660 FILE *fp;
661 t_elem *curr;
662 t_clanmember *member;
663 char *clanfile;
664 t_clan *clan = (t_clan *) data;
665
666 clanfile = xmalloc(strlen(clansdir) + 1 + 4 + 1);
667 sprintf(clanfile, "%s/%c%c%c%c", clansdir, clan->clantag >> 24, (clan->clantag >> 16) & 0xff, (clan->clantag >> 8) & 0xff, clan->clantag & 0xff);
668
669 if ((fp = fopen(clanfile, "w")) == NULL)
670 {
671 eventlog(eventlog_level_error, __FUNCTION__, "can't open clanfile \"%s\"", clanfile);
672 xfree((void *) clanfile);
673 return -1;
674 }
675
676 fprintf(fp, "\"%s\",\"%s\",%i,%i\n", clan->clanname, clan->clan_motd, clan->clanid, (int) clan->creation_time);
677
678 LIST_TRAVERSE(clan->members, curr)
679 {
680 if (!(member = elem_get_data(curr)))
681 {
682 eventlog(eventlog_level_error, __FUNCTION__, "got NULL elem in list");
683 continue;
684 }
685 if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600))
686 member->status = CLAN_PEON;
687 fprintf(fp, "%i,%c,%u\n", account_get_uid(member->memberacc), member->status + '0', (unsigned) member->join_time);
688 }
689
690 fclose(fp);
691 xfree((void *) clanfile);
692 return 0;
693 }
694
695 static int file_remove_clan(int clantag)
696 {
697 char *tempname;
698
699 tempname = xmalloc(strlen(clansdir) + 1 + 4 + 1);
700 sprintf(tempname, "%s/%c%c%c%c", clansdir, clantag >> 24, (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff);
701 if (remove((const char *) tempname) < 0)
702 {
703 eventlog(eventlog_level_error, __FUNCTION__, "could not delete clan file \"%s\" (remove: %s)", (char *) tempname, pstrerror(errno));
704 xfree(tempname);
705 return -1;
706 }
707 xfree(tempname);
708 return 0;
709 }
710
711 static int file_remove_clanmember(int uid)
712 {
713 return 0;
714 }
715
716 static int file_load_teams(t_load_teams_func cb)
717 {
718 char const *dentry;
719 t_pdir *teamdir;
720 char *pathname;
721 unsigned int teamid;
722 t_team *team;
723 FILE *fp;
724 char * line;
725 unsigned int fteamid,lastgame;
726 unsigned char size;
727 char clienttag[5];
728 int i;
729
730 if (cb == NULL)
731 {
732 eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
733 return -1;
734 }
735
736 if (!(teamdir = p_opendir(teamsdir)))
737 {
738 eventlog(eventlog_level_error, __FUNCTION__, "unable to open team directory \"%s\" for reading (p_opendir: %s)", teamsdir, pstrerror(errno));
739 return -1;
740 }
741 eventlog(eventlog_level_trace, __FUNCTION__, "start reading teams");
742
743 pathname = xmalloc(strlen(teamsdir) + 1 + 8 + 1);
744 while ((dentry = p_readdir(teamdir)) != NULL)
745 {
746 if (dentry[0] == '.')
747 continue;
748
749 if (strlen(dentry) != 8)
750 {
751 eventlog(eventlog_level_error, __FUNCTION__, "found invalid team filename in teamdir \"%s\"", dentry);
752 continue;
753 }
754
755 sprintf(pathname, "%s/%s", teamsdir, dentry);
756
757 teamid = (unsigned int)strtoul(dentry,NULL,16); // we use hexadecimal teamid as filename
758
759 if ((fp = fopen(pathname, "r")) == NULL)
760 {
761 eventlog(eventlog_level_error, __FUNCTION__, "can't open teamfile \"%s\"", pathname);
762 continue;
763 }
764
765 team = xmalloc(sizeof(t_team));
766 team->teamid = teamid;
767
768 if (!(line = file_get_line(fp)))
769 {
770 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: file is empty");
771 goto load_team_failure;
772 }
773
774 if (sscanf(line,"%u,%c,%4s,%u",&fteamid,&size,clienttag,&lastgame)!=4)
775 {
776 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid number of arguments on first line");
777 goto load_team_failure;
778 }
779
780 if (fteamid != teamid)
781 {
782 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: filename and stored teamid don't match");
783 goto load_team_failure;
784 }
785
786 size -='0';
787 if ((size<2) || (size>4))
788 {
789 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid team size");
790 goto load_team_failure;
791 }
792 team->size = size;
793
794 if (!(tag_check_client(team->clienttag = tag_str_to_uint(clienttag))))
795 {
796 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid clienttag");
797 goto load_team_failure;
798 }
799 team->lastgame = (time_t)lastgame;
800
801 if (!(line= file_get_line(fp)))
802 {
803 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: missing 2nd line");
804 goto load_team_failure;
805 }
806
807 if (sscanf(line,"%u,%u,%u,%u",&team->teammembers[0],&team->teammembers[1],&team->teammembers[2],&team->teammembers[3])!=4)
808 {
809 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid number of arguments on 2nd line");
810 goto load_team_failure;
811 }
812
813 for (i=0; i<MAX_TEAMSIZE;i++)
814 {
815 if (i<size)
816 {
817 if ((team->teammembers[i]==0))
818 {
819 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: too few members");
820 goto load_team_failure;
821 }
822 }
823 else
824 {
825 if ((team->teammembers[i]!=0))
826 {
827 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: too many members");
828 goto load_team_failure;
829 }
830
831 }
832 team->members[i] = NULL;
833 }
834
835 if (!(line= file_get_line(fp)))
836 {
837 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: missing 3rd line");
838 goto load_team_failure;
839 }
840
841 if (sscanf(line,"%d,%d,%d,%d,%d",&team->wins,&team->losses,&team->xp,&team->level,&team->rank)!=5)
842 {
843 eventlog(eventlog_level_error,__FUNCTION__,"invalid team file: invalid number of arguments on 3rd line");
844 goto load_team_failure;
845 }
846
847 eventlog(eventlog_level_trace,__FUNCTION__,"succesfully loaded team %s",dentry);
848 cb(team);
849
850 goto load_team_success;
851 load_team_failure:
852 xfree((void*)team);
853 eventlog(eventlog_level_error,__FUNCTION__,"error while reading file \"%s\"",dentry);
854
855 load_team_success:
856
857 file_get_line(NULL); // clear file_get_line buffer
858 fclose(fp);
859
860
861 }
862
863 xfree((void *) pathname);
864
865 if (p_closedir(teamdir) < 0)
866 {
867 eventlog(eventlog_level_error, __FUNCTION__, "unable to close team directory \"%s\" (p_closedir: %s)", teamsdir, pstrerror(errno));
868 }
869 eventlog(eventlog_level_trace, __FUNCTION__, "finished reading teams");
870
871 return 0;
872 }
873
874 static int file_write_team(void *data)
875 {
876 FILE *fp;
877 char *teamfile;
878 t_team *team = (t_team *) data;
879
880 teamfile = xmalloc(strlen(teamsdir) + 1 + 8 + 1);
881 sprintf(teamfile, "%s/%08x", teamsdir, team->teamid);
882
883 if ((fp = fopen(teamfile, "w")) == NULL)
884 {
885 eventlog(eventlog_level_error, __FUNCTION__, "can't open teamfile \"%s\"", teamfile);
886 xfree((void *) teamfile);
887 return -1;
888 }
889
890 fprintf(fp,"%u,%c,%s,%u\n",team->teamid,team->size+'0',clienttag_uint_to_str(team->clienttag),(unsigned int)team->lastgame);
891 fprintf(fp,"%u,%u,%u,%u\n",team->teammembers[0],team->teammembers[1],team->teammembers[2],team->teammembers[3]);
892 fprintf(fp,"%d,%d,%d,%d,%d\n",team->wins,team->losses,team->xp,team->level,team->rank);
893
894 fclose(fp);
895 xfree((void *) teamfile);
896
897 return 0;
898 }
899
900 static int file_remove_team(unsigned int teamid)
901 {
902
903 char *tempname;
904
905 tempname = xmalloc(strlen(clansdir) + 1 + 8 + 1);
906 sprintf(tempname, "%s/%08x", clansdir, teamid);
907 if (remove((const char *) tempname) < 0)
908 {
909 eventlog(eventlog_level_error, __FUNCTION__, "could not delete team file \"%s\" (remove: %s)", (char *) tempname, pstrerror(errno));
910 xfree(tempname);
911 return -1;
912 }
913 xfree(tempname);
914
915 return 0;
916 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1