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

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