]> andersk Git - moira.git/blob - incremental/afs.c
pr_ChangeEntry is smart enough to know that the id's haven't changed.
[moira.git] / incremental / afs.c
1 /* $Header$
2  *
3  * Do AFS incremental updates
4  *
5  * Copyright (C) 1989,1992 by the Massachusetts Institute of Technology
6  * for copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <sys/types.h>
11 #include <sys/file.h>
12 #include <strings.h>
13
14 #include <krb.h>
15 #include <moira.h>
16 #include <moira_site.h>
17
18 #include <afs/param.h>
19 #include <afs/cellconfig.h>
20 #include <afs/venus.h>
21 #include <afs/ptclient.h>
22 #include <afs/pterror.h>
23
24 #define STOP_FILE "/moira/afs/noafs"
25
26 #define file_exists(file) (access((file), F_OK) == 0)
27
28 char *whoami;
29
30 main(argc, argv)
31 char **argv;
32 int argc;
33 {
34     int beforec, afterc, i;
35     char *table, **before, **after;
36     char buf[1024];
37
38     for (i = getdtablesize() - 1; i > 2; i--)
39       close(i);
40
41     table = argv[1];
42     beforec = atoi(argv[2]);
43     before = &argv[4];
44     afterc = atoi(argv[3]);
45     after = &argv[4 + beforec];
46     whoami = argv[0];
47
48     strcpy(buf, table);
49     strcat(buf, " (");
50     for (i = 0; i < beforec; i++) {
51         if (i > 0)
52           strcat(buf, ",");
53         strcat(buf, before[i]);
54     }
55     strcat(buf, ")->(");
56     for (i = 0; i < afterc; i++) {
57         if (i > 0)
58           strcat(buf, ",");
59         strcat(buf, after[i]);
60     }
61     strcat(buf, ")");
62 #ifdef DEBUG
63     printf("%s\n", buf);
64 #endif
65
66     initialize_sms_error_table();
67     initialize_krb_error_table();
68
69     for (i=0; file_exists(STOP_FILE); i++) {
70         if (i > 30) {
71             critical_alert("incremental",
72                            "AFS incremental failed (%s exists): %s",
73                            STOP_FILE, buf);
74             exit(1);
75         }
76         sleep(60);
77     }
78
79     if (!strcmp(table, "users")) {
80         do_user(before, beforec, after, afterc);
81     } else if (!strcmp(table, "list")) {
82         do_list(before, beforec, after, afterc);
83     } else if (!strcmp(table, "members")) {
84         do_member(before, beforec, after, afterc);
85     } else if (!strcmp(table, "filesys")) {
86         do_filesys(before, beforec, after, afterc);
87     } else if (!strcmp(table, "quota")) {
88         do_quota(before, beforec, after, afterc);
89     }
90     exit(0);
91 }
92
93
94 do_cmd(cmd)
95 char *cmd;
96 {
97     int success = 0, tries = 0;
98
99     while (success == 0 && tries < 1) {
100         if (tries++)
101             sleep(5*60);
102         com_err(whoami, 0, "Executing command: %s", cmd);
103         if (system(cmd) == 0)
104             success++;
105     }
106     if (!success)
107         critical_alert("incremental", "failed command: %s", cmd);
108 }
109
110
111 add_user_lists(ac, av, user)
112     int ac;
113     char *av[];
114     char *user;
115 {
116     if (atoi(av[5])) {
117         sleep(1);                               /* give the ptserver room */
118         edit_group(1, av[0], "USER", user);
119     }
120 }
121
122
123 do_user(before, beforec, after, afterc)
124 char **before;
125 int beforec;
126 char **after;
127 int afterc;
128 {
129     int astate, bstate, auid, buid, code;
130     char hostname[64];
131     char *av[2];
132
133     auid = buid = astate = bstate = 0;
134     if (afterc > U_STATE) astate = atoi(after[U_STATE]);
135     if (beforec > U_STATE) bstate = atoi(before[U_STATE]);
136     if (afterc > U_UID) auid = atoi(after[U_UID]);
137     if (beforec > U_UID) buid = atoi(before[U_UID]);
138
139     /* We consider "half-registered" users to be active */
140     if (astate == 2) astate = 1;
141     if (bstate == 2) bstate = 1;
142
143     if (astate != 1 && bstate != 1)             /* inactive user */
144         return;
145
146     if (astate == bstate && auid == buid && 
147         !strcmp(before[U_NAME], after[U_NAME]))
148         /* No AFS related attributes have changed */
149         return;
150
151     code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
152     if (code) {
153         critical_alert("incremental", "Couldn't initialize libprot: %s",
154                        error_message(code));
155         return;
156     }
157     
158     if (astate == bstate) {
159         /* Only a modify has to be done */
160         code = pr_ChangeEntry(before[U_NAME], after[U_NAME],
161                               (auid==buid) ? 0 : auid, "");
162         if (code) {
163             critical_alert("incremental",
164                            "Couldn't change user %s (id %d) to %s (id %d): %s",
165                            before[U_NAME], buid, after[U_NAME], auid,
166                            error_message(code));
167         }
168         return;
169     }
170     if (bstate == 1) {
171         code = pr_DeleteByID(buid);
172         if (code && code != PRNOENT) {
173             critical_alert("incremental",
174                            "Couldn't delete user %s (id %d): %s",
175                            before[U_NAME], buid, error_message(code));
176         }
177         return;
178     }
179     if (astate == 1) {
180         code = pr_CreateUser(after[U_NAME], &auid);
181         if (code) {
182             critical_alert("incremental",
183                            "Couldn't create user %s (id %d): %s",
184                            after[U_NAME], auid, error_message(code));
185         }
186         if (beforec) {
187             /* Reactivating a user; get his group list */
188             gethostname(hostname, sizeof(hostname));
189             code = mr_connect(hostname);
190             if (!code) code = mr_auth("afs.incr");
191             if (code) {
192                 critical_alert("incremental",
193                                "Error contacting Moira server to retrieve grouplist of user %s: %s",
194                                after[U_NAME], error_message(code));
195                 return;
196             }
197             av[0] = "RUSER";
198             av[1] = after[U_NAME];
199             code = mr_query("get_lists_of_member", 2, av,
200                             add_user_lists, after[U_NAME]);
201             if (code)
202                 critical_alert("incremental",
203                                "Couldn't retrieve membership of user %s: %s",
204                                after[U_NAME], error_message(code));
205             mr_disconnect();
206         }
207         return;
208     }
209 }
210
211
212
213 do_list(before, beforec, after, afterc)
214 char **before;
215 int beforec;
216 char **after;
217 int afterc;
218 {
219     register int agid, bgid;
220     int ahide, bhide;
221     long code, id;
222     char hostname[64];
223     char g1[PR_MAXNAMELEN], g2[PR_MAXNAMELEN];
224     char *av[2];
225
226     agid = bgid = 0;
227     if (beforec > L_GID && atoi(before[L_ACTIVE]) && atoi(before[L_GROUP])) {
228         bgid = atoi(before[L_GID]);
229         bhide = atoi(before[L_HIDDEN]);
230     }
231     if (afterc > L_GID && atoi(after[L_ACTIVE]) && atoi(after[L_GROUP])) {
232         agid = atoi(after[L_GID]);
233         ahide = atoi(after[L_HIDDEN]);
234     }
235
236     if (agid == 0 && bgid == 0)                 /* Not active groups */
237         return;
238
239     code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
240     if (code) {
241         critical_alert("incremental", "Couldn't initialize libprot: %s",
242                        error_message(code));
243         return;
244     }
245
246     if (agid && bgid) {
247         if (strcmp(after[L_NAME], before[L_NAME])) {
248             /* Only a modify is required */
249             strcpy(g1, "system:");
250             strcpy(g2, "system:");
251             strcat(g1, before[L_NAME]);
252             strcat(g2, after[L_NAME]);
253             code = pr_ChangeEntry(g1, g2, -agid, "");
254             if (code) {
255                 critical_alert("incremental",
256                                "Couldn't change group %s (id %d) to %s (id %d): %s",
257                                before[L_NAME], -bgid, after[L_NAME], -agid,
258                                error_message(code));
259             }
260         }
261         if (ahide != bhide) {
262             code = pr_SetFieldsEntry
263                 (-agid, PR_SF_ALLBITS,
264                  (ahide ? PRP_STATUS_ANY : PRP_GROUP_DEFAULT) >> PRIVATE_SHIFT,
265                  0 /*ngroups*/, 0 /*nusers*/);
266             if (code) {
267                 critical_alert("incremental",
268                                "Couldn't set flags of group %s: %s",
269                                after[L_NAME], error_message(code));
270             }
271         }
272         return;
273     }
274     if (bgid) {
275         code = pr_DeleteByID(-bgid);
276         if (code && code != PRNOENT) {
277             critical_alert("incremental",
278                            "Couldn't delete group %s (id %d): %s",
279                            before[L_NAME], -bgid, error_message(code));
280         }
281         return;
282     }
283     if (agid) {
284         strcpy(g1, "system:");
285         strcat(g1, after[L_NAME]);
286         strcpy(g2, "system:administrators");
287         id = -agid;
288         code = pr_CreateGroup(g1, g2, &id);
289         if (code) {
290             critical_alert("incremental",
291                            "Couldn't create group %s (id %d): %s",
292                            after[L_NAME], id, error_message(code));
293             return;
294         }
295         if (ahide) {
296             code = pr_SetFieldsEntry
297                 (-agid, PR_SF_ALLBITS,
298                  (ahide ? PRP_STATUS_ANY : PRP_GROUP_DEFAULT) >> PRIVATE_SHIFT,
299                  0 /*ngroups*/, 0 /*nusers*/);
300             if (code) {
301                 critical_alert("incremental",
302                                "Couldn't set flags of group %s: %s",
303                                after[L_NAME], error_message(code));
304             }
305         }
306
307         /* We need to make sure the group is properly populated */
308         if (beforec < L_ACTIVE || atoi(before[L_ACTIVE]) == 0) return;
309
310         gethostname(hostname, sizeof(hostname));
311         code = mr_connect(hostname);
312         if (!code) code = mr_auth("afs.incr");
313         if (code) {
314             critical_alert("incremental",
315                            "Error contacting Moira server to resolve %s: %s",
316                            after[L_NAME], error_message(code));
317             return;
318         }
319         av[0] = "LIST";
320         av[1] = after[L_NAME];
321         get_members(2, av, after[L_NAME]);
322
323         mr_disconnect();
324         return;
325     }
326 }
327
328
329 do_member(before, beforec, after, afterc)
330 char **before;
331 int beforec;
332 char **after;
333 int afterc;
334 {
335     int code;
336     char *p;
337     
338     if ((beforec < 4 || !atoi(before[LM_END])) &&
339         (afterc < 4 || !atoi(after[LM_END])))
340         return;
341
342     code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
343     if (code) {
344         critical_alert("incremental", "Couldn't initialize libprot: %s",
345                        error_message(code));
346         return;
347     }
348
349     if (afterc) 
350         edit_group(1, after[LM_LIST], after[LM_TYPE], after[LM_MEMBER]);
351     if (beforec)
352         edit_group(0, before[LM_LIST], before[LM_TYPE], before[LM_MEMBER]);
353 }
354
355
356 get_members(ac, av, group)
357     int ac;
358     char *av[];
359     char *group;
360 {
361     int code=0;
362
363     if (strcmp(av[0], "LIST")) {
364         sleep(1);                               /* give the ptserver room */
365         edit_group(1, group, av[0], av[1]);
366     } else {
367         code = mr_query("get_end_members_of_list", 1, &av[1],
368                         get_members, group);
369         if (code)
370             critical_alert("incremental",
371                            "Couldn't retrieve full membership of %s: %s",
372                            group, error_message(code));
373     }
374     return code;
375 }
376
377
378 edit_group(op, group, type, member)
379     int op;
380     char *group;
381     char *type;
382     char *member;
383 {
384     char *p = 0;
385     char buf[PR_MAXNAMELEN];
386     int (*fn)();
387     int code;
388     static char local_realm[REALM_SZ+1] = "";
389     extern long pr_AddToGroup(), pr_RemoveUserFromGroup();
390
391     fn = op ? pr_AddToGroup : pr_RemoveUserFromGroup;
392     
393     /* The following KERBEROS code allows for the use of entities
394      * user@foreign_cell.
395      */
396     if (!local_realm[0])
397         krb_get_lrealm(local_realm, 1);
398     if (!strcmp(type, "KERBEROS")) {
399         p = index(member, '@');
400         if (p && !strcasecmp(p+1, local_realm))
401             *p = 0;
402     } else if (strcmp(type, "USER"))
403         return;                                 /* invalid type */
404
405     strcpy(buf, "system:");
406     strcat(buf, group);
407     code = (*fn)(member, buf);
408     if (code) {
409         if (op==0 && code == PRNOENT) return;
410         if (op==1 && code == PRIDEXIST) return;
411         if (strcmp(type, "KERBEROS") || code != PRNOENT) {
412             critical_alert("incremental",
413                            "Couldn't %s %s %s %s: %s",
414                            op ? "add" : "remove", member,
415                            op ? "to" : "from", buf,
416                            error_message(code));
417         }
418     }
419     if (p) *p = '@';
420 }
421
422
423 do_filesys(before, beforec, after, afterc)
424 char **before;
425 int beforec;
426 char **after;
427 int afterc;
428 {
429     char cmd[1024];
430     
431     if (beforec < FS_CREATE) {
432         if (afterc < FS_CREATE || atoi(after[FS_CREATE])==0 ||
433             strcmp(after[FS_TYPE], "AFS"))
434             return;
435
436         /* new locker creation */
437         sprintf(cmd, "%s/perl -I%s %s/afs_create.pl %s %s %s %s %s %s",
438                 BIN_DIR, BIN_DIR, BIN_DIR,
439                 after[FS_NAME], after[FS_L_TYPE], after[FS_MACHINE],
440                 after[FS_PACK], after[FS_OWNER], after[FS_OWNERS]);
441         do_cmd(cmd);
442         return;
443     }
444
445     /* What do we do?  When do we use FS_CREATE?
446      * 
447      * TYPE change:  AFS->ERR, ERR->AFS: rename/unmount/remount
448      * LOCKERTYPE change: rename/remount
449      * PACK change: remount
450      * LABEL change: rename/remount
451      * Deletion: rename/unmount
452      */
453     if (afterc < FS_CREATE) {
454         if (!strcmp(before[FS_TYPE], "AFS"))
455             critical_alert("incremental",
456                            "Could not delete AFS filesystem %s: Operation not supported\n",
457                            before[FS_NAME]);
458         return;
459     }
460
461     if (!strcmp(after[FS_TYPE], "AFS")) {
462         if (strcmp(before[FS_TYPE], "AFS")) {
463             critical_alert("incremental",
464                            "Cannot convert %s to an AFS filesystem: Operation not supported\n",
465                            after[FS_NAME]);
466         } else {
467             critical_alert("incremental",
468                            "Cannot change attributes of AFS filesystem %s: Operation not supported\n",
469                            after[FS_NAME]);
470         }
471         return;
472     }
473 }
474
475
476 do_quota(before, beforec, after, afterc)
477 char **before;
478 int beforec;
479 char **after;
480 int afterc;
481 {
482     char cmd[1024];
483
484     if (afterc < Q_DIRECTORY || strcmp("ANY", after[Q_TYPE]) ||
485         strncmp("/afs/", after[Q_DIRECTORY], 5))
486         return;
487
488     sprintf(cmd, "%s/perl -I%s %s/afs_quota.pl %s %s",
489             BIN_DIR, BIN_DIR, BIN_DIR,
490             after[Q_DIRECTORY], after[Q_QUOTA]);
491     do_cmd(cmd);
492     return;
493 }
This page took 1.520765 seconds and 5 git commands to generate.