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
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->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);
}

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



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

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

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

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

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

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

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

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

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

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

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

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


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

Per Cederqvist's avatar
Per Cederqvist committed
612 613


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

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

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

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


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

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

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

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


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

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

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


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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

Per Cederqvist's avatar
Per Cederqvist committed
889

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

Per Cederqvist's avatar
Per Cederqvist committed
904
    case loc_no:
Per Cederqvist's avatar
Per Cederqvist committed
905
	foutput_ulong((unsigned long)misc.datum.local_no, fp);
Per Cederqvist's avatar
Per Cederqvist committed
906 907 908 909 910 911 912 913 914 915
	break;
	
    case rec_time:
	foutput_time(fp, misc.datum.received_at);
	break;
	
    case comm_to:
    case comm_in:
    case footn_to:
    case footn_in:
916
	foutput_ulong((unsigned long)misc.datum.text_link, fp);
Per Cederqvist's avatar
Per Cederqvist committed
917 918 919
	break;
	
    case sent_by:
Per Cederqvist's avatar
Per Cederqvist committed
920
	foutput_ulong((unsigned long)misc.datum.sender, fp);
Per Cederqvist's avatar
Per Cederqvist committed
921 922 923 924 925 926 927 928 929
	break;
	
    case sent_at:
	foutput_time(fp, misc.datum.sent_at);
	break;

#ifndef COMPILE_CHECKS
    default:
#endif
930 931
    case unknown_info:
	restart_kom("prot_a_output_misc_info: Illegal misc\n");
Per Cederqvist's avatar
Per Cederqvist committed
932 933 934 935 936 937 938 939 940
    }
}


/* 
 * 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?).
 */

941
static void
Per Cederqvist's avatar
Per Cederqvist committed
942
foutput_ulong (unsigned long l,
943
	       struct dbfile *fp)
Per Cederqvist's avatar
Per Cederqvist committed
944
{
945
    static char   buf[sizeof(unsigned long) * 3 + 1];
Per Cederqvist's avatar
Per Cederqvist committed
946 947
    char         *cp;

948
    foutput_space(fp);
Per Cederqvist's avatar
Per Cederqvist committed
949
    if (l < 10)
950
	dbfile_putc("0123456789"[l], fp);
951 952 953 954 955 956