]> andersk Git - moira.git/blob - afssync/sync.qc
Faster membership editing
[moira.git] / afssync / sync.qc
1 /* $Header$
2  *
3  *
4  *  (c) Copyright 1989 by the Massachusetts Institute of Technology.
5  *  For copying and distribution information, please see the file
6  *  <mit-copyright.h>.
7  */
8
9 #include <mit-copyright.h>
10 #include <stdio.h>
11 #include <sys/file.h>
12
13 #include <rx/xdr.h>
14 #include "ptint.h"
15 #include "ptserver.h"
16 #include "pterror.h"
17
18 #include <moira.h>
19 #include <moira_site.h>
20 #include <ctype.h>
21
22 #define min(x,y)        ((x) < (y) ? (x) : (y))
23 char *whoami = "sync";
24
25 char *malloc(), *strsave();
26 int dbase_fd;
27
28 int ucount = 0;
29 int gcount = 0;
30 int mcount = 0;
31
32 struct hash *users;
33 struct hash *groups;
34
35 struct member {
36     struct entry *user;
37     struct entry *group;
38     struct member *unext;
39     struct member *gnext;
40 };
41 struct entry {
42     long id;
43     struct member *members;
44 };
45
46 main(argc, argv)
47 int argc;
48 char **argv;
49 {
50 ##  char db[9];
51     
52     int status;
53     int ingerr();
54
55     if (!strcmp(argv[1], "-db")) {
56         strncpy(db, argv[2], sizeof(db)-1);
57         argc -= 2;
58         argv += 2;
59     }
60     if (argc != 2) {
61         fprintf(stderr, "usage: %s [-db sms] outfile\n", whoami);
62         exit(MR_ARGS);
63     }
64
65     dbase_fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0660);
66     if (dbase_fd < 0) {
67         perror("opening file %s", argv[1]);
68         exit(1);
69     }   
70     IIseterr(ingerr);
71
72     initialize_sms_error_table();
73     initialize_pt_error_table();
74     Initdb();                                   /* Initialize prdb */
75     
76     users = create_hash(10000);
77     groups = create_hash(15000);
78     
79 ##  ingres db
80 ##  set lockmode session where level = table
81 ##  begin transaction
82
83     do_passwd();
84     do_groups();
85
86 ##  end transaction
87 ##  exit
88
89     exit(MR_SUCCESS);
90 }
91
92
93 do_passwd()
94 ##{
95 ##  char login[9];
96 ##  int uid, id, status;
97     int t;
98     struct prentry tentry;
99     struct entry *u;
100
101     t = time(0);
102     fprintf(stderr, "Doing users: %s", ctime(&t));
103     
104 ##  range of u is users
105 ##  retrieve (login = u.#login, uid = u.#uid, id = u.users_id)
106 ##      where u.#uid > 0 and (u.#status = 1 or u.#status = 2) {
107             lowercase(strtrim(login));
108
109             if (FindByID(0,uid))
110                 status = PRIDEXIST;
111             else
112                 status = CreateEntry(0,login,&uid,1/*idflag*/,0/*gflag*/,
113                                      SYSADMINID/*oid*/, SYSADMINID/*cid*/);
114             if (status)
115                 fprintf(stderr, "Error adding user %s uid %d: %s\n",
116                         login, uid, error_message(status));
117             else {
118                 u = (struct entry *)malloc(sizeof(struct entry));
119                 u->id = uid;
120                 u->members = 0;
121                 hash_store(users, id, u);
122                 ucount++;
123             }
124 ##  }
125 ##}
126
127
128
129 do_groups()
130 ##{
131     long status, pos;
132     struct prentry gentry, uentry;
133     struct entry *u, *g;
134     struct member *m;
135     struct bucket **p, *b;
136     char namebuf[40];
137     int aid, t;
138 ##  char name[33];
139 ##  int gid, id, lid, hide;
140
141     t = time(0);
142     fprintf(stderr, "Doing groups: %s", ctime(&t));
143
144 ##  range of l is list
145 ##  range of m is imembers
146     /* get lock records */
147 ##  retrieve (name = l.modtime) where l.list_id = 0
148 ##  retrieve (name = users.modtime) where users.users_id = 0
149
150 ##  retrieve (name = l.#name, gid = l.#gid, lid = l.list_id, hide = l.hidden)
151 ##      where l.group != 0 and l.active != 0 and l.#gid > 0 {
152             lowercase(strtrim(name));
153             sprintf(namebuf, "system:%s", name);
154             aid = -gid;
155
156             if (FindByID(0, aid))
157                 status = PRIDEXIST;
158             else
159                 status = CreateEntry(0,namebuf,&aid,1/*idflag*/,PRGRP/*gflag*/,
160                                      SYSADMINID/*oid*/, SYSADMINID/*cid*/);
161             if (status)
162                 fprintf(stderr, "Error adding group %s id %d: %s\n",
163                         namebuf, aid, error_message(status));
164             else {
165                 g = (struct entry *)malloc(sizeof(struct entry));
166                 g->id = aid;
167                 g->members = 0;
168                 hash_store(groups, lid, g);
169                 gcount++;
170             }
171
172             /* Set modes on hidden lists (S----) */
173             if (hide && (status==0 || status==PRIDEXIST)) {
174                 pos = FindByID(0, aid);
175                 status = pr_Read(0, 0, pos, &gentry, sizeof(gentry));
176                 if (!status) {
177                     gentry.flags = htonl(PRGRP|PRACCESS|PRP_STATUS_ANY);
178                     status = pr_Write(0, 0, pos, &gentry, sizeof(gentry));
179                 }
180                 if (status)
181                     fprintf(stderr,
182                             "Error setting flags on group %s: %s\n",
183                             namebuf, error_message(status));
184             }
185 ##  }
186
187     t = time(0);
188     fprintf(stderr, "Doing members: %s", ctime(&t));
189
190 ##  retrieve (lid = m.list_id, id = m.member_id)
191 ##      where m.member_type = "USER" {
192       if ((u = (struct entry *)hash_lookup(users, id)) &&
193           (g = (struct entry *)hash_lookup(groups, lid))) {
194               m = (struct member *)malloc(sizeof(struct member));
195               m->user = u;
196               m->group = g;
197               m->unext = u->members;
198               m->gnext = g->members;
199               u->members = g->members = m;
200               mcount++;
201       }
202 ##  }
203     for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
204         for (b = *p; b; b = b->next) {
205             if ((u = (struct entry *)b->data)->members == 0)
206                 continue;
207             pos = FindByID(0, u->id);
208             pr_Read(0, 0, pos, &uentry, sizeof(uentry));
209             for (t=0, m=u->members; m && t<PRSIZE; m=m->unext, t++)
210                 uentry.entries[t] = htonl(m->group->id);
211             uentry.count = htonl(t);
212             pr_Write(0, 0, pos, &uentry, sizeof(uentry));
213             if (m) {
214                 pr_ReadEntry(0, 0, pos, &uentry);
215                 while (m) {
216                     AddToEntry(0, &uentry, pos, m->group->id);
217                     m = m->unext;
218                 }
219             }
220         }
221     }
222     for (p = &(groups->data[groups->size - 1]); p >= groups->data; p--) {
223         for (b = *p; b; b = b->next) {
224             if ((g = (struct entry *)b->data)->members == 0)
225                 continue;
226             pos = FindByID(0, g->id);
227             pr_Read(0, 0, pos, &gentry, sizeof(gentry));
228             for (t=0, m=g->members; m && t<PRSIZE; m=m->gnext, t++)
229                 gentry.entries[t] = htonl(m->user->id);
230             gentry.count = htonl(t);
231             pr_Write(0, 0, pos, &gentry, sizeof(gentry));
232             if (m) {
233                 pr_ReadEntry(0, 0, pos, &gentry);
234                 while (m) {
235                     AddToEntry(0, &gentry, pos, m->user->id);
236                     m = m->gnext;
237                 }
238             }
239         }
240     }
241
242     t = time(0);
243     fprintf(stderr, "Done (%d users, %d groups, %d members): %s",
244             ucount, gcount, mcount, ctime(&t));
245
246 ##}
247
248
249 /*
250  * ingerr: (supposedly) called when Ingres indicates an error.
251  * I have not yet been able to get this to work to intercept a
252  * database open error.
253  */
254 #define INGRES_DEADLOCK 4700
255
256 static int ingerr(num)
257     int *num;
258 {
259     char buf[256];
260     int ingres_errno;
261
262     switch (*num) {
263     case INGRES_DEADLOCK:
264         ingres_errno = MR_DEADLOCK;
265         break;
266     default:
267         ingres_errno = MR_INGRES_ERR;
268     }
269     com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
270     exit(ingres_errno);
271 }
This page took 0.058958 seconds and 5 git commands to generate.