]> andersk Git - moira.git/blob - gen/nfs.qc
added ingres error & deadlock detection
[moira.git] / gen / nfs.qc
1 /* $Header$
2  *
3  * This generates the files necessary to load an nfs server.
4  */
5
6 #include <stdio.h>
7 #include <sms.h>
8 #include <sms_app.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <sys/time.h>
12
13 #define NFS_DIR "/u1/sms/dcm/nfs"
14
15 #define min(x,y)        ((x) < (y) ? (x) : (y))
16
17 struct np {
18     char mach[33];
19     char dev[33];
20     char list[33];
21 };
22
23 struct fs {
24     int nfsphys;
25     char *dir;
26     int owner;
27     int owners;
28     struct qt *quota;
29 };
30
31
32 char *whoami = "nfs.gen";
33 char *malloc(), *strsave();
34 char *ingres_date_and_time(), *ingres_time(), *ingres_date();
35
36 main(argc, argv)
37 int argc;
38 char **argv;
39 {
40     char cmd[64];
41     struct stat sb;
42     int changed = 0;
43     int ingerr();
44
45     if (argc > 2) {
46         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
47         exit(SMS_ARGS);
48     }
49
50     IIseterr(ingerr);
51 ##  ingres sms
52
53     changed = do_nfs();
54
55 ##  exit
56
57     if (!changed) {
58         fprintf(stderr, "No files updated.\n");
59         if (argc == 2 && stat(argv[1], &sb) == 0)
60           exit(SMS_NO_CHANGE);
61     }
62
63     if (argc == 2) {
64         sprintf(cmd, "cd %s; cp /u1/sms/bin/install_* .; tar cf %s .", NFS_DIR, argv[1]);
65         if (system(cmd))
66           exit(SMS_TAR_FAIL);
67     }
68
69     exit(SMS_SUCCESS);
70 }
71
72
73 /*
74  * ingerr: (supposedly) called when Ingres indicates an error.
75  * I have not yet been able to get this to work to intercept a
76  * database open error.
77  */
78 #define INGRES_DEADLOCK 4700
79
80 static int ingerr(num)
81     int *num;
82 {
83     char buf[256];
84     int ingres_errno;
85
86     switch (*num) {
87     case INGRES_DEADLOCK:
88         ingres_errno = SMS_DEADLOCK;
89         break;
90     default:
91         ingres_errno = SMS_INGRES_ERR;
92     }
93     com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
94     critical_alert("DCM", "NFS build encountered INGRES ERROR %d", *num);
95     exit(ingres_errno);
96 }
97
98
99 /* Generate the files.  Returns zero if nothing changed, non-zero otherwise. */
100
101 int do_nfs()
102 ##{
103 ##  char machname[33], listname[33];
104     struct save_queue *machs, *lists;
105     int changed;
106
107     machs = sq_create();
108     lists = sq_create();
109 ##  range of s is serverhosts
110 ##  retrieve (machname = trim(machine.name), listname = trim(s.value3))
111 ##      where machine.mach_id = s.mach_id and s.enable != 0 {
112       sq_save_unique_string(machs, strsave(machname));
113       sq_save_unique_string(lists, strsave(listname));
114 ##  }
115
116     changed = do_lists(lists);
117     changed += do_machs(machs);
118     return(changed);
119 ##}
120
121
122 /* Make all of the credentials lists that will be needed.  Returns 0 if
123  * no files were actually changed */
124
125 int do_lists(lists)
126 struct save_queue *lists;
127 ##{
128     struct save_queue *sq;
129     char file[64], *u;
130     struct hash *users, *do_everyone();
131     struct stat sb;
132     FILE *fd;
133 ##  char *listname, *lsname, lname[33], uname[9], *filetime;
134 ##  int uid, id, flag1, flag2, flag3, flag4;
135
136     sprintf(file, "%s/list-", NFS_DIR);
137     if (stat(file, &sb) == 0) {
138         filetime = ingres_date_and_time(sb.st_mtime);
139 ##      retrieve (flag1 = int4(interval("min", tblstats.modtime - filetime)))
140 ##              where tblstats.table = "users"
141 ##      retrieve (flag2 = int4(interval("min", tblstats.modtime - filetime)))
142 ##              where tblstats.table = "list"
143 ##      retrieve (flag3 = int4(interval("min", tblstats.modtime - filetime)))
144 ##              where tblstats.table = "members"
145 ##      retrieve (flag4 = int4(interval("min", tblstats.modtime - filetime)))
146 ##              where tblstats.table = "serverhosts"
147         if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0) {
148             fprintf(stderr, "The lists do not need to be rebuilt.\n");
149             return(0);
150         }
151     }
152
153     /* build the list of everyone, and store it in a file whose name
154      * corresponds to the empty list.
155      */
156     users = do_everyone();
157
158     fprintf(stderr, "Building specific lists\n");
159     /* now do each of the lists used by an NFS server */
160 ##  range of l is list
161 ##  range of l1 is list
162 ##  range of m is members
163 ##  range of u is users
164     while (sq_get_data(lists, &listname)) {
165         if (strlen(listname) == 0)
166           continue;
167         sprintf(file, "%s/list-%s", NFS_DIR, listname);
168         fd = fopen(file, "w");
169         if (!fd) {
170             fprintf(stderr, "cannot open %s for output\n", file);
171             exit(SMS_OCONFIG);
172         }
173         sq = sq_create();
174         sq_save_data(sq, listname);
175         while (sq_get_data(sq, &lsname)) {
176 ##          repeat retrieve (lname = trim(l.name))
177 ##              where m.list_id = l1.list_id and l1.name = @lsname and
178 ##                    m.member_type = "LIST" and m.member_id = l.list_id {
179               sq_save_unique_string(sq, lname);
180 ##          }
181 ##          repeat retrieve (id = m.member_id)
182 ##              where m.list_id = l1.list_id and l1.name = @lsname and
183 ##                    m.member_type = "USER" {
184               if (u = hash_lookup(users, id)) 
185                 fprintf(fd, "%s\n", u);
186 ##          }
187         }
188         sq_destroy(sq);
189         if (fclose(fd)) {
190             fprintf(stderr, "error closing %s\n", file);
191             exit(SMS_CCONFIG);
192         }
193     }
194     sq_destroy(lists);
195     return(1);
196 ##}
197
198
199 /*  Build the list of everybody. */
200 struct grp {
201     struct grp *next;
202     int id;
203 };
204 struct user {
205     char name[9];
206     int uid;
207     struct grp *lists;
208 };
209
210 struct hash *do_everyone()
211 ##{
212     char buf[BUFSIZ], *l;
213     struct hash *groups, *users;
214     struct user *u;
215     struct grp *g;
216     struct bucket *b, **p;
217 ##  char name[33];
218 ##  int gid, id, lid, maxid, uid;
219     FILE *fd;
220     int i;
221     struct save_queue *sq;
222
223     fprintf(stderr, "Building the list of everybody\n");
224     sprintf(buf, "%s/list-", NFS_DIR);
225     fd = fopen(buf, "w");
226     if (!fd) {
227         fprintf(stderr, "cannot open %s for output\n", buf);
228         exit(SMS_OCONFIG);
229     }
230
231     /* make space for group list */
232     groups = create_hash(15000);
233
234     /* retrieve simple groups */
235 ##  range of l is list
236 ##  retrieve (gid = l.#gid, lid = l.list_id)
237 ##      where l.group != 0 and l.active != 0 {
238       sprintf(buf, ":%d", gid);
239       hash_store(groups, lid, strsave(buf));
240 ##  }
241
242     /* get special cases: lists that aren't groups themselves but are
243      * members of groups. */
244     sq = sq_create();
245 ##  range of m is members
246 ##  retrieve (gid = list.#gid, lid = l.list_id)
247 ##      where l.active != 0 and list.active != 0 and m.member_type = "LIST" and
248 ##              m.member_id = l.list_id and m.list_id = list.list_id and
249 ##              list.group != 0 {
250       if (l = hash_lookup(groups, lid)) {
251           sprintf(buf, "%s:%d", l, gid);
252           free(l);
253       } else {
254           sprintf(buf, ":%d", gid);
255       }
256       hash_store(groups, lid, strsave(buf));
257       sq_save_data(sq, lid);
258 ##  }
259
260     while (sq_get_data(sq, &id)) {
261 ##      repeat retrieve (lid = l.list_id) where l.active != 0 and
262 ##              m.member_type = "LIST" and m.member_id = l.list_id and
263 ##              m.list_id = @id {
264           if (l = hash_lookup(groups, lid)) {
265               sprintf(buf, "%s%s", l, hash_lookup(groups, id));
266               free(l);
267               l = strsave(buf);
268           } else {
269               l = hash_lookup(groups, id);
270           }
271           hash_store(groups, lid, l);
272           sq_save_unique_data(sq, lid);
273 ##      }
274     }
275     sq_destroy(sq);
276
277     /* now do grplists */
278     users = create_hash(10000);
279 ##  range of u is users
280 ##  retrieve (id = u.users_id, name = u.login, uid = u.#uid)
281 ##       where u.status = 1 {
282       u = (struct user *) malloc(sizeof(struct user));
283       strcpy(u->name, strtrim(name));
284       u->uid = uid;
285       u->lists = NULL;
286       hash_store(users, id, u);
287 ##  }
288
289 ##  repeat retrieve (lid = m.list_id, id = m.member_id)
290 ##      where m.member_type = "USER" {
291       if ((u = (struct user *) hash_lookup(users, id)) &&
292           (hash_lookup(groups, lid) != NULL)) {
293           g = (struct grp *) malloc(sizeof(struct grp));
294           g->next = u->lists;
295           u->lists = g;
296           g->id = lid;
297       }
298 ##  }
299
300     for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
301         for (b = *p; b; b = b->next) {
302             i = 0;
303             u = (struct user *)b->data;
304             sprintf(buf, "%s:%d", u->name, u->uid);
305             for (g = u->lists; g; g = g->next)
306               if (l = hash_lookup(groups, g->id)) {
307                   i++;
308                   strcat(buf, l);
309               }
310             /* should free stuff here... */
311             if (i > 1) {
312                 remove_duplicate_groups(buf);
313             }
314             b->data = strsave(buf);
315             fprintf(fd, "%s\n", buf);
316         }
317     }
318
319     fclose(fd);
320     free(groups);
321     return(users);
322 ##}
323
324 #define MAXGROUPS 256
325
326 remove_duplicate_groups(p)
327 register char *p;
328 {
329     register char *pp;
330     char *index();
331     register int *mp;
332     int memory[MAXGROUPS], i, *mg = &memory[MAXGROUPS-1];
333
334     bzero(memory, MAXGROUPS * sizeof(int));
335     p = index(p, ':');
336     p++;
337     while (p = index(p, ':')) {
338         i = atoi(++p);
339         pp = p;
340         for (mp = memory; *mp && mp < mg; mp++)
341           if (*mp == i) {
342               if (p = index(p, ':'))
343                 strcpy(pp, ++p);
344               else {
345                   *(--pp) = 0;
346               }
347               p = pp - 2;
348               break;
349           }
350         *mp = i;
351     }
352 }
353
354
355 /* Now do each of the servers, linking the credentials list file and 
356  * compiling the quota and dirs files.
357  */
358
359 int do_machs(machs)
360 struct save_queue *machs;
361 ##{
362 ##  char *machname, listname[33], dev[33], *device, dir[64], fstype[9];
363 ##  char *filetime;
364 ##  int uid, quota, id, gid, flag1, flag2, flag3, flag4;
365     char file[64], f1[64], f2[64], *cp, *index();
366     int prevuid, quotasum;
367     FILE *fd;
368     struct stat sb;
369     struct save_queue *sq;
370
371 /*
372     sprintf(file, "%s/list-", NFS_DIR);
373     if (stat(file, &sb) == 0) {
374         filetime = ingres_date_and_time(sb.st_mtime);
375  #      retrieve (flag1 = int4(interval("min", tblstats.modtime - filetime)))
376  #              where tblstats.table = "serverhosts"
377  #      retrieve (flag2 = int4(interval("min", tblstats.modtime - filetime)))
378  #              where tblstats.table = "filesys"
379  #      retrieve (flag3 = int4(interval("min", tblstats.modtime - filetime)))
380  #              where tblstats.table = "nfsquota"
381  #      retrieve (flag4 = int4(interval("min", tblstats.modtime - filetime)))
382  #              where tblstats.table = "nfsphys"
383         if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0) {
384             fprintf(stderr, "The machine files do not need to be rebuilt.\n");
385             return(0);
386         }
387     }
388 */
389
390     fprintf(stderr, "Building machine files\n");
391
392 ##  range of s is serverhosts
393 ##  range of m is machine
394 ##  range of n is nfsphys
395 ##  range of q is nfsquota
396 ##  range of f is filesys
397 ##  range of u is users
398 ##  range of l is list
399     while (sq_get_data(machs, &machname)) {
400 ##      repeat retrieve (listname = trim(s.value3))
401 ##          where s.mach_id = m.mach_id and m.name = @machname
402         strtrim(machname);
403         sprintf(f1, "%s/list-%s", NFS_DIR, listname);
404         sprintf(f2, "%s/%s.cred", NFS_DIR, machname);
405         unlink(f2); /* ignore errors on this unlink */
406         if (link(f1, f2)) {
407             fprintf(stderr, "Cannot link %s to %s\n", f1, f2);
408             exit(SMS_OCONFIG);
409         }
410         sq = sq_create();
411 ##      repeat retrieve (dev = trim(n.#device))
412 ##          where n.mach_id = m.mach_id and m.name = @machname {
413           sq_save_data(sq, strsave(dev));
414 ##      }
415         while (sq_get_data(sq, &device)) {
416 ##          repeat retrieve (id = n.nfsphys_id) where n.mach_id = m.mach_id and
417 ##              m.#name = @machname and n.#device = @device
418             while (cp = index(device, '/')) *cp = '@';
419             sprintf(file, "%s/%s.%s.quotas", NFS_DIR, machname, device);
420             fd = fopen(file, "w");
421             if (!fd) {
422                 fprintf(stderr, "cannot open %s for output\n", file);
423                 exit(SMS_OCONFIG);
424             }
425             prevuid = -1;
426             quotasum = 0;
427 ##          repeat retrieve (uid = u.#uid, quota = q.#quota)
428 ##              where q.users_id = u.users_id and q.filsys_id = f.filsys_id and
429 ##                    f.phys_id = @id and u.status != 0 sort by #uid {
430                 if (uid != prevuid) {
431                     if (quotasum)
432                       fprintf(fd, "%d %d\n", prevuid, quotasum);
433                     prevuid = uid;
434                     quotasum = quota;
435                 } else {
436                     quotasum += quota;
437                 }
438 ##          }
439             if (quotasum)
440               fprintf(fd, "%d %d\n", prevuid, quotasum);
441             if (fclose(fd)) {
442                 fprintf(stderr, "error closing %s", file);
443                 exit(SMS_CCONFIG);
444             }
445             sprintf(file, "%s/%s.%s.dirs", NFS_DIR, machname, device);
446             fd = fopen(file, "w");
447             if (!fd) {
448                 fprintf(stderr, "cannot open %s for output\n", file);
449                 exit(SMS_OCONFIG);
450             }
451 ##          repeat retrieve (dir = trim(f.#name), fstype = trim(f.lockertype),
452 ##                           uid = u.#uid, gid = l.#gid)
453 ##              where f.phys_id = @id and f.owner = u.users_id and 
454 ##                    f.owners = l.list_id and f.createflg != 0 {
455               fprintf(fd, "%s %d %d %s\n", dir, uid, gid, fstype);
456 ##          }
457             if (fclose(fd)) {
458                 fprintf(stderr, "error closing %s", file);
459                 exit(SMS_CCONFIG);
460             }
461         }
462         sq_destroy(sq);
463     }
464     return(1);
465 ##}
This page took 0.075926 seconds and 5 git commands to generate.