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