ram-output.c 24.7 KB
Newer Older
Linus Tolke Y's avatar
Linus Tolke Y committed
1
/*
2 3
 * $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.
Linus Tolke Y's avatar
Linus Tolke Y committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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.
 *
Per Cederqvist's avatar
Per Cederqvist committed
23
 * Please report bugs at http://bugzilla.lysator.liu.se/. 
Linus Tolke Y's avatar
Linus Tolke Y committed
24
 */
Per Cederqvist's avatar
Per Cederqvist committed
25 26 27 28 29 30 31 32 33 34 35
/*
 * 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.)
 */

David Byers's avatar
David Byers committed
36 37 38 39 40

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

Per Cederqvist's avatar
Per Cederqvist committed
41
#include <stdio.h>
42
#include "timewrap.h"
Per Cederqvist's avatar
Per Cederqvist committed
43
#include <sys/types.h>
44
#include <string.h>
Per Cederqvist's avatar
Per Cederqvist committed
45

46
#include "s-string.h"
Per Cederqvist's avatar
Per Cederqvist committed
47
#include "kom-types.h"
48
#include "ram-io.h"
Per Cederqvist's avatar
Per Cederqvist committed
49
#include "ram-output.h"
Per Cederqvist's avatar
Per Cederqvist committed
50
#include "lyskomd.h"
Per Cederqvist's avatar
Per Cederqvist committed
51
#include "log.h"
52
#include "local-to-global.h"
53
#include "server-time.h"
54
#include "eintr.h"
Per Cederqvist's avatar
Per Cederqvist committed
55

56
/* Forward declarations. */
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
static void foutput_aux_item_list(struct dbfile *, const Aux_item_list *);
static void foutput_conf_type (struct dbfile *, Conf_type);
static void foutput_mark(struct dbfile *, Mark);
static void foutput_mark_list(struct dbfile *, const Mark_list);
static void foutput_member(struct dbfile *, Member);
static void foutput_member_list(struct dbfile *, Member_list);
static void foutput_membership_list(struct dbfile *, Membership_list);
static void foutput_misc_info(struct dbfile *, Misc_info);
static void foutput_personal_flags(struct dbfile *, Personal_flags);
static void foutput_priv_bits(struct dbfile *, Priv_bits);
static void foutput_string(struct dbfile *, String);
static void foutput_text_list(struct dbfile *, const Local_to_global *);
static void foutput_time(struct dbfile *, time_t);
static void foutput_ulong(unsigned long, struct dbfile *);
static void foutput_space(struct dbfile *fp);
static void foutput_bool(struct dbfile *fp, int val);
static void foutput_array_start(struct dbfile *fp);
static void foutput_array_end(struct dbfile *fp);
static void foutput_array_nodata(struct dbfile *fp);
76

77
void
78
foutput_header(struct dbfile* fp, const char *magic, int include_timestamp)
79
{
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    if (strlen(magic) != 5)
	restart_kom("Bad magic %s: not 5 chars long.\n", magic);

    switch (fp->format)
    {
    case 0:
        fprintf(fp->fp, "%s\n", magic);
        break;
    case 1:
        fprintf(fp->fp, "%s:%05d\n", magic, fp->format);
        break;
    case 2:
    case 3:
	fprintf(fp->fp, "%s:%05d\n", magic, fp->format);
	if (include_timestamp)
	    fprintf(fp->fp, "%020lu\n", (unsigned long)current_time.tv_sec);
        break;
    default:
        restart_kom("foutput_header(): Unknown output format %d",
                    fp->format);
    }
101 102
}

103
static void
104
foutput_info_0(struct dbfile *fp, Info *info)
105
{
106
    fprintf(fp->fp, " %lu %lu %lu %lu %lu",
107 108 109 110 111 112 113
	    (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);
}

114
static void
115
foutput_info_2(struct dbfile *fp, Info *info)
116
{
117
    fprintf(fp->fp, " %lu %lu %lu %lu %lu %lu",
118 119 120 121 122 123 124 125 126 127
	    (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);
}


128
void foutput_info(struct dbfile *fp, Info *info)
129
{
130
    switch(fp->format)
131 132 133 134 135 136
    {
    case 0:
    case 1:
        foutput_info_0(fp, info);
        break;
    case 2:
137
    case 3:
138 139 140
        foutput_info_2(fp, info);
        break;
    default:
141
        restart_kom("unknown database format: %d", fp->format);
142 143 144 145 146
        break;
    }
}


147
static void
148
foutput_person_0 (struct dbfile *fp,
149
                  const Person *person)
150 151 152 153 154
{
    foutput_string (fp, person->username);
    foutput_priv_bits (fp, person->privileges);
    foutput_personal_flags (fp, person->flags);

155
    foutput_text_list (fp, &person->created_texts);
156 157 158 159 160
    foutput_mark_list (fp, person->marks);
    foutput_membership_list (fp, person->conferences);

    foutput_time(fp, person->last_login);

161
    fprintf (fp->fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu",
162 163 164 165 166 167 168 169 170 171 172 173 174
	     (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);
}

175
static void
176
foutput_person_2(struct dbfile *fp,
177
		 const Person *person)
Per Cederqvist's avatar
Per Cederqvist committed
178 179 180 181 182
{
    foutput_string (fp, person->username);
    foutput_priv_bits (fp, person->privileges);
    foutput_personal_flags (fp, person->flags);

183
    foutput_space(fp);
184
    l2g_write (fp, &person->created_texts);
Per Cederqvist's avatar
Per Cederqvist committed
185 186 187 188 189
    foutput_mark_list (fp, person->marks);
    foutput_membership_list (fp, person->conferences);

    foutput_time(fp, person->last_login);

190
    fprintf (fp->fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu",
Per Cederqvist's avatar
Per Cederqvist committed
191 192
	     (unsigned long) person -> user_area,
	     (unsigned long) person -> total_time_present, /* This is not a time,
Per Cederqvist's avatar
Per Cederqvist committed
193 194
						     * but a number of seconds.
						     */
Per Cederqvist's avatar
Per Cederqvist committed
195 196 197 198 199 200 201
	     (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);
Per Cederqvist's avatar
Per Cederqvist committed
202 203
}

204
extern void
205
foutput_person (struct dbfile *fp,
206
                const Person *person)
207
{
208
    switch(fp->format)
209 210 211 212 213 214
    {
    case 0:
    case 1:
        foutput_person_0(fp, person);
        break;
    case 2:
215
    case 3:
216 217 218
        foutput_person_2(fp, person);
        break;
    default:
219
        restart_kom("unknown database format: %d", fp->format);
220 221 222 223 224
        break;
    }
}


225
static void
226
foutput_conference_2(struct dbfile *fp,
227
		     const Conference *conf_c)
228 229 230
{
    foutput_string(fp, conf_c->name);
    foutput_member_list(fp, conf_c->members);
231
    foutput_space(fp);
232
    l2g_write(fp, &conf_c->texts);
233 234 235 236
    foutput_conf_type(fp, conf_c->type);

    foutput_time(fp, conf_c -> creation_time );
    foutput_time(fp, conf_c -> last_written );
Per Cederqvist's avatar
Per Cederqvist committed
237

238
    fprintf (fp->fp, " %lu %lu %lu %lu %lu %lu %lu",
239 240 241 242 243 244 245
	     (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);
246
    foutput_ulong((unsigned long) conf_c->keep_commented, fp);
247 248 249 250
    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);
}
Per Cederqvist's avatar
Per Cederqvist committed
251

252
static void
253
foutput_conference_1 (struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
254 255 256 257
		    Conference *conf_c)
{
    foutput_string(fp, conf_c->name);
    foutput_member_list(fp, conf_c->members);
258
    foutput_text_list(fp, &conf_c->texts);
Per Cederqvist's avatar
Per Cederqvist committed
259 260 261 262 263
    foutput_conf_type(fp, conf_c->type);

    foutput_time(fp, conf_c -> creation_time );
    foutput_time(fp, conf_c -> last_written );

264
    fprintf (fp->fp, " %lu %lu %lu %lu %lu %lu %lu",
Per Cederqvist's avatar
Per Cederqvist committed
265 266 267 268 269 270 271
	     (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);
Per Cederqvist's avatar
Per Cederqvist committed
272 273
}

274
static void
275
foutput_conference_0 (struct dbfile *fp,
276
                      Conference *conf_c)
277 278 279
{
    foutput_string(fp, conf_c->name);
    foutput_member_list(fp, conf_c->members);
280
    foutput_text_list(fp, &conf_c->texts);
281
    foutput_conf_type(fp, conf_c->type);
282 283 284 285

    foutput_time(fp, conf_c -> creation_time );
    foutput_time(fp, conf_c -> last_written );

286
    fprintf (fp->fp, " %lu %lu %lu %lu %lu %lu %lu",
287 288 289 290 291 292 293 294 295
	     (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);
}

296
void foutput_conference(struct dbfile *fp,
297 298
                        Conference *conf_c)
{
299
    switch(fp->format)
300 301 302 303 304 305 306 307
    {
    case 0:
        foutput_conference_0(fp, conf_c);
        break;
    case 1:
        foutput_conference_1(fp, conf_c);
        break;
    case 2:
308
    case 3:
309 310 311
        foutput_conference_2(fp, conf_c);
        break;
    default:
312
        restart_kom("unknown database format: %d", fp->format);
313 314 315 316 317
        break;
    }
}


Per Cederqvist's avatar
Per Cederqvist committed
318

319
static void
320
foutput_text_stat_0(struct dbfile *fp,
321
                    Text_stat *t_stat)
Per Cederqvist's avatar
Per Cederqvist committed
322 323 324 325 326
{
    int i;

    foutput_time(fp, t_stat->creation_time);
    
Per Cederqvist's avatar
Per Cederqvist committed
327 328 329 330 331 332
    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);
Per Cederqvist's avatar
Per Cederqvist committed
333 334 335

    if ( t_stat->misc_items != NULL && t_stat->no_of_misc > 0 )
    {
336
	foutput_array_start(fp);
Per Cederqvist's avatar
Per Cederqvist committed
337 338
	for ( i = 0; i < t_stat->no_of_misc; i++ )
	    foutput_misc_info(fp, t_stat->misc_items[ i ]);
339
	foutput_array_end(fp);
Per Cederqvist's avatar
Per Cederqvist committed
340 341
    }
    else
342
	foutput_array_nodata(fp);
343 344
}

345
static void
346
foutput_text_stat_2(struct dbfile *fp,
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
                    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 )
    {
362
	foutput_array_start(fp);
363 364
	for ( i = 0; i < t_stat->no_of_misc; i++ )
	    foutput_misc_info(fp, t_stat->misc_items[ i ]);
365
	foutput_array_end(fp);
366 367
    }
    else
368
	foutput_array_nodata(fp);
369 370 371 372 373

    foutput_ulong((unsigned long) t_stat->highest_aux, fp);
    foutput_aux_item_list(fp, &t_stat->aux_item_list);
}

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
static void
foutput_text_stat_3(struct dbfile *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->generation, fp);
    foutput_ulong((unsigned long) t_stat->reclamation, 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);
}

405
void
406
foutput_text_stat(struct dbfile *fp,
407 408
                  Text_stat *t_stat)
{
409
    switch (fp->format)
410 411 412 413 414 415 416 417
    {
    case 0:
    case 1:
        foutput_text_stat_0(fp, t_stat);
        break;
    case 2:
        foutput_text_stat_2(fp, t_stat);
        break;
418 419 420
    case 3:
        foutput_text_stat_3(fp, t_stat);
        break;
421
    default:
422
        restart_kom("unknown database format: %d\n", fp->format);
423 424 425 426 427 428
        break;
    }
}



429
static void
430
foutput_aux_flags(struct dbfile *fp,
431 432
                  Aux_item_flags f)
{
433 434 435 436 437 438 439 440 441
    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);
442 443
}

David Byers's avatar
David Byers committed
444
static void
445
foutput_aux_item_link(struct dbfile *fp,
David Byers's avatar
David Byers committed
446 447 448 449 450 451 452 453 454 455 456 457 458
                      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:
459
	;
David Byers's avatar
David Byers committed
460 461 462
    }
}

463
static void
464
foutput_aux_item(struct dbfile *fp,
465 466 467 468 469 470 471 472 473
                 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);
David Byers's avatar
David Byers committed
474
    foutput_aux_item_link(fp, &a_item->linked_item);
475 476
}

477
static void
478
foutput_aux_item_list(struct dbfile *fp,
479
		      const Aux_item_list *aux)
480 481 482 483 484 485
{
    int i;

    foutput_ulong((unsigned long) aux->length, fp);
    if (aux->items && aux->length > 0)
    {
486
        foutput_array_start(fp);
487 488
        for (i = 0; i < aux->length; i++)
            foutput_aux_item(fp, &aux->items[i]);
489
        foutput_array_end(fp);
490 491
    }
    else
492
        foutput_array_nodata(fp);
493 494 495
}
		      

496
static void
497
foutput_membership_type(struct dbfile *fp,
498 499
                        Membership_type type)
{
500 501 502 503 504 505 506 507 508
    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);
509 510
}

511
static void
512
foutput_read_ranges_0(struct dbfile *fp,
513 514 515 516 517 518 519 520 521 522
		      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)
523
	fprintf(fp->fp, " 0 0 *");
524 525 526 527 528 529 530 531 532 533
    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)
	{
534
	    fprintf(fp->fp, " %lu", begin->last_read);
535 536 537
	    begin++;
	}
	else
538
	    fprintf(fp->fp, " 0");
539 540

	if (begin == end)
541
	    fprintf(fp->fp, " 0 *");
542 543 544 545 546 547 548 549
	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;

550
	    fprintf(fp->fp, " %lu {", no_of_read);
551 552 553 554 555 556
	    
	    for (ptr = begin; ptr < end; ++ptr)
	    {
		Local_text_no lno;

		for (lno = ptr->first_read; lno <= ptr->last_read; lno++)
557
		    fprintf(fp->fp, " %lu", (unsigned long)lno);
558 559
	    }
	    
560
	    fprintf(fp->fp, " }");
561 562 563 564
	}
    }
}

565
static void
566
foutput_membership_0(struct dbfile *fp,
567 568 569 570
		   Membership *mship)
{
    foutput_time(fp, mship->last_time_read );
    
571
    fprintf(fp->fp, " %lu %lu",
572
	    (unsigned long)mship->conf_no,
573 574
	    (unsigned long)mship->priority);
    foutput_read_ranges_0(fp, mship);
575 576 577
}

static void
578
foutput_membership_2(struct dbfile *fp,
579 580 581 582
                     Membership *mship)
{
    foutput_time(fp, mship->last_time_read );
    
583
    fprintf(fp->fp, " %lu %lu",
584
	    (unsigned long)mship->conf_no,
585 586
	    (unsigned long)mship->priority);
    foutput_read_ranges_0(fp, mship);
587
    fprintf(fp->fp, " %lu", (unsigned long)mship->added_by);
588 589 590 591 592
    foutput_time(fp, mship->added_at);
    foutput_membership_type(fp, mship->type);
}


593
extern void
594
foutput_membership(struct dbfile *fp,
595 596
                   Membership *mship)
{
597
    switch (fp->format)
598 599
    {
    case 0:
600
    case 1:
601 602 603
        foutput_membership_0(fp, mship);
        break;
    case 2:
604
    case 3:
605 606 607
        foutput_membership_2(fp, mship);
        break;
    default:
608
        restart_kom("unknown database format: %d", fp->format);
609 610 611 612
        break;
    }
}

Per Cederqvist's avatar
Per Cederqvist committed
613 614


615
static void
616
foutput_string(struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
617 618
	       String str)
{
Per Cederqvist's avatar
Per Cederqvist committed
619
    foutput_ulong((unsigned long)str.len, fp);
620
    putc('H', fp->fp);
Per Cederqvist's avatar
Per Cederqvist committed
621 622

    if (str.len)
623
	fwrite(str.string, str.len, 1, fp->fp);
Per Cederqvist's avatar
Per Cederqvist committed
624 625
}

626
static void
627
foutput_priv_bits(struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
628 629
		  Priv_bits bits)
{
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
    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);
Per Cederqvist's avatar
Per Cederqvist committed
647 648
}

649
static void
650
foutput_personal_flags(struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
651 652
		       Personal_flags flags)
{
653 654 655 656 657 658 659 660 661
    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);
Per Cederqvist's avatar
Per Cederqvist committed
662 663 664
}	


665
static void
666
foutput_text_list(struct dbfile *fp,
667
		  const Local_to_global *text_list)
Per Cederqvist's avatar
Per Cederqvist committed
668
{
669 670
    Local_text_no first;
    Local_text_no end;
Per Cederqvist's avatar
Per Cederqvist committed
671

672 673
    first = l2g_next_key(text_list, 0);
    end = l2g_first_appendable_key(text_list);
674 675 676

    if (first == 0)
	first = end;
677 678 679
    
    foutput_ulong((unsigned long)first, fp);
    foutput_ulong((unsigned long)(end - first), fp);
Per Cederqvist's avatar
Per Cederqvist committed
680

681
    if (first < end)
Per Cederqvist's avatar
Per Cederqvist committed
682
    {
683
	foutput_array_start(fp);
684
	while (first < end)
685
	    foutput_ulong((unsigned long)l2g_lookup(text_list, first++), fp);
686
	foutput_array_end(fp);
Per Cederqvist's avatar
Per Cederqvist committed
687 688
    }
    else
689
	foutput_array_nodata(fp);
Per Cederqvist's avatar
Per Cederqvist committed
690 691 692
}


693
static void
694
foutput_mark_list(struct dbfile *fp,
695
		  const Mark_list mark_list)
Per Cederqvist's avatar
Per Cederqvist committed
696 697 698
{
    int i;

699
    fprintf(fp->fp, " %lu", (unsigned long)mark_list.no_of_marks);
Per Cederqvist's avatar
Per Cederqvist committed
700 701 702

    if ( mark_list.marks != NULL && mark_list.no_of_marks > 0 )
    {
703
	fprintf(fp->fp, " {");
Per Cederqvist's avatar
Per Cederqvist committed
704 705
	for ( i = 0; i < mark_list.no_of_marks; i++ )
	    foutput_mark(fp, mark_list.marks[ i ]);
706
	fprintf(fp->fp, " }");
Per Cederqvist's avatar
Per Cederqvist committed
707 708
    }
    else
709
	fprintf(fp->fp, " *");
Per Cederqvist's avatar
Per Cederqvist committed
710 711 712 713
    
}


714
static void
715
foutput_mark(struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
716 717
	     Mark mark)
{
718
    fprintf(fp->fp, " %lu %lu", (unsigned long)mark.text_no, (unsigned long)mark.mark_type);
Per Cederqvist's avatar
Per Cederqvist committed
719 720
}

721
static void
722
foutput_membership_list_0 (struct dbfile		* fp,
723
                           Membership_list  mlist)
Per Cederqvist's avatar
Per Cederqvist committed
724 725 726
{
    int i;
    
727
    fprintf(fp->fp, " %lu", (unsigned long)mlist.no_of_confs);
Per Cederqvist's avatar
Per Cederqvist committed
728 729 730

    if ( mlist.confs != NULL && mlist.no_of_confs > 0 )
    {
731
	foutput_array_start(fp);
Per Cederqvist's avatar
Per Cederqvist committed
732
	for ( i = 0; i < mlist.no_of_confs; i++)
733
	    foutput_membership_0(fp, mlist.confs + i);
734
	foutput_array_end(fp);
Per Cederqvist's avatar
Per Cederqvist committed
735 736
    }
    else
737
	foutput_array_nodata(fp);
Per Cederqvist's avatar
Per Cederqvist committed
738 739
}

740
static void
741
foutput_membership_list_2 (struct dbfile		* fp,
742
                           Membership_list  mlist)
Per Cederqvist's avatar
Per Cederqvist committed
743 744 745
{
    int i;
    
746
    fprintf(fp->fp, " %lu", (unsigned long)mlist.no_of_confs);
747 748

    if ( mlist.confs != NULL && mlist.no_of_confs > 0 )
Per Cederqvist's avatar
Per Cederqvist committed
749
    {
750
	foutput_array_start(fp);
751 752
	for ( i = 0; i < mlist.no_of_confs; i++)
	    foutput_membership_2(fp, mlist.confs + i);
753
	foutput_array_end(fp);
Per Cederqvist's avatar
Per Cederqvist committed
754 755
    }
    else
756
	foutput_array_nodata(fp);
Per Cederqvist's avatar
Per Cederqvist committed
757 758
}

759
static void
760
foutput_membership_list(struct dbfile        * fp,
761 762
                        Membership_list mlist)
{
763
    switch (fp->format)
764 765
    {
    case 0:
766
    case 1:
767 768 769
        foutput_membership_list_0(fp, mlist);
        break;
    case 2:
770
    case 3:
771 772 773
        foutput_membership_list_2(fp, mlist);
        break;
    default:
774
        restart_kom("unknown database format: %d", fp->format);
775 776 777 778
        break;
    }    
}

779
static void
780
foutput_time(struct dbfile *fp,
781
	     time_t clk)
Per Cederqvist's avatar
Per Cederqvist committed
782
{
783
    foutput_ulong((unsigned long) clk, fp);
Per Cederqvist's avatar
Per Cederqvist committed
784 785 786
}


787
static void
788
foutput_member_list(struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
789 790 791 792
		    Member_list m_list)
{
    int i;

793
    fprintf(fp->fp, " %lu", (unsigned long)m_list.no_of_members);
Per Cederqvist's avatar
Per Cederqvist committed
794 795
    if ( m_list.members != NULL && m_list.no_of_members > 0 )
    {
796
	foutput_array_start(fp);
Per Cederqvist's avatar
Per Cederqvist committed
797 798
	for ( i = 0; i < m_list.no_of_members; i++ )
	    foutput_member(fp, m_list.members[ i ]);
799
	foutput_array_end(fp);
Per Cederqvist's avatar
Per Cederqvist committed
800 801
    }
    else
802
	foutput_array_nodata(fp);
Per Cederqvist's avatar
Per Cederqvist committed
803 804 805
}


806
static void
807
foutput_member_0(struct dbfile *fp,
808 809
                 Member member)
{
810
    fprintf(fp->fp, " %lu", (unsigned long)member.member);
811 812 813
}

static void
814
foutput_member_2(struct dbfile *fp,
815 816
                 Member member)
{
817
    fprintf(fp->fp, " %lu %lu",
818 819 820 821 822 823
            (unsigned long)member.member,
            (unsigned long)member.added_by);
    foutput_time(fp, member.added_at);
    foutput_membership_type(fp, member.type);
}

824
static void
825
foutput_member(struct dbfile *fp,
Per Cederqvist's avatar
Per Cederqvist committed
826 827
	       Member member)
{
828
    switch (fp->format)
829 830 831 832 833 834
    {
    case 0:
    case 1:
        foutput_member_0(fp, member);
        break;
    case 2:
835
    case 3:
836 837 838
        foutput_member_2(fp, member);
        break;
    default:
839
        restart_kom("unknown database format: %d", fp->format);
840 841
        break;
    }
Per Cederqvist's avatar
Per Cederqvist committed
842 843
}

844
static void
845
foutput_conf_type_1(struct dbfile *fp,
846
                    Conf_type type)
Per Cederqvist's avatar
Per Cederqvist committed
847
{
848 849 850 851 852 853 854 855 856
    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);
Per Cederqvist's avatar
Per Cederqvist committed
857 858
}

859
static void
860
foutput_conf_type_0(struct dbfile *fp,
861
                    Conf_type type)
862
{
863 864 865 866 867
    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);
868 869
}

870
static void
871
foutput_conf_type (struct dbfile *fp,
872 873
                   Conf_type type)
{
874
    switch (fp->format)
875 876 877 878 879 880
    {
    case 0:
        foutput_conf_type_0(fp, type);
        break;
    case 1:
    case 2:
881
    case 3:
882 883 884
        foutput_conf_type_1(fp, type);
        break;
    default:
885
        restart_kom("unknown database format: %d", fp->format);
886 887 888 889
        break;
    }
}

Per Cederqvist's avatar
Per Cederqvist committed
890

891
static void
892
foutput_misc_info(struct dbfile *fp, 
Per Cederqvist's avatar
Per Cederqvist committed
893 894
		  Misc_info misc)
{
Per Cederqvist's avatar
Per Cederqvist committed
895
    foutput_ulong((unsigned long)misc.type, fp);
Per Cederqvist's avatar
Per Cederqvist committed
896 897 898 899 900
    
    switch(misc.type)
    {
    case recpt:
    case cc_recpt:
901
    case bcc_recpt:
902
	foutput_ulong((unsigned long)misc.datum.recipient, fp);
903
	break;
904

Per Cederqvist's avatar
Per Cederqvist committed
905
    case loc_no:
Per Cederqvist's avatar
Per Cederqvist committed
906
	foutput_ulong((unsigned long)misc.datum.local_no, fp);
Per Cederqvist's avatar
Per Cederqvist committed
907 908 909 910 911 912 913 914 915 916
	break;
	
    case rec_time:
	foutput_time(fp, misc.datum.received_at);
	break;
	
    case comm_to:
    case comm_in:
    case footn_to:
    case footn_in:
917
	foutput_ulong((unsigned long)misc.datum.text_link, fp);
Per Cederqvist's avatar
Per Cederqvist committed
918