source: trunk/athena/bin/discuss/server/recover.c @ 2747

Revision 2747, 9.2 KB checked in by srz, 35 years ago (diff)
Added support for signatures.
Line 
1/*
2 *
3 *      Copyright (C) 1988, 1989 by the Massachusetts Institute of Technology
4 *      Developed by the MIT Student Information Processing Board (SIPB).
5 *      For copying information, see the file mit-copyright.h in this release.
6 *
7 */
8/*
9 *
10 * recover -- program to recover a meeting from the transaction file.
11 *            this program is linked to a server so it can use the
12 *            privileged procedures of create_mtg, and the like.
13 *
14 */
15
16#include <stdio.h>
17#include <strings.h>
18#include <sys/types.h>
19#include <sys/file.h>
20#include <sys/stat.h>
21
22#include <discuss/types.h>
23#include <discuss/dsc_et.h>
24#include <discuss/tfile.h>
25#include <discuss/interface.h>
26#include "mtg.h"
27
28#define NULL 0
29#define MAX_TRNS 20000
30#define min(a, b) (a < b ? a : b)
31
32static trn_base tb;
33static trn_hdr th;
34static int tempf;
35static int trnf;
36static int trnfsize;
37static int num_trns;
38static int current_pos;
39static char *mtg_name = NULL, *location = NULL, *chairman = NULL, *trn_file = NULL;
40static int trn_pos[MAX_TRNS];
41static int found_eof = 0;
42static char *temp_dir = "/tmp";
43
44tfile unix_tfile ();
45char *malloc();
46static fsize(),read_trn_hdr(),read_last_trn(),save_trn();
47
48extern char rpc_caller[];
49extern int has_privs, use_zephyr;
50
51main (argc, argv)
52int argc;
53char **argv;
54{
55     int i;
56
57     has_privs = TRUE;
58     use_zephyr = 0;
59
60     for (i = 1; i < argc; i++) {
61          if (*argv[i] == '-') switch (argv[i][1]) {
62          case 'c':
63               if (++i < argc)
64                    chairman = argv[i];
65               continue;
66
67          case 'n':
68               if (++i < argc)
69                    mtg_name = argv[i];
70               continue;
71
72           case 't':
73               if (++i < argc)
74                   temp_dir = argv[i];
75               continue;
76
77          default:
78               goto lusage;
79          }
80          if (trn_file == NULL)
81               trn_file = argv[i];
82          else if (location == NULL)
83               location = argv[i];
84          else goto lusage;
85     }
86
87     if (trn_file == NULL || location == NULL)
88          goto lusage;                                  /* required */
89
90     if ((trnf = open (trn_file, O_RDONLY, 0)) < 0) {
91          fprintf (stderr, "Can't open transaction file %s\n", trn_file);
92          exit(1);
93     }
94
95     trnfsize = fsize (trnf);
96     read_header();                             /* check meeting */
97
98
99     /* search for last transaction, which gives us our best toehold into
100        the meeting.  This is done by searching from the end of the meeting
101        for unique. */
102     read_last_trn();                           /* read last_trn into th */
103
104     if (th.current > MAX_TRNS) {
105          fprintf (stderr, "More transactions than expected: %d\n", th.current);
106          exit(1);
107     }
108
109     /* zero out array */
110     num_trns = th.current;
111     for (i = 0; i <= num_trns; i++) {
112          trn_pos[i] = 0;
113     }
114
115     /* loop to fill out transaction position array */
116     while (current_pos != 0) {
117          read_trn_hdr (current_pos);
118          trn_pos [th.current] = current_pos;
119
120          current_pos = th.prev_trn;
121     }
122
123     create_temp();
124
125     for (i = 1; i <= num_trns; i++) {
126          if (trn_pos [i] != 0)
127               save_trn (trn_pos [i]);
128          else {
129               int result;
130
131               expunge_trn(location, i, &result);
132               if (result != 0) {
133                    fprintf(stderr, "Error expunging transaction [%04d]: %s\n", i, error_message(result));
134                    exit(1);
135               }
136          }
137     }
138
139     exit (0);
140
141lusage:
142     fprintf(stderr, "usage: recover trn_file mtg_name {-c chairman} {-n name}\n");
143     exit (1);
144}
145
146read_header()
147{
148     int result;
149     int pos;
150
151     lseek(trnf,0,0);                           /* rewind file */
152     if (read (trnf, &tb, sizeof (trn_base)) < sizeof (trn_base)) {
153          fprintf (stderr, "Can't read trn_base\n");
154          exit(1);
155     }
156
157     if (tb.version != TRN_BASE_1) {
158          fprintf (stderr, "Invalid trn_base version\n");
159          exit(1);
160     }
161
162     if (tb.unique != TRN_BASE_UNIQUE) {
163          fprintf (stderr, "Invalid trn_base unique\n");
164          exit(1);
165     }
166
167     /* read the chairman */
168     if (chairman == NULL) {
169          if (tb.chairman_len > 255) {
170               fprintf (stderr, "Unreasonable chairman length\n");
171               exit(1);
172          }
173          chairman = malloc (tb.chairman_len);
174          if (lseek(trnf, tb.chairman_addr, 0) < 0) {
175no_chairman:
176               fprintf (stderr, "Can't read chairman\n");
177               exit(1);
178          }
179         
180          if (read (trnf, chairman, tb.chairman_len) < tb.chairman_len)
181               goto no_chairman;
182     }
183         
184     /* read the long name */
185     if (mtg_name == NULL) {
186          if (tb.long_name_len > 255) {
187               fprintf (stderr, "Unreasonable long_name length\n");
188               exit(1);
189          }
190          mtg_name = malloc (tb.long_name_len);
191          if (lseek(trnf, tb.long_name_addr, 0) < 0) {
192no_long_name:
193               fprintf (stderr, "Can't read long_name\n");
194               exit(1);
195          }
196         
197          if (read (trnf, mtg_name, tb.long_name_len) < tb.long_name_len)
198               goto no_long_name;
199     }
200
201     strcpy (rpc_caller, chairman);
202     /* got the params, now create the meeting */
203     create_mtg_priv (location, mtg_name, tb.public_flag, tb.date_created, chairman, NULL, &result);
204     if (result != 0) {
205          fprintf (stderr, "Couldn't create meeting, %s", error_message(result));
206          exit(1);
207     }
208
209     pos = sizeof (tb) + tb.long_name_len + tb.chairman_len;
210     if (pos == trnfsize) {
211          fprintf (stderr, "Empty meeting\n");
212          exit (0);
213     }
214}
215
216/*
217 *
218 * read_trn_hdr () -- Procedure to read a transaction header, erroring out
219 *                    if not kosher.
220 *
221 */
222static
223read_trn_hdr (position)
224int position;
225{
226     if (lseek (trnf, position, 0) < 0) {
227no_read:
228          fprintf (stderr, "Can't find transaction at %d\n", position);
229          exit (1);
230     }
231
232     if (read (trnf, &th, sizeof (th)) != sizeof (th))
233          goto no_read;
234
235     /* safety checks */
236     if (th.version != TRN_HDR_1) {
237          fprintf (stderr, "Invalid trn_hdr version at %d\n", position);
238          exit(1);
239     }
240
241     if (th.unique != TRN_HDR_UNIQUE) {
242          fprintf (stderr, "Invalid trn_hdr unique\n");
243          exit(1);
244     }
245
246     if (th.current <= 0 || th.author_len < 0 || th.subject_len < 0 || th.num_chars < 0 || th.num_lines < 0) {
247          fprintf (stderr, "Negative number\n");
248          exit(1);
249     }
250
251     if (th.author_addr+th.author_len > trnfsize || th.subject_addr+th.subject_len > trnfsize || th.text_addr+th.num_chars > trnfsize) {
252          fprintf (stderr, "Field past file\n");
253          exit(1);
254     }
255
256     return;
257}
258/*
259 *
260 * maybe_read_trn_hdr -- procedure to try to read a transaction header,
261 *                       returning true if successful.
262 *
263 */
264static
265maybe_read_trn_hdr(position)
266int position;
267{
268     if (lseek (trnf, position, 0) < 0) {
269          return (FALSE);
270     }
271
272     if (read (trnf, &th, sizeof (th)) != sizeof (th))
273          return (FALSE);
274
275     /* safety checks */
276     if (th.version != TRN_HDR_1) {
277          return (FALSE);
278     }
279
280     if (th.unique != TRN_HDR_UNIQUE) {
281          return (FALSE);
282     }
283
284     if (th.current <= 0 || th.author_len < 0 || th.subject_len < 0 || th.num_chars < 0 || th.num_lines < 0) {
285          return (FALSE);
286     }
287
288     if (th.author_addr+th.author_len > trnfsize || th.subject_addr+th.subject_len > trnfsize || th.text_addr+th.num_chars > trnfsize) {
289          return (FALSE);
290     }
291
292     return (TRUE);
293}
294
295/*
296 *
297 * read_last_trn -- brute force routine to just try reading transactions until
298 *                  get a success.
299 *
300 */
301static
302read_last_trn ()
303{
304     current_pos = trnfsize - sizeof (th) - 2;
305
306     while (current_pos > sizeof (tb)) {
307          if (maybe_read_trn_hdr (current_pos))
308               return;
309          current_pos--;
310     }
311}
312
313static
314save_trn (position)
315int position;
316{
317     char *th_subject, *th_author, *th_signature;
318     tfile tf;
319     int tfs,tocopy;
320     trn_nums result_trn;
321     int result;
322     char buffer[512];
323
324     read_trn_hdr (position);
325
326     th_subject = malloc (th.subject_len);
327     lseek (trnf, th.subject_addr, 0);
328     read (trnf, th_subject, th.subject_len);
329         
330     th_author = malloc (th.author_len);
331     lseek (trnf, th.author_addr, 0);
332     read (trnf, th_author, th.author_len);
333
334     th_signature = NULL;
335     if (strlen (th_author) + 1 != th.author_len) {
336          th_signature = th_author + strlen(th_author) + 1;
337     }
338
339     /* start temp file */
340     ftruncate(tempf,0);
341     lseek(tempf,0,0);
342
343     lseek(trnf, th.text_addr, 0);
344     tfs = th.num_chars;
345     while (tfs > 0) {
346          tocopy = min (512, tfs);
347          read (trnf, buffer, tocopy);
348          write (tempf, buffer, tocopy);
349          tfs -= tocopy;
350     }
351
352     lseek(tempf,0,0);
353
354     tf = unix_tfile (tempf);
355
356     add_trn_priv (location, tf, th_subject, th_signature, th.orig_pref, th.current, th_author, th.date_entered, 0, &result_trn, &result);
357     if (result != 0) {
358          fprintf (stderr, "Couldn't add transaction %d; %s", th.current, error_message(result));
359          exit(1);
360     }
361
362     free(th_author);
363     free(th_subject);
364     tdestroy (tf);
365     printf ("Added transaction %d\n", th.current);
366     return;
367}
368
369/*
370 *
371 * fsize () -- Routine to find out the size of a file.
372 *
373 */
374static
375fsize (d)
376int d;
377{
378     struct stat buf;
379
380     if (fstat (d, &buf) < 0)
381          return (0);
382
383     return (buf.st_size);
384}
385
386/*
387 *
388 * new_string (s)  --   Routine to create a copy of the given string, using
389 *                      malloc.
390 *
391 */
392static
393char *new_string (s)
394char *s;
395{
396     int len;
397     char *newstr;
398
399     len = strlen (s) + 1;
400     newstr = malloc (len);
401     strcpy (newstr, s);
402     return (newstr);
403}
404
405/*
406 *
407 * create_temp () -- Create temp file, and let it be tempf.
408 *
409 */
410create_temp()
411{
412     char *filename;
413
414     filename = malloc (strlen (temp_dir) + 10);
415     strcpy (filename, temp_dir);
416     strcat (filename, "/rcXXXXXX");
417     mktemp (filename);
418
419     tempf = open (filename, O_RDWR | O_CREAT, 0700);
420     if (tempf < 0) {
421          fprintf (stderr, "Cannot open temp file `%s'\n", filename);
422          exit (1);
423     }
424}
Note: See TracBrowser for help on using the repository browser.