/* * $Id: ram-output.c,v 0.45 2003/08/23 16:38:14 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-output.c - write objects to disk. * * This is a hack. It shouldn't be used except for debugging and as a * temporary substitute for what Willf|r is (or should:-) be doing. * * Written by ceder 1990-07-13. Rewritten 1990-08-31. * Some functions rewritten for speed by Inge Wallin. * (It worked - now saving is twice as fast.) */ #ifdef HAVE_CONFIG_H # include #endif #include #include "timewrap.h" #include #include "s-string.h" #include "kom-types.h" #include "ram-io.h" #include "ram-output.h" #include "lyskomd.h" #include "log.h" #include "local-to-global.h" #include "server-time.h" /* Forward declarations. */ static void foutput_aux_item_list(FILE *, const Aux_item_list *); static void foutput_conf_type (FILE *, Conf_type); static void foutput_mark(FILE *, Mark); static void foutput_mark_list(FILE *, const Mark_list); static void foutput_member(FILE *, Member); static void foutput_member_list(FILE *, Member_list); static void foutput_membership_list(FILE *, Membership_list); static void foutput_misc_info(FILE *, Misc_info); static void foutput_personal_flags(FILE *, Personal_flags); static void foutput_priv_bits(FILE *, Priv_bits); static void foutput_string(FILE *, String); static void foutput_text_list(FILE *, const Local_to_global *); static void foutput_time(FILE *, time_t); static void foutput_ulong(unsigned long, FILE *); static void foutput_space(FILE *fp); static void foutput_bool(FILE *fp, int val); static void foutput_array_start(FILE *fp); static void foutput_array_end(FILE *fp); static void foutput_array_nodata(FILE *fp); static int output_format = 2; void foutput_header(FILE* fp, const char *state, int include_timestamp) { fprintf(fp, "%s:%05d\n", state, output_format); /* DIRTY-FLAG and VERSION*/ if (include_timestamp) fprintf(fp, "%020lu\n", (unsigned long)current_time.tv_sec); } void set_output_format(int fmt) { output_format = fmt; switch (fmt) { case 0: case 1: case 2: break; default: restart_kom("unknown output format selected: %d\n", fmt); break; } } static void foutput_info_0(FILE *fp, Info *info) { fprintf(fp, " %lu %lu %lu %lu %lu", (unsigned long)info->conf_pres_conf, (unsigned long)info->pers_pres_conf, (unsigned long)info->motd_conf, (unsigned long)info->kom_news_conf, (unsigned long)info->motd_of_lyskom); } static void foutput_info_2(FILE *fp, Info *info) { fprintf(fp, " %lu %lu %lu %lu %lu %lu", (unsigned long)info->conf_pres_conf, (unsigned long)info->pers_pres_conf, (unsigned long)info->motd_conf, (unsigned long)info->kom_news_conf, (unsigned long)info->motd_of_lyskom, (unsigned long)info->highest_aux_no); foutput_aux_item_list(fp, &info->aux_item_list); } void foutput_info(FILE *fp, Info *info) { switch(output_format) { case 0: case 1: foutput_info_0(fp, info); break; case 2: foutput_info_2(fp, info); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_person_0 (FILE *fp, const Person *person) { foutput_string (fp, person->username); foutput_priv_bits (fp, person->privileges); foutput_personal_flags (fp, person->flags); foutput_text_list (fp, &person->created_texts); foutput_mark_list (fp, person->marks); foutput_membership_list (fp, person->conferences); foutput_time(fp, person->last_login); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu", (unsigned long) person -> user_area, (unsigned long) person -> total_time_present, /* This is not a time, * but a number of seconds. */ (unsigned long) person -> sessions, (unsigned long) person -> created_lines, (unsigned long) person -> created_bytes, (unsigned long) person -> read_texts, (unsigned long) person -> no_of_text_fetches, (unsigned long) person -> created_persons, (unsigned long) person -> created_confs); } static void foutput_person_2(FILE *fp, const Person *person) { foutput_string (fp, person->username); foutput_priv_bits (fp, person->privileges); foutput_personal_flags (fp, person->flags); foutput_space(fp); l2g_write (fp, &person->created_texts); foutput_mark_list (fp, person->marks); foutput_membership_list (fp, person->conferences); foutput_time(fp, person->last_login); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu", (unsigned long) person -> user_area, (unsigned long) person -> total_time_present, /* This is not a time, * but a number of seconds. */ (unsigned long) person -> sessions, (unsigned long) person -> created_lines, (unsigned long) person -> created_bytes, (unsigned long) person -> read_texts, (unsigned long) person -> no_of_text_fetches, (unsigned long) person -> created_persons, (unsigned long) person -> created_confs); } extern void foutput_person (FILE *fp, const Person *person) { switch(output_format) { case 0: case 1: foutput_person_0(fp, person); break; case 2: foutput_person_2(fp, person); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_conference_2(FILE *fp, const Conference *conf_c) { foutput_string(fp, conf_c->name); foutput_member_list(fp, conf_c->members); foutput_space(fp); l2g_write(fp, &conf_c->texts); foutput_conf_type(fp, conf_c->type); foutput_time(fp, conf_c -> creation_time ); foutput_time(fp, conf_c -> last_written ); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu", (unsigned long) conf_c -> creator, (unsigned long) conf_c -> presentation, (unsigned long) conf_c -> supervisor, (unsigned long) conf_c -> permitted_submitters, (unsigned long) conf_c -> super_conf, (unsigned long) conf_c -> msg_of_day, (unsigned long) conf_c -> nice); foutput_ulong((unsigned long) conf_c->keep_commented, fp); foutput_ulong((unsigned long) conf_c->expire, fp); foutput_ulong((unsigned long) conf_c->highest_aux, fp); foutput_aux_item_list(fp, &conf_c->aux_item_list); } static void foutput_conference_1 (FILE *fp, Conference *conf_c) { foutput_string(fp, conf_c->name); foutput_member_list(fp, conf_c->members); foutput_text_list(fp, &conf_c->texts); foutput_conf_type(fp, conf_c->type); foutput_time(fp, conf_c -> creation_time ); foutput_time(fp, conf_c -> last_written ); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu", (unsigned long) conf_c -> creator, (unsigned long) conf_c -> presentation, (unsigned long) conf_c -> supervisor, (unsigned long) conf_c -> permitted_submitters, (unsigned long) conf_c -> super_conf, (unsigned long) conf_c -> msg_of_day, (unsigned long) conf_c -> nice); } static void foutput_conference_0 (FILE *fp, Conference *conf_c) { foutput_string(fp, conf_c->name); foutput_member_list(fp, conf_c->members); foutput_text_list(fp, &conf_c->texts); foutput_conf_type(fp, conf_c->type); foutput_time(fp, conf_c -> creation_time ); foutput_time(fp, conf_c -> last_written ); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu", (unsigned long) conf_c -> creator, (unsigned long) conf_c -> presentation, (unsigned long) conf_c -> supervisor, (unsigned long) conf_c -> permitted_submitters, (unsigned long) conf_c -> super_conf, (unsigned long) conf_c -> msg_of_day, (unsigned long) conf_c -> nice); } void foutput_conference(FILE *fp, Conference *conf_c) { switch(output_format) { case 0: foutput_conference_0(fp, conf_c); break; case 1: foutput_conference_1(fp, conf_c); break; case 2: foutput_conference_2(fp, conf_c); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_text_stat_0(FILE *fp, Text_stat *t_stat) { int i; foutput_time(fp, t_stat->creation_time); foutput_ulong((unsigned long) t_stat->author, fp); foutput_ulong((unsigned long) t_stat->file_pos, fp); foutput_ulong((unsigned long) t_stat->no_of_lines, fp); foutput_ulong((unsigned long) t_stat->no_of_chars, fp); foutput_ulong((unsigned long) t_stat->no_of_marks, fp); foutput_ulong((unsigned long) t_stat->no_of_misc, fp); if ( t_stat->misc_items != NULL && t_stat->no_of_misc > 0 ) { foutput_array_start(fp); for ( i = 0; i < t_stat->no_of_misc; i++ ) foutput_misc_info(fp, t_stat->misc_items[ i ]); foutput_array_end(fp); } else foutput_array_nodata(fp); } static void foutput_text_stat_2(FILE *fp, Text_stat *t_stat) { int i; foutput_time(fp, t_stat->creation_time); foutput_ulong((unsigned long) t_stat->author, fp); foutput_ulong((unsigned long) t_stat->file_pos, fp); foutput_ulong((unsigned long) t_stat->no_of_lines, fp); foutput_ulong((unsigned long) t_stat->no_of_chars, fp); foutput_ulong((unsigned long) t_stat->no_of_marks, fp); foutput_ulong((unsigned long) t_stat->no_of_misc, fp); if ( t_stat->misc_items != NULL && t_stat->no_of_misc > 0 ) { foutput_array_start(fp); for ( i = 0; i < t_stat->no_of_misc; i++ ) foutput_misc_info(fp, t_stat->misc_items[ i ]); foutput_array_end(fp); } else foutput_array_nodata(fp); foutput_ulong((unsigned long) t_stat->highest_aux, fp); foutput_aux_item_list(fp, &t_stat->aux_item_list); } void foutput_text_stat(FILE *fp, Text_stat *t_stat) { switch (output_format) { case 0: case 1: foutput_text_stat_0(fp, t_stat); break; case 2: foutput_text_stat_2(fp, t_stat); break; default: restart_kom("unknown database format: %d\n", output_format); break; } } static void foutput_aux_flags(FILE *fp, Aux_item_flags f) { foutput_space(fp); foutput_bool(fp, f.deleted); foutput_bool(fp, f.inherit); foutput_bool(fp, f.secret); foutput_bool(fp, f.hide_creator); foutput_bool(fp, f.dont_garb); foutput_bool(fp, f.reserved3); foutput_bool(fp, f.reserved4); foutput_bool(fp, f.reserved5); } static void foutput_aux_item_link(FILE *fp, Aux_item_link *link) { foutput_ulong((unsigned long) link->target_type, fp); foutput_ulong((unsigned long) link->target_item, fp); switch (link->target_type) { case CONF_OBJECT_TYPE: foutput_ulong((unsigned long) link->target_object.conf, fp); break; case TEXT_OBJECT_TYPE: foutput_ulong((unsigned long) link->target_object.text, fp); break; default: ; } } static void foutput_aux_item(FILE *fp, Aux_item *a_item) { foutput_ulong((unsigned long) a_item->aux_no, fp); foutput_ulong((unsigned long) a_item->tag, fp); foutput_ulong((unsigned long) a_item->creator, fp); foutput_time(fp, a_item->sent_at); foutput_aux_flags(fp, a_item->flags); foutput_ulong((unsigned long) a_item->inherit_limit, fp); foutput_string(fp, a_item->data); foutput_aux_item_link(fp, &a_item->linked_item); } static void foutput_aux_item_list(FILE *fp, const Aux_item_list *aux) { int i; foutput_ulong((unsigned long) aux->length, fp); if (aux->items && aux->length > 0) { foutput_array_start(fp); for (i = 0; i < aux->length; i++) foutput_aux_item(fp, &aux->items[i]); foutput_array_end(fp); } else foutput_array_nodata(fp); } static void foutput_membership_type(FILE *fp, Membership_type type) { foutput_space(fp); foutput_bool(fp, type.invitation); foutput_bool(fp, type.passive); foutput_bool(fp, type.secret); foutput_bool(fp, type.passive_message_invert); foutput_bool(fp, type.reserved2); foutput_bool(fp, type.reserved3); foutput_bool(fp, type.reserved4); foutput_bool(fp, type.reserved5); } static void foutput_read_ranges_0(FILE *fp, Membership *mship) { if (mship->read_ranges == NULL && mship->no_of_read_ranges != 0 ) { kom_log("foutput_read_ranges_0(): no_of_read_ranges forced to 0" " in a membership in %lu.\n", (unsigned long)mship->conf_no); mship->no_of_read_ranges = 0; } if (mship->no_of_read_ranges == 0) fprintf(fp, " 0 0 *"); else { struct read_range *begin; struct read_range *end; begin = &mship->read_ranges[0]; end = begin + mship->no_of_read_ranges; if (begin->first_read == 1) { fprintf(fp, " %lu", begin->last_read); begin++; } else fprintf(fp, " 0"); if (begin == end) fprintf(fp, " 0 *"); else { unsigned long no_of_read = 0; const struct read_range *ptr; for (ptr = begin; ptr < end; ++ptr) no_of_read += ptr->last_read - ptr->first_read + 1; fprintf(fp, " %lu {", no_of_read); for (ptr = begin; ptr < end; ++ptr) { Local_text_no lno; for (lno = ptr->first_read; lno <= ptr->last_read; lno++) fprintf(fp, " %lu", (unsigned long)lno); } fprintf(fp, " }"); } } } static void foutput_membership_0(FILE *fp, Membership *mship) { foutput_time(fp, mship->last_time_read ); fprintf(fp, " %lu %lu", (unsigned long)mship->conf_no, (unsigned long)mship->priority); foutput_read_ranges_0(fp, mship); } static void foutput_membership_2(FILE *fp, Membership *mship) { foutput_time(fp, mship->last_time_read ); fprintf(fp, " %lu %lu", (unsigned long)mship->conf_no, (unsigned long)mship->priority); foutput_read_ranges_0(fp, mship); fprintf(fp, " %lu", (unsigned long)mship->added_by); foutput_time(fp, mship->added_at); foutput_membership_type(fp, mship->type); } extern void foutput_membership(FILE *fp, Membership *mship) { switch (output_format) { case 0: case 1: foutput_membership_0(fp, mship); break; case 2: foutput_membership_2(fp, mship); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_string(FILE *fp, String str) { foutput_ulong((unsigned long)str.len, fp); putc('H', fp); if (str.len) fwrite(str.string, str.len, 1, fp); } static void foutput_priv_bits(FILE *fp, Priv_bits bits) { foutput_space(fp); foutput_bool(fp, bits.wheel); foutput_bool(fp, bits.admin); foutput_bool(fp, bits.statistic); foutput_bool(fp, bits.create_pers); foutput_bool(fp, bits.create_conf); foutput_bool(fp, bits.change_name); foutput_bool(fp, bits.flg7); foutput_bool(fp, bits.flg8); foutput_bool(fp, bits.flg9); foutput_bool(fp, bits.flg10); foutput_bool(fp, bits.flg11); foutput_bool(fp, bits.flg12); foutput_bool(fp, bits.flg13); foutput_bool(fp, bits.flg14); foutput_bool(fp, bits.flg15); foutput_bool(fp, bits.flg16); } static void foutput_personal_flags(FILE *fp, Personal_flags flags) { foutput_space(fp); foutput_bool(fp, flags.unread_is_secret); foutput_bool(fp, flags.flg2); foutput_bool(fp, flags.flg3); foutput_bool(fp, flags.flg4); foutput_bool(fp, flags.flg5); foutput_bool(fp, flags.flg6); foutput_bool(fp, flags.flg7); foutput_bool(fp, flags.flg8); } static void foutput_text_list(FILE *fp, const Local_to_global *text_list) { Local_text_no first; Local_text_no end; first = l2g_next_key(text_list, 0); end = l2g_first_appendable_key(text_list); if (first == 0) first = end; foutput_ulong((unsigned long)first, fp); foutput_ulong((unsigned long)(end - first), fp); if (first < end) { foutput_array_start(fp); while (first < end) foutput_ulong((unsigned long)l2g_lookup(text_list, first++), fp); foutput_array_end(fp); } else foutput_array_nodata(fp); } static void foutput_mark_list(FILE *fp, const Mark_list mark_list) { int i; fprintf(fp, " %lu", (unsigned long)mark_list.no_of_marks); if ( mark_list.marks != NULL && mark_list.no_of_marks > 0 ) { fprintf(fp, " {"); for ( i = 0; i < mark_list.no_of_marks; i++ ) foutput_mark(fp, mark_list.marks[ i ]); fprintf(fp, " }"); } else fprintf(fp, " *"); } static void foutput_mark(FILE *fp, Mark mark) { fprintf(fp, " %lu %lu", (unsigned long)mark.text_no, (unsigned long)mark.mark_type); } static void foutput_membership_list_0 (FILE * fp, Membership_list mlist) { int i; fprintf(fp, " %lu", (unsigned long)mlist.no_of_confs); if ( mlist.confs != NULL && mlist.no_of_confs > 0 ) { foutput_array_start(fp); for ( i = 0; i < mlist.no_of_confs; i++) foutput_membership_0(fp, mlist.confs + i); foutput_array_end(fp); } else foutput_array_nodata(fp); } static void foutput_membership_list_2 (FILE * fp, Membership_list mlist) { int i; fprintf(fp, " %lu", (unsigned long)mlist.no_of_confs); if ( mlist.confs != NULL && mlist.no_of_confs > 0 ) { foutput_array_start(fp); for ( i = 0; i < mlist.no_of_confs; i++) foutput_membership_2(fp, mlist.confs + i); foutput_array_end(fp); } else foutput_array_nodata(fp); } static void foutput_membership_list(FILE * fp, Membership_list mlist) { switch (output_format) { case 0: case 1: foutput_membership_list_0(fp, mlist); break; case 2: foutput_membership_list_2(fp, mlist); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_time(FILE *fp, time_t clk) { foutput_ulong((unsigned long) clk, fp); } static void foutput_member_list(FILE *fp, Member_list m_list) { int i; fprintf(fp, " %lu", (unsigned long)m_list.no_of_members); if ( m_list.members != NULL && m_list.no_of_members > 0 ) { foutput_array_start(fp); for ( i = 0; i < m_list.no_of_members; i++ ) foutput_member(fp, m_list.members[ i ]); foutput_array_end(fp); } else foutput_array_nodata(fp); } static void foutput_member_0(FILE *fp, Member member) { fprintf(fp, " %lu", (unsigned long)member.member); } static void foutput_member_2(FILE *fp, Member member) { fprintf(fp, " %lu %lu", (unsigned long)member.member, (unsigned long)member.added_by); foutput_time(fp, member.added_at); foutput_membership_type(fp, member.type); } static void foutput_member(FILE *fp, Member member) { switch (output_format) { case 0: case 1: foutput_member_0(fp, member); break; case 2: foutput_member_2(fp, member); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_conf_type_1(FILE *fp, Conf_type type) { foutput_space(fp); foutput_bool(fp, type.rd_prot); foutput_bool(fp, type.original); foutput_bool(fp, type.secret); foutput_bool(fp, type.letter_box); foutput_bool(fp, type.allow_anon); foutput_bool(fp, type.forbid_secret); foutput_bool(fp, type.reserved2); foutput_bool(fp, type.reserved3); } static void foutput_conf_type_0(FILE *fp, Conf_type type) { foutput_space(fp); foutput_bool(fp, type.rd_prot); foutput_bool(fp, type.original); foutput_bool(fp, type.secret); foutput_bool(fp, type.letter_box); } static void foutput_conf_type (FILE *fp, Conf_type type) { switch (output_format) { case 0: foutput_conf_type_0(fp, type); break; case 1: case 2: foutput_conf_type_1(fp, type); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_misc_info(FILE *fp, Misc_info misc) { foutput_ulong((unsigned long)misc.type, fp); switch(misc.type) { case recpt: case cc_recpt: case bcc_recpt: foutput_ulong((unsigned long)misc.datum.recipient, fp); break; case loc_no: foutput_ulong((unsigned long)misc.datum.local_no, fp); break; case rec_time: foutput_time(fp, misc.datum.received_at); break; case comm_to: case comm_in: case footn_to: case footn_in: foutput_ulong((unsigned long)misc.datum.text_link, fp); break; case sent_by: foutput_ulong((unsigned long)misc.datum.sender, fp); break; case sent_at: foutput_time(fp, misc.datum.sent_at); break; #ifndef COMPILE_CHECKS default: #endif case unknown_info: restart_kom("prot_a_output_misc_info: Illegal misc\n"); } } /* * Output the unsigned long L in the fastest way possible to the file * FP. Ok, it's ugly, but it's fast (or is it?). */ static void foutput_ulong (unsigned long l, FILE *fp) { static char buf[sizeof(unsigned long) * 3 + 1]; char *cp; foutput_space(fp); if (l < 10) putc("0123456789"[l], fp); else { cp = buf + sizeof(buf); while (l > 0) { *--cp = (l % 10) + '0'; l /= 10; } fwrite(cp, buf + sizeof(buf) - cp, 1, fp); } } void foutput_atsign(FILE *fp) { putc('@', fp); } void foutput_newline(FILE *fp) { putc('\n', fp); } void foutput_space(FILE *fp) { putc(' ', fp); } void foutput_array_start(FILE *fp) { fputs(" {", fp); } void foutput_array_end(FILE *fp) { fputs(" }", fp); } void foutput_array_nodata(FILE *fp) { fputs(" *", fp); } void foutput_bool(FILE *fp, int val) { putc(val + '0', fp); }