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

Revision 17452, 7.4 KB checked in by zacheiss, 23 years ago (diff)
Include unistd.h for lseek prototype and SEEK_* macros
Line 
1/*
2 *
3 * expunge -- program to expunge a meeting; i.e. really delete those
4 *            deleted transaction.  This program is linked to a server
5 *            so it can use the privileged procedure of create_mtg, and
6 *            the like.
7 *
8 */
9
10#include <stdio.h>
11#include <strings.h>
12#include <sys/types.h>
13#include <sys/file.h>
14#include <sys/stat.h>
15#include <unistd.h>
16
17#include <discuss/types.h>
18#include <discuss/dsc_et.h>
19#include <discuss/tfile.h>
20#include <discuss/interface.h>
21#include <discuss/acl.h>
22#include "mtg.h"
23
24#define NULL 0
25#define MAX_TRNS 1000
26#define min(a, b) (a < b ? a : b)
27
28static int tempf;
29static char *mtg_name = NULL, *location = NULL, *chairman = NULL, *trn_file = NULL;
30static char *backup_location = NULL;
31static char *future_location = NULL;
32static int found_eof = 0;
33static int error_occurred = 0;
34
35tfile unix_tfile ();
36char *malloc();
37
38extern char rpc_caller[];
39extern int has_privs;
40extern int errno;
41extern int no_nuke;
42
43main (argc, argv)
44int argc;
45char **argv;
46{
47     int i,n,low,high;
48     mtg_info old_mtg_info,new_mtg_info;
49     trn_info old_trn_info;
50     int result;
51     dsc_acl *acl_list,*new_acl_list;
52     dsc_acl_entry *ae;
53     char *new_modes;
54     tfile tf;
55     char control_name[256];
56     int control_fd;
57     
58     init_dsc_err_tbl();
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          default:
73               goto lusage;
74          }
75          if (location == NULL)
76               location = argv[i];
77          else goto lusage;
78     }
79
80     if (location == NULL)
81          goto lusage;                                  /* required */
82
83     has_privs = TRUE;                                  /* Tell discuss we're special */
84     strcpy (rpc_caller, "expunger");
85
86     /* First, we get the mtg info to make sure it exists */
87     get_mtg_info (location, &old_mtg_info, &result);
88     if (result != 0) {
89          fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
90          exit (1);
91     }
92
93     get_acl (location, &result, &acl_list);
94     if (result != 0) {
95          fprintf(stderr, "%s: %s while getting acl\n", location, error_message(result));
96          exit (1);
97     }
98
99     /* Create the new meeting */
100     backup_location = malloc (strlen(location)+5);     /* be generous */
101     strcpy (backup_location, location);
102     strcat (backup_location, "~");
103
104     future_location = malloc (strlen(location)+5);     /* be generous */
105     strcpy (future_location, location);
106     strcat (future_location, "#");
107
108     printf("Creating new meeting\n");
109     fflush(stdout);
110
111     if (mtg_name == NULL) {
112          mtg_name = old_mtg_info.long_name;
113     }
114     if (chairman == NULL) {
115          chairman = old_mtg_info.chairman;
116     }
117
118     /* get acl's on old meeting, so we can make it new one */
119     get_acl (location, &result, &new_acl_list);
120     if (result != 0) {
121          fprintf(stderr, "%s: %s while getting acl\n", backup_location, error_message(result));
122          exit (1);
123     }
124
125     create_mtg_priv (backup_location, mtg_name, old_mtg_info.public_flag,
126                      old_mtg_info.date_created, chairman,
127                      new_acl_list, &result);
128     if (result != 0) {
129          fprintf (stderr, "%s: %s while creating new meeting\n",
130                   location, error_message(result));
131          exit (1);
132     }
133     
134     /* now, do the actual expunging */
135     low = old_mtg_info.lowest;
136     high = old_mtg_info.highest;
137     create_temp ();
138
139expunge_range:
140     for (i = low; i <= high; i++) {
141          get_trn_info (location, i, &old_trn_info, &result);
142          if (result != 0 && result != DELETED_TRN && result != EXPUNGED_TRN) {
143               fprintf(stderr,
144                       "Error getting info for transaction [%04d]: %s\n",
145                       i, error_message(result));
146               error_occurred = TRUE;
147          } else if (result != 0) {             /* expunge it */
148               no_nuke = TRUE;
149               printf("Expunging transaction [%04d]\n", i);
150               expunge_trn (backup_location, i, &result);
151               no_nuke = FALSE;
152               if (result != 0) {
153                    fprintf(stderr,
154                            "Error expunging transaction [%04d]: %s\n",
155                            i, error_message(result));
156                    error_occurred = TRUE;
157               }
158          } else if (result == 0) {
159               ftruncate(tempf,0);
160               lseek(tempf,0,SEEK_SET);
161               tf = unix_tfile (tempf);
162
163               get_trn (location, i, tf, &result);
164               if (result != 0) {
165                    fprintf(stderr, "Error getting transaction [%04d]: %s\n",
166                            i, error_message(result));
167                    error_occurred = TRUE;
168                    free(old_trn_info. author);
169                    free(old_trn_info.subject);
170                    continue;
171               }
172
173               tdestroy (tf);
174               lseek(tempf,0,SEEK_SET);
175
176               tf = unix_tfile (tempf);
177               no_nuke = TRUE;
178               add_trn_priv (backup_location, tf, old_trn_info.subject,
179                             old_trn_info.pref, old_trn_info.current,
180                             old_trn_info.author, old_trn_info.date_entered,
181                             &n, &result);
182               no_nuke = FALSE;
183               if (result != 0) {
184                    fprintf(stderr,
185                            "Error getting info for transaction %d: %s\n", i,
186                            error_message(result));
187                    error_occurred = TRUE;
188               }
189               free(old_trn_info.author);
190               free(old_trn_info.subject);
191          }
192     }
193
194     /* Check if any new transactions have been added */
195     free(old_mtg_info.long_name);
196     free(old_mtg_info.chairman);
197     free(old_mtg_info.location);
198     get_mtg_info(location, &old_mtg_info, &result);
199     if (result != 0) {
200          fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
201          error_occurred = TRUE;
202     } else if (old_mtg_info.highest > high) {          /* New transactions added */
203          low = high+1;
204          high = old_mtg_info.highest;
205          goto expunge_range;
206     }
207
208     strcpy(control_name, location);
209     strcat(control_name, "/control");
210     if ((control_fd = open (control_name, O_RDWR, 0700)) < 0) {
211          error_occurred = TRUE;
212     } else {
213          flock(control_fd, LOCK_EX);           /* Hold meeting by the balls */
214          free(old_mtg_info.long_name);
215          free(old_mtg_info.chairman);
216          free(old_mtg_info.location);
217
218          no_nuke = TRUE;
219          get_mtg_info(location, &old_mtg_info, &result);
220          if (result != 0) {           
221               fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result));
222               error_occurred = TRUE;
223               flock(control_fd,LOCK_UN);
224               close(control_fd);
225          } else if (old_mtg_info.highest > high) {             /* New transactions added */
226               low = high + 1;
227               high = old_mtg_info.highest;
228               flock(control_fd,LOCK_UN);
229               close(control_fd);
230               goto expunge_range;
231          }
232     }
233
234     /* When we get here, we have the old meeting locked.  Now we do the move
235        as atomically as we can */
236     if (!error_occurred) {
237          if (rename(location, future_location) < 0) {
238               perror("rename of old meeting failed");
239               exit (1);
240          }
241          if (rename(backup_location, location) < 0) {
242               perror("rename of new meeting");
243               exit (1);
244          }
245          remove_mtg (future_location, &result);
246          if (result != 0) {
247               fprintf(stderr, "%s: %s while removing new meeting.\n",
248                       location, error_message(result));
249               exit (1);
250          }
251     } else exit (1);                           /* error occurred */
252
253     exit (0);
254
255lusage:
256     fprintf(stderr, "usage: expunge mtg_location {-c chairman} {-n name}\n");
257     exit (1);
258}
259
260/*
261 *
262 * create_temp () -- Create temp file, and let it be tempf.
263 *
264 */
265create_temp()
266{
267     char filename [20];
268
269     strcpy (filename, "/tmp/rcXXXXXX");
270     mktemp (filename);
271
272     tempf = open (filename, O_RDWR | O_CREAT, 0700);
273     if (tempf < 0) {
274          fprintf (stderr, "Cannot open temp file\n");
275          exit (1);
276     }
277}
278
279
Note: See TracBrowser for help on using the repository browser.