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

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