/* * $Id: ram-parse.c,v 0.58 2003/08/28 23:11:02 ceder Exp $ * Copyright (C) 1991, 1993-1999, 2001-2003 Lysator Academic Computer Association. * * This file is part of the LysKOM server. * * LysKOM is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * LysKOM is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with LysKOM; see the file COPYING. If not, write to * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * * Please report bugs at http://bugzilla.lysator.liu.se/. */ /* * ram-parse.c -- parse objects from disk file. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #ifdef HAVE_STRING_H # include #endif #include "timewrap.h" #include #include #include "s-string.h" #include "kom-types.h" #include "ram-io.h" #include "ram-parse.h" #include "log.h" #include "lyskomd.h" #include "server/smalloc.h" #include "kom-errno.h" #include "kom-memory.h" #include "local-to-global.h" static Success fparse_text_list(struct dbfile *fp, Local_to_global *result); /* * FIXME (bug 340): Not all functions are needed. * FIXME (bug 341): The method for checking errors in fparse_long is * ugly, and not all callers check for errors properly. */ #define REALLOC(ptr, size) srealloc(ptr, size) static int fparse_long_errors = 0; void fskipwhite(struct dbfile *fp) { int c; while ( (c = dbfile_getc(fp)) != EOF && /* isascii(c) && */ isspace(c) ) ; if (c != EOF) dbfile_ungetc(fp, c); } extern unsigned long fparse_long(struct dbfile *fp) { unsigned long res = 0; int foo = 0; int c; fskipwhite(fp); while ( (c = dbfile_getc(fp)) != EOF && /* isascii(c) && */ isdigit(c)) { foo = 1; res = 10 * res + c - '0'; } if ( foo == 0 ) { restart_kom("fparse_long() failed at pos %ld.\n", dbfile_ftell(fp)); ++fparse_long_errors; } dbfile_ungetc(fp, c); return res; } extern time_t fparse_time(struct dbfile *fp) { return fparse_long(fp); } static Success fparse_info_0(struct dbfile *fp, Info *info) { info->conf_pres_conf = fparse_long(fp); info->pers_pres_conf = fparse_long(fp); info->motd_conf = fparse_long(fp); info->kom_news_conf = fparse_long(fp); info->motd_of_lyskom = fparse_long(fp); return OK; } static Success fparse_info_2(struct dbfile *fp, Info *info) { info->conf_pres_conf = fparse_long(fp); info->pers_pres_conf = fparse_long(fp); info->motd_conf = fparse_long(fp); info->kom_news_conf = fparse_long(fp); info->motd_of_lyskom = fparse_long(fp); info->highest_aux_no = fparse_long(fp); free_aux_item_list(&info->aux_item_list); return fparse_aux_item_list(fp, &info->aux_item_list); } extern Success fparse_info(struct dbfile *fp, Info *info) { if ( fparse_long_errors != 0 ) { kom_log("fparse_info(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } switch (fp->format) { case 0: case 1: return fparse_info_0(fp, info); break; case 2: case 3: return fparse_info_2(fp, info); break; default: restart_kom("unknown input format: %d\n", fp->format); return FAILURE; break; } } static Success fparse_conference_2(struct dbfile *fp, Conference *result) { if ( fparse_long_errors != 0 ) { kom_log("fparse_conference(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } if ( fparse_string(fp, &result->name) != OK ) { kom_log("fparse_conference(): Can't parse name.\n"); return FAILURE; } if ( fparse_member_list(fp, &result->members) != OK || l2g_read(fp, &result->texts) != OK || fparse_conf_type(fp, &result->type) != OK ) { kom_log("fparse_conference: file is corrupt.\n"); return FAILURE; } result->creation_time = fparse_time(fp); result->last_written = fparse_time(fp); result->creator = fparse_long(fp); result->presentation = fparse_long(fp); result->supervisor = fparse_long(fp); result->permitted_submitters = fparse_long(fp); result->super_conf = fparse_long(fp); result->msg_of_day = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("fparse_conference(): %d %s before 'nice'. Reset.\n", fparse_long_errors, "fparse_long_errors"); fparse_long_errors = 0; return FAILURE; } result->nice = fparse_long(fp); result->keep_commented = fparse_long(fp); result->expire = fparse_long(fp); result->highest_aux = fparse_long(fp); if (fparse_aux_item_list(fp, &result->aux_item_list) != OK) return FAILURE; fskipwhite(fp); return OK; } static Success fparse_conference_0(struct dbfile *fp, Conference *result) { if ( fparse_long_errors != 0 ) { kom_log("fparse_conference(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } if ( fparse_string(fp, &result->name) != OK ) { kom_log("fparse_conference(): Can't parse name.\n"); return FAILURE; } if ( fparse_member_list(fp, &result->members) != OK || fparse_text_list(fp, &result->texts) != OK || fparse_conf_type(fp, &result->type) != OK ) { kom_log("fparse_conference: file is corrupt.\n"); return FAILURE; } result->creation_time = fparse_time(fp); result->last_written = fparse_time(fp); result->creator = fparse_long(fp); result->presentation = fparse_long(fp); result->supervisor = fparse_long(fp); result->permitted_submitters = fparse_long(fp); result->super_conf = fparse_long(fp); result->msg_of_day = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("fparse_conference(): %d %s before 'nice'. Reset.\n", fparse_long_errors, "fparse_long_errors"); fparse_long_errors = 0; return FAILURE; } result->nice = fparse_long(fp); result->highest_aux = 0; result->aux_item_list.length = 0; result->aux_item_list.items = 0; fskipwhite(fp); return OK; } extern Success fparse_conference(struct dbfile *fp, Conference *result) { switch (fp->format) { case 0: case 1: return fparse_conference_0(fp, result); break; case 2: case 3: return fparse_conference_2(fp, result); break; default: restart_kom("unknown input format: %d\n", fp->format); return FAILURE; break; } } static Success fparse_person_0(struct dbfile *fp, Person *person) { String pwd = EMPTY_STRING; if ( fparse_long_errors != 0 ) { kom_log("fparse_person(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } if ( fparse_string(fp, &pwd) != OK ) { kom_log("fparse_person(): Failed to parse password.\n"); return FAILURE; } memcpy(person->pwd, pwd.string, PASSWD_LEN); s_clear(&pwd); if ( fparse_string(fp, &person->username) != OK || fparse_priv_bits(fp, &person->privileges) != OK || fparse_personal_flags(fp, &person->flags) != OK || fparse_text_list(fp, &person->created_texts) != OK || fparse_mark_list(fp, &person->marks) != OK || fparse_membership_list(fp, &person->conferences) != OK ) { kom_log("fparse_person(): parse error.\n"); return FAILURE; } person->last_login = fparse_time(fp); person->user_area = fparse_long(fp); person->total_time_present = fparse_long(fp); person->sessions = fparse_long(fp); person->created_lines = fparse_long(fp); person->created_bytes = fparse_long(fp); person->read_texts = fparse_long(fp); person->no_of_text_fetches = fparse_long(fp); person->created_persons = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("fparse_person(): %d %s before 'created_confs'. Reset.\n", fparse_long_errors, "fparse_long_errors"); fparse_long_errors = 0; return FAILURE; } person->created_confs = fparse_long(fp); fskipwhite(fp); return OK; } static Success fparse_person_2(struct dbfile *fp, Person *person) { String pwd = EMPTY_STRING; if ( fparse_long_errors != 0 ) { kom_log("fparse_person(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } if ( fparse_string(fp, &pwd) != OK ) { kom_log("fparse_person(): Failed to parse password.\n"); return FAILURE; } memcpy(person->pwd, pwd.string, PASSWD_LEN); s_clear(&pwd); if ( fparse_string(fp, &person->username) != OK || fparse_priv_bits(fp, &person->privileges) != OK || fparse_personal_flags(fp, &person->flags) != OK || l2g_read(fp, &person->created_texts) != OK || fparse_mark_list(fp, &person->marks) != OK || fparse_membership_list(fp, &person->conferences) != OK ) { kom_log("fparse_person(): parse error.\n"); return FAILURE; } person->last_login = fparse_time(fp); person->user_area = fparse_long(fp); person->total_time_present = fparse_long(fp); person->sessions = fparse_long(fp); person->created_lines = fparse_long(fp); person->created_bytes = fparse_long(fp); person->read_texts = fparse_long(fp); person->no_of_text_fetches = fparse_long(fp); person->created_persons = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("fparse_person(): %d %s before 'created_confs'. Reset.\n", fparse_long_errors, "fparse_long_errors"); fparse_long_errors = 0; return FAILURE; } person->created_confs = fparse_long(fp); fskipwhite(fp); return OK; } extern Success fparse_person(struct dbfile *fp, Person *result) { switch(fp->format) { case 0: case 1: return fparse_person_0(fp, result); break; case 2: case 3: return fparse_person_2(fp, result); break; default: restart_kom("unknown input format: %d\n", fp->format); return FAILURE; break; } } static Success fparse_membership_type(struct dbfile *fp, Membership_type *result) { fskipwhite(fp); result->invitation = dbfile_getc(fp) != '0'; result->passive = dbfile_getc(fp) != '0'; result->secret = dbfile_getc(fp) != '0'; result->passive_message_invert = dbfile_getc(fp) != '0'; result->reserved2 = dbfile_getc(fp) != '0'; result->reserved3 = dbfile_getc(fp) != '0'; result->reserved4 = dbfile_getc(fp) != '0'; result->reserved5 = dbfile_getc(fp) != '0'; return OK; } static Success fparse_read_range_0(struct dbfile *fp, Membership *mship) { Local_text_no last_text_read; unsigned int no_of_read; unsigned int i; unsigned int n; struct read_range *res; struct read_range *tail; Local_text_no tmp; last_text_read = fparse_long(fp); no_of_read = fparse_long(fp); sfree(mship->read_ranges); if (last_text_read == 0) { mship->read_ranges = NULL; mship->no_of_read_ranges = 0; } else { mship->no_of_read_ranges = 1; mship->read_ranges = smalloc(sizeof(mship->read_ranges[0])); mship->read_ranges->first_read = 1; mship->read_ranges->last_read = last_text_read; } if (no_of_read > 0) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': n = mship->no_of_read_ranges; tail = res = mship->read_ranges; for (i = 0; i < no_of_read; i++) { tmp = fparse_long(fp); if (tail != NULL && tmp <= tail->last_read) { kom_log("fparse_read_range_0: discarded out-of-order" " local number %lu probably introduced by" " bug 1121\n", (unsigned long)tmp); } else if (tail != NULL && tmp == tail->last_read + 1) tail->last_read = tmp; else { res = REALLOC(res, ++n * sizeof(*res)); tail = &res[n-1]; tail->first_read = tail->last_read = tmp; } } mship->no_of_read_ranges = n; mship->read_ranges = res; fskipwhite(fp); if (dbfile_getc(fp) != '}') { err_stat = 1; kom_errno = KOM_LDB_ERR; kom_log("fparse_read_range_0(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); return FAILURE; } break; case '*': kom_log("fparse_read_range_0(): " "empty read_ranges with %lu elements (corrected)\n", (unsigned long)no_of_read); mship->no_of_read_ranges = 0; break; default: kom_log("fparse_read_range_0(): expected '*' or '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 2; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_read_range_0(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 3; kom_errno = KOM_LDB_ERR; return FAILURE; } } return OK; } static Success fparse_membership_2(struct dbfile *fp, Membership *mship) { mship->last_time_read = fparse_time(fp); mship->conf_no = fparse_long(fp); mship->priority = fparse_long(fp); if (fparse_read_range_0(fp, mship) != OK) return FAILURE; mship->added_by = fparse_long(fp); mship->added_at = fparse_time(fp); if (fparse_membership_type(fp, &mship->type) != OK) return FAILURE; return OK; } static Success fparse_membership_0(struct dbfile *fp, Membership *mship) { mship->last_time_read = fparse_time(fp); mship->conf_no = fparse_long(fp); mship->priority = fparse_long(fp); if (fparse_read_range_0(fp, mship) != OK) return FAILURE; return OK; } static Success fparse_membership(struct dbfile *fp, Membership *mship) { switch(fp->format) { case 0: case 1: return fparse_membership_0(fp, mship); break; case 2: case 3: return fparse_membership_2(fp, mship); break; default: restart_kom("unknown input format: %d\n", fp->format); return FAILURE; break; } } static Success fparse_membership_list_0(struct dbfile *fp, Membership_list *result) { int i; /* First free all the read_texts. */ if ( result->confs != NULL ) { for ( i = 0; i < result->no_of_confs; i++) sfree(result->confs[ i ].read_ranges); } result->no_of_confs = fparse_long(fp); if ( result->no_of_confs > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->confs = REALLOC(result->confs, (result->no_of_confs * sizeof(Membership))); if ( result->confs == NULL && result->no_of_confs > 0 ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_confs; i++) { init_membership(&result->confs[ i ]); if ( fparse_membership_0(fp, &result->confs[i]) != OK ) return FAILURE; } fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_membership_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 4; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->confs != NULL ) { sfree(result->confs); result->confs = NULL; } kom_log("%s empty list with %lu elements (corrected).\n", "fparse_membership_list():", (unsigned long)result->no_of_confs); result->no_of_confs = 0; break; default: kom_log("fparse_membership_list(): " "expected '*' or '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 5; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_membership_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 6; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->confs != NULL ) { sfree(result->confs); result->confs = NULL; } } return OK; } static Success fparse_membership_list_2(struct dbfile *fp, Membership_list *result) { int i; /* First free all the read_texts. */ if ( result->confs != NULL ) { for ( i = 0; i < result->no_of_confs; i++) sfree(result->confs[ i ].read_ranges); } result->no_of_confs = fparse_long(fp); if ( result->no_of_confs > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->confs = REALLOC(result->confs, (result->no_of_confs * sizeof(Membership))); if ( result->confs == NULL && result->no_of_confs > 0 ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_confs; i++) { init_membership(&result->confs[ i ]); if ( fparse_membership(fp, &result->confs[i]) != OK ) return FAILURE; } fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_membership_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 4; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->confs != NULL ) { sfree(result->confs); result->confs = NULL; } kom_log("%s empty list with %lu elements (corrected).\n", "fparse_membership_list():", (unsigned long)result->no_of_confs); result->no_of_confs = 0; break; default: kom_log("fparse_membership_list(): " "expected '*' or '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 5; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_membership_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 6; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->confs != NULL ) { sfree(result->confs); result->confs = NULL; } } return OK; } extern Success fparse_membership_list(struct dbfile *fp, Membership_list *result) { switch(fp->format) { case 0: case 1: return fparse_membership_list_0(fp, result); break; case 2: case 3: return fparse_membership_list_2(fp, result); break; default: restart_kom("unknown input format: %d\n", fp->format); return FAILURE; break; } } extern Success fparse_conf_list(struct dbfile *fp, Conf_list_old *result) { unsigned long i; result->no_of_conf_nos = fparse_long(fp); if ( result->no_of_conf_nos > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->conf_nos = REALLOC(result->conf_nos, (result->no_of_conf_nos * sizeof(Conf_no))); if ( result->conf_nos == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_conf_nos; i++) result->conf_nos[ i ] = fparse_long(fp); fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_conf_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 7; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->conf_nos != NULL ) { sfree(result->conf_nos); result->conf_nos = NULL; } break; default: kom_log("fparse_conf_list(): expected '*' or '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 8; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_conf_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 9; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->conf_nos != NULL ) { sfree(result->conf_nos); result->conf_nos = NULL; } } if ( result->no_of_conf_nos > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->type_of_conf = REALLOC(result->type_of_conf, (result->no_of_conf_nos * sizeof(Conf_type))); if ( result->type_of_conf == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_conf_nos; i++) if ( fparse_conf_type(fp, &result->type_of_conf[i]) != OK ) { return FAILURE; } fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_conf_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 10; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->type_of_conf != NULL ) { sfree(result->type_of_conf); result->type_of_conf = NULL; } break; default: kom_log("fparse_conf_list(): expected '*' or '+' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 11; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_conf_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 12; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->type_of_conf != NULL ) { sfree(result->type_of_conf); result->type_of_conf = NULL; } } return OK; } extern Success fparse_mark_list(struct dbfile *fp, Mark_list *result) { int i; result->no_of_marks = fparse_long(fp); if ( result->no_of_marks > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->marks = REALLOC(result->marks, (result->no_of_marks * sizeof(Mark))); if ( result->marks == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_marks; i++) if ( fparse_mark(fp, &result->marks[ i ] ) != OK ) { return FAILURE; } fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_mark_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 13; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->marks != NULL ) { sfree(result->marks); result->marks = NULL; } break; default: kom_log("fparse_mark_list(): expected '*' or '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 14; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_mark_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 15; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->marks != NULL ) { sfree(result->marks); result->marks = NULL; } } return OK; } static Success fparse_text_stat_3(struct dbfile *fp, Text_stat *result) { int i; int c; if ( fparse_long_errors != 0 ) { kom_log("fparse_text_stat(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } result->creation_time = fparse_time(fp); result->author = fparse_long(fp); result->generation = fparse_long(fp); result->file_pos = fparse_long(fp); result->no_of_lines = fparse_long(fp); result->no_of_chars = fparse_long(fp); result->no_of_marks = fparse_long(fp); result->no_of_misc = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("%s(): %d fparse_long_errors before 'misc_items' (3). Reset.\n", "fparse_text_stat", fparse_long_errors); fparse_long_errors = 0; return FAILURE; } if ( result->no_of_misc > 0 ) { fskipwhite(fp); switch( c = dbfile_getc(fp) ) { case '{': result->misc_items = REALLOC(result->misc_items, (result->no_of_misc * sizeof(Misc_info))); if ( result->misc_items == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_misc; i++) if ( fparse_misc_info(fp, &result->misc_items[ i ]) != OK ) return FAILURE; fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '}' ) { kom_log("fparse_text_stat(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 16; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '@': case '+': dbfile_ungetc(fp, c); kom_log("fparse_text_stat(): got '%c'; expected '{' or '*'\n.", c); kom_log("Character ungetc'd and interpreted as a '*' at %ld.\n", dbfile_ftell(fp)); /* Fall through */ case '*': if ( result->misc_items != NULL ) { sfree(result->misc_items); result->misc_items = NULL; } break; default: kom_log("fparse_text_stat(): expected '*' or '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 17; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '*' ) { kom_log("fparse_text_stat(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 18; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->misc_items != NULL ) { sfree(result->misc_items); result->misc_items = NULL; } } result->highest_aux = fparse_long(fp); if (fparse_aux_item_list(fp, &result->aux_item_list) != OK) return FAILURE; fskipwhite(fp); return OK; } static Success fparse_text_stat_2(struct dbfile *fp, Text_stat *result) { int i; int c; if ( fparse_long_errors != 0 ) { kom_log("fparse_text_stat(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } result->creation_time = fparse_time(fp); result->author = fparse_long(fp); result->generation = 0; result->file_pos = fparse_long(fp); result->no_of_lines = fparse_long(fp); result->no_of_chars = fparse_long(fp); result->no_of_marks = fparse_long(fp); result->no_of_misc = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("fparse_text_stat(): %d fparse_long_errors" " before 'misc_items' (2). Reset.\n", fparse_long_errors); fparse_long_errors = 0; return FAILURE; } if ( result->no_of_misc > 0 ) { fskipwhite(fp); switch( c = dbfile_getc(fp) ) { case '{': result->misc_items = REALLOC(result->misc_items, (result->no_of_misc * sizeof(Misc_info))); if ( result->misc_items == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_misc; i++) if ( fparse_misc_info(fp, &result->misc_items[ i ]) != OK ) return FAILURE; fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '}' ) { kom_log("fparse_text_stat(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 16; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '@': case '+': dbfile_ungetc(fp, c); kom_log("fparse_text_stat(): got '%c'; expected '{' or '*'\n.", c); kom_log("Character ungetc'd and interpreted as a '*' at %ld.\n", dbfile_ftell(fp)); /* Fall through */ case '*': if ( result->misc_items != NULL ) { sfree(result->misc_items); result->misc_items = NULL; } break; default: kom_log("fparse_text_stat(): expected '*' or '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 17; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '*' ) { kom_log("fparse_text_stat(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 18; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->misc_items != NULL ) { sfree(result->misc_items); result->misc_items = NULL; } } result->highest_aux = fparse_long(fp); if (fparse_aux_item_list(fp, &result->aux_item_list) != OK) return FAILURE; fskipwhite(fp); return OK; } static Success fparse_text_stat_0(struct dbfile *fp, Text_stat *result) { int i; int c; if ( fparse_long_errors != 0 ) { kom_log("fparse_text_stat(): fparse_long_errors == %d on entry. Reset.\n", fparse_long_errors); fparse_long_errors = 0; } result->creation_time = fparse_time(fp); result->author = fparse_long(fp); result->generation = 0; result->file_pos = fparse_long(fp); result->no_of_lines = fparse_long(fp); result->no_of_chars = fparse_long(fp); result->no_of_marks = fparse_long(fp); result->no_of_misc = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("%s(): %d fparse_long_errors before 'misc_items'. Reset.\n", "fparse_text_stat", fparse_long_errors); fparse_long_errors = 0; return FAILURE; } if ( result->no_of_misc > 0 ) { fskipwhite(fp); switch( c = dbfile_getc(fp) ) { case '{': result->misc_items = REALLOC(result->misc_items, (result->no_of_misc * sizeof(Misc_info))); if ( result->misc_items == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_misc; i++) if ( fparse_misc_info(fp, &result->misc_items[ i ]) != OK ) return FAILURE; fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '}' ) { kom_log("fparse_text_stat(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 19; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '@': case '+': dbfile_ungetc(fp, c); kom_log("fparse_text_stat(): got '%c'; expected '{' or '*'\n.", c); kom_log("Character ungetc'd and interpreted as a '*' at %ld.\n", dbfile_ftell(fp)); /* Fall through */ case '*': if ( result->misc_items != NULL ) { sfree(result->misc_items); result->misc_items = NULL; } break; default: kom_log("fparse_text_stat(): expected '*' or '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 20; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '*' ) { kom_log("fparse_text_stat(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 21; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->misc_items != NULL ) { sfree(result->misc_items); result->misc_items = NULL; } } result->highest_aux = 0; result->aux_item_list.length = 0; result->aux_item_list.items = NULL; fskipwhite(fp); return OK; } extern Success fparse_text_stat(struct dbfile *fp, Text_stat *result) { switch(fp->format) { case 0: case 1: return fparse_text_stat_0(fp, result); break; case 2: return fparse_text_stat_2(fp, result); break; case 3: return fparse_text_stat_3(fp, result); break; default: restart_kom("unknown input format: %d\n", fp->format); return FAILURE; break; } } static Success fparse_text_list(struct dbfile *fp, Local_to_global *result) { unsigned long i; Local_text_no lno; Local_text_no no_of_texts; lno = fparse_long(fp); no_of_texts = fparse_long(fp); l2g_clear(result); if (no_of_texts > 0) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': for ( i = 0; i < no_of_texts; i++) l2g_append(result, lno++, fparse_long(fp)); fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_text_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 22; kom_errno = KOM_LDB_ERR; return FAILURE; } break; default: kom_log("fparse_text_list(): expected '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 23; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_text_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 24; kom_errno = KOM_LDB_ERR; return FAILURE; } l2g_set_first_appendable_key(result, lno); } return OK; } extern Success fparse_string(struct dbfile *fp, String *result) { String_size length; length = fparse_long(fp); if ( dbfile_getc(fp) != 'H' ) { kom_log("fparse_string(): expected 'H' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 25; kom_errno = KOM_LDB_ERR; return FAILURE; } s_size_crea_str(result, length); if ( result->string == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } if ( fread(result->string, sizeof(char), result->len, fp->fp) != (size_t)result->len ) { kom_log("fparse_string(): unexpected eof at pos %ld.\n", dbfile_ftell(fp)); err_stat = 26; kom_errno = KOM_LDB_ERR; return FAILURE; } return OK; } extern Success fparse_member_list(struct dbfile *fp, Member_list *result) { int i; result->no_of_members = fparse_long(fp); if ( result->no_of_members > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->members = REALLOC(result->members, (result->no_of_members * sizeof(Member))); if ( result->members == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_members; i++) { init_member(&result->members[i]); if ( fparse_member(fp, &result->members[ i ]) != OK ) { return FAILURE; } } fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_member_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 27; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->members != NULL ) { sfree(result->members); result->members = NULL; } break; default: kom_log("fparse_member_list(): expected '*' or '{' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 28; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_member_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 29; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->members != NULL ) { sfree(result->members); result->members = NULL; } } return OK; } static Success fparse_member_0(struct dbfile *fp, Member *result) { result->member = fparse_long(fp); return OK; } static Success fparse_member_2(struct dbfile *fp, Member *result) { result->member = fparse_long(fp); result->added_by = fparse_long(fp); result->added_at = fparse_time(fp); return fparse_membership_type(fp, &result->type); } extern Success fparse_member(struct dbfile *fp, Member *result) { switch (fp->format) { case 0: case 1: return fparse_member_0(fp, result); break; case 2: case 3: return fparse_member_2(fp, result); break; default: restart_kom("unknown database format: %d", fp->format); return FAILURE; } } extern Success fparse_mark(struct dbfile *fp, Mark *result) { result->text_no = fparse_long(fp); result->mark_type = fparse_long(fp); return OK; } extern Success fparse_priv_bits(struct dbfile *fp, Priv_bits *result) { fskipwhite(fp); result->wheel = dbfile_getc(fp) != '0'; result->admin = dbfile_getc(fp) != '0'; result->statistic = dbfile_getc(fp) != '0'; result->create_pers = dbfile_getc(fp) != '0'; result->create_conf = dbfile_getc(fp) != '0'; result->change_name = dbfile_getc(fp) != '0'; result->flg7 = dbfile_getc(fp) != '0'; result->flg8 = dbfile_getc(fp) != '0'; result->flg9 = dbfile_getc(fp) != '0'; result->flg10 = dbfile_getc(fp) != '0'; result->flg11 = dbfile_getc(fp) != '0'; result->flg12 = dbfile_getc(fp) != '0'; result->flg13 = dbfile_getc(fp) != '0'; result->flg14 = dbfile_getc(fp) != '0'; result->flg15 = dbfile_getc(fp) != '0'; result->flg16 = dbfile_getc(fp) != '0'; return OK; } extern Success fparse_personal_flags(struct dbfile *fp, Personal_flags *result) { fskipwhite(fp); result->unread_is_secret = dbfile_getc(fp) != '0'; result->flg2 = dbfile_getc(fp) != '0'; result->flg3 = dbfile_getc(fp) != '0'; result->flg4 = dbfile_getc(fp) != '0'; result->flg5 = dbfile_getc(fp) != '0'; result->flg6 = dbfile_getc(fp) != '0'; result->flg7 = dbfile_getc(fp) != '0'; result->flg8 = dbfile_getc(fp) != '0'; return OK; } extern Success fparse_conf_type(struct dbfile *fp, Conf_type *result) { char c; fskipwhite(fp); result->rd_prot = dbfile_getc(fp) != '0'; result->original = dbfile_getc(fp) != '0'; result->secret = dbfile_getc(fp) != '0'; result->letter_box = dbfile_getc(fp) != '0'; c = dbfile_getc(fp); if (c != '0' && c != '1') { result->allow_anon = 1; result->forbid_secret = 0; result->reserved2 = 0; result->reserved3 = 0; dbfile_ungetc(fp, c); return(OK); } result->allow_anon = ( c != '0' ); result->forbid_secret = ( dbfile_getc(fp) != '0' ); result->reserved2 = ( dbfile_getc(fp) != '0' ); result->reserved3 = ( dbfile_getc(fp) != '0' ); return OK; } extern Success fparse_who_info(struct dbfile *fp, Who_info *result) { result->person = fparse_long(fp); result->working_conference = fparse_long(fp); if ( fparse_string(fp, &result->what_am_i_doing) != OK ) { kom_log("fparse_who_info(): parse error.\n"); err_stat = 30; kom_errno = KOM_LDB_ERR; return FAILURE; } return OK; } extern Success fparse_who_info_list(struct dbfile *fp, Who_info_list *result) { int i; fskipwhite(fp); result->no_of_persons = fparse_long(fp); if ( result->no_of_persons > 0 ) { fskipwhite(fp); switch(dbfile_getc(fp)) { case '{': result->info = REALLOC(result->info, (result->no_of_persons * sizeof(Who_info))); if ( result->info == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for ( i = 0; i < result->no_of_persons; i++) { init_who_info(&result->info[ i ]); if ( fparse_who_info(fp, &result->info[ i ]) != OK ) return FAILURE; } fskipwhite(fp); if ( dbfile_getc(fp) != '}' ) { kom_log("fparse_who_info_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 31; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->info != NULL ) { sfree(result->info); result->info = NULL; } break; default: kom_log("fparse_who_info_list(): expected '*' or '{' at %ld.\n", dbfile_ftell(fp)); err_stat = 32; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( dbfile_getc(fp) != '*' ) { kom_log("fparse_who_info_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 33; kom_errno = KOM_LDB_ERR; return FAILURE; } if ( result->info != NULL ) { sfree(result->info); result->info = NULL; } } return OK; } extern Success fparse_aux_item_flags(struct dbfile *fp, Aux_item_flags *f) { fskipwhite(fp); f->deleted = dbfile_getc(fp) != '0'; f->inherit = dbfile_getc(fp) != '0'; f->secret = dbfile_getc(fp) != '0'; f->hide_creator = dbfile_getc(fp) != '0'; f->dont_garb = dbfile_getc(fp) != '0'; f->reserved3 = dbfile_getc(fp) != '0'; f->reserved4 = dbfile_getc(fp) != '0'; f->reserved5 = dbfile_getc(fp) != '0'; return OK; } extern Success fparse_aux_item_link(struct dbfile *fp, Aux_item_link *link) { link->target_type = (enum object_type)(long)fparse_long(fp); link->target_item = fparse_long(fp); switch (link->target_type) { case CONF_OBJECT_TYPE: link->target_object.conf = (Conf_no)fparse_long(fp); break; case TEXT_OBJECT_TYPE: link->target_object.text = (Text_no)fparse_long(fp); break; default: ; } return OK; } extern Success fparse_aux_item(struct dbfile *fp, Aux_item *item) { item->aux_no = fparse_long(fp); item->tag = fparse_long(fp); item->creator = fparse_long(fp); item->sent_at = fparse_time(fp); fparse_aux_item_flags(fp, &item->flags); item->inherit_limit = fparse_long(fp); item->data = EMPTY_STRING; if (fparse_string(fp, &item->data) != OK) { kom_log("fparse_aux_item(): Can't parse name.\n"); return FAILURE; } if (fparse_aux_item_link(fp, &(item->linked_item)) != OK) { kom_log("fparse_aux_item(): Can't parse link.\n"); return FAILURE; } return OK; } extern Success fparse_aux_item_list(struct dbfile *fp, Aux_item_list *result) { int c, i; result->items = NULL; result->length = fparse_long(fp); if ( fparse_long_errors != 0 ) { kom_log("%s(): %d fparse_long_errors before 'aux_items'. Reset.\n", "fparse_text_stat", fparse_long_errors); fparse_long_errors = 0; return FAILURE; } if ( result->length > 0 ) { fskipwhite(fp); switch( c = dbfile_getc(fp) ) { case '{': result->items = REALLOC(result->items, (result->length * sizeof(Aux_item))); if ( result->items == NULL ) { err_stat = 0; kom_errno = KOM_OUT_OF_MEMORY; return FAILURE; } for (i = 0; i < result->length; i++) if ( fparse_aux_item(fp, &result->items[ i ]) != OK ) return FAILURE; fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '}' ) { kom_log("fparse_aux_item_list(): expected '}' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 34; kom_errno = KOM_LDB_ERR; return FAILURE; } break; case '*': if ( result->items != NULL ) { sfree(result->items); result->items = NULL; result->length = 0; } break; default: kom_log("fparse_aux_item_list(): expected '*' or '}' at %ld.\n", dbfile_ftell(fp)); err_stat = 35; kom_errno = KOM_LDB_ERR; return FAILURE; } } else { fskipwhite(fp); if ( (c = dbfile_getc(fp)) != '*' ) { kom_log("fparse_aux_item_list(): expected '*' at pos %ld.\n", dbfile_ftell(fp)); err_stat = 36; kom_errno = KOM_LDB_ERR; return FAILURE; } result->items = NULL; result->length = 0; } return OK; } extern Success fparse_misc_info(struct dbfile *fp, Misc_info *result) { long typ; typ = fparse_long(fp); switch(typ) { case recpt: case cc_recpt: case bcc_recpt: result->datum.recipient = fparse_long(fp); break; case loc_no: result->datum.local_no = fparse_long(fp); break; case rec_time: result->datum.received_at = fparse_time(fp); break; case comm_to: case comm_in: case footn_to: case footn_in: result->datum.text_link = fparse_long(fp); break; case sent_by: result->datum.sender = fparse_long(fp); break; case sent_at: result->datum.sent_at = fparse_time(fp); break; default: kom_log("fparse_misc_info(): illegal info_type %d at pos %ld.\n", result->type, dbfile_ftell(fp)); err_stat = 37; kom_errno = KOM_LDB_ERR; return FAILURE; } result->type = (enum info_type)typ; return OK; } extern Success fparse_set_pos(struct dbfile *fp, long offset) { if (fseek(fp->fp, offset, SEEK_SET) != 0) { kom_log("fseek failed: %s\n", strerror(errno)); return FAILURE; } else return OK; }