source: trunk/athena/bin/discuss/server/byteswap.c @ 8855

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