]> andersk Git - moira.git/blob - gen/nfs.dc
36683030be03a29c611fe521da156eef7afd75c4
[moira.git] / gen / nfs.dc
1 /* $Header$
2  *
3  * This generates the files necessary to load an nfs server.
4  *
5  *  (c) Copyright 1988, 1990 by the Massachusetts Institute of Technology.
6  *  For copying and distribution information, please see the file
7  *  <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <stdio.h>
12 #include <moira.h>
13 #include <moira_site.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 EXEC SQL INCLUDE sqlca;
18
19
20 #define min(x,y)        ((x) < (y) ? (x) : (y))
21
22 char *whoami = "nfs.gen";
23 char *malloc(), *strsave();
24 char nfs_dir[64];
25 struct hash *users, *groups;
26
27
28 main(argc, argv)
29 int argc;
30 char **argv;
31 {
32     char cmd[64];
33     struct stat sb;
34     int changed = 0;
35
36     if (argc > 2) {
37         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
38         exit(MR_ARGS);
39     }
40
41     initialize_sms_error_table();
42     sprintf(nfs_dir, "%s/nfs", DCM_DIR);
43
44 #ifsql INGRES
45     EXEC SQL CONNECT moira;
46     EXEC SQL SET LOCKMODE SESSION WHERE LEVEL=TABLE, READLOCK=SHARED;
47 #endsql
48 #ifsql INFORMIX
49     EXEC SQL DATABASE moira;
50 #endsql
51
52     changed = do_nfs();
53
54 #ifsql INGRES
55     EXEC SQL DISCONNECT;
56 #endsql
57 #ifsql INFORMIX
58     EXEC SQL CLOSE DATABASE;
59 #endsql
60
61     if (!changed) {
62         fprintf(stderr, "No files updated.\n");
63         if (argc == 2 && stat(argv[1], &sb) == 0)
64           exit(MR_NO_CHANGE);
65     }
66
67     if (argc == 2) {
68         sprintf(cmd, "cd %s; cp %s/nfs/* .; tar cf %s .",
69                 nfs_dir, SMS_DIR, argv[1]);
70         if (system(cmd))
71           exit(MR_TAR_FAIL);
72     }
73
74     exit(MR_SUCCESS);
75 }
76
77
78 /* Generate the files.  Returns zero if nothing changed, non-zero otherwise. */
79
80 int do_nfs()
81 {
82     EXEC SQL BEGIN DECLARE SECTION;
83     char machname[41], listname[33];
84     EXEC SQL END DECLARE SECTION;
85     struct save_queue *machs, *lists;
86     int changed;
87
88     machs = sq_create();
89     lists = sq_create();
90
91     /* The following is declarative, not executed,
92      * and so is dependent on where it is in the file,
93      * not in the order of execution of statements.
94      */
95     EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
96     EXEC SQL DECLARE s_cursor CURSOR FOR
97       SELECT m.name, s.value3
98       FROM machine m, serverhosts s
99       WHERE m.mach_id = s.mach_id AND s.service = 'NFS' AND s.enable != 0;
100     EXEC SQL OPEN s_cursor;
101     while (1) {
102         EXEC SQL FETCH s_cursor INTO :machname, :listname;
103         if (sqlca.sqlcode != 0) break;
104         sq_save_unique_string(machs, strsave(strtrim(machname)));
105         sq_save_unique_string(lists, strsave(strtrim(listname)));
106       }
107     EXEC SQL CLOSE s_cursor;
108
109     changed = do_lists(lists);
110     EXEC SQL COMMIT;
111     changed += do_machs(machs);
112     return(changed);
113  sqlerr:
114     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
115     critical_alert("DCM", "NFS build encountered DATABASE ERROR %d",
116                    sqlca.sqlcode);
117     exit(MR_INGRES_ERR);
118 }
119
120
121 /* Make all of the credentials lists that will be needed.  Returns 0 if
122  * no files were actually changed */
123
124 int do_lists(lists)
125 struct save_queue *lists;
126 {
127     char file[64], *u;
128     struct stat sb;
129     FILE *fd;
130     EXEC SQL BEGIN DECLARE SECTION;
131     char *listname, *lsname, lname[33], uname[9];
132     int uid, id, flag1, flag2, flag3, flag4;
133     EXEC SQL END DECLARE SECTION;
134
135     sprintf(file, "%s/list-", nfs_dir);
136     /*
137     if (stat(file, &sb) == 0) {
138         if ((ModDiff (&flag1, "users", sb.st_mtime)) ||
139             (ModDiff (&flag2, "list", sb.st_mtime)) ||
140             (ModDiff (&flag3, "imembers", sb.st_mtime)) ||
141             (ModDiff (&flag4, "serverhosts", sb.st_mtime))) exit (MR_DATE);
142         if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0) {
143             fprintf(stderr, "The lists do not need to be rebuilt.\n");
144             return(0);
145         }
146     }
147     */
148
149     /* get locks */
150     EXEC SQL SELECT modtime INTO :lname FROM list WHERE list_id = 0;
151     EXEC SQL SELECT modtime INTO :lname FROM users WHERE users_id = 0;
152
153     /* build the list of everyone, and store it in a file whose name
154      * corresponds to the empty list.
155      */
156     do_everyone();
157
158     fprintf(stderr, "Building specific lists\n");
159     /* now do each of the lists used by an NFS server */
160
161     while (sq_get_data(lists, &listname)) {
162         if (strlen(listname) == 0)
163           continue;
164         sprintf(file, "%s/list-%s", nfs_dir, listname);
165         fd = fopen(file, "w");
166         if (!fd) {
167             fprintf(stderr, "cannot open %s for output\n", file);
168             exit(MR_OCONFIG);
169         }
170
171         EXEC SQL DECLARE m_cursor CURSOR FOR
172           SELECT m.member_id
173           FROM imembers m, list l
174           WHERE m.list_id=l.list_id AND l.name = :listname AND
175             m.member_type='USER'
176           ORDER BY member_id;
177         EXEC SQL OPEN m_cursor;
178         while (1) {
179             EXEC SQL FETCH m_cursor INTO :id;
180             if (sqlca.sqlcode != 0) break;
181             if (u = hash_lookup(users, id))
182               fprintf(fd, "%s\n", u);
183         }
184         EXEC SQL CLOSE m_cursor;
185         if (fclose(fd) == EOF) {
186             fprintf(stderr, "error closing %s\n", file);
187             exit(MR_CCONFIG);
188         }
189     }
190 /* don't free here either
191     sq_destroy(lists);
192  */
193     return(1);
194  sqlerr:
195     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
196     critical_alert("DCM", "NFS build encountered DATABASE ERROR %d",
197                    sqlca.sqlcode);
198     exit(MR_INGRES_ERR);
199 }
200
201
202 /*  Build the list of everybody. */
203 struct grp {
204     struct grp *next;
205     char *lid;
206 };
207 struct user {
208     char name[9];
209     int uid;
210     struct grp *lists;
211 };
212
213
214 do_everyone()
215 {
216     char buf[BUFSIZ], *l;
217     struct user *u;
218     struct grp *g;
219     struct bucket *b, **p;
220     EXEC SQL BEGIN DECLARE SECTION;
221     char name[33];
222     int gid, id, lid, maxid, uid;
223     EXEC SQL END DECLARE SECTION;
224     FILE *fd;
225     int i;
226     struct save_queue *sq;
227
228     fprintf(stderr, "Building the list of everybody\n");
229     sprintf(buf, "%s/list-", nfs_dir);
230     fd = fopen(buf, "w");
231     if (!fd) {
232         fprintf(stderr, "cannot open %s for output\n", buf);
233         exit(MR_OCONFIG);
234     }
235
236     /* make space for group list */
237     groups = create_hash(15000);
238
239     /* retrieve simple groups */
240     EXEC SQL DECLARE l_cursor CURSOR FOR
241      SELECT gid, list_id
242      FROM list
243      WHERE grouplist != 0 AND active != 0
244      ORDER BY list_id;
245     EXEC SQL OPEN l_cursor;
246     while (1) {
247         EXEC SQL FETCH l_cursor INTO :gid, :lid;
248         if (sqlca.sqlcode != 0) break;
249         sprintf(buf, ":%d", gid);
250         hash_store(groups, lid, strsave(buf));
251       }
252     EXEC SQL CLOSE l_cursor;
253
254     /* now do grplists */
255     users = create_hash(10000);
256     EXEC SQL DECLARE u_cursor CURSOR FOR
257       SELECT users_id, login, uid
258       FROM users
259       WHERE status = 1
260       ORDER BY users_id;
261     EXEC SQL OPEN u_cursor;
262     while (1) {
263         EXEC SQL FETCH u_cursor INTO :id, :name, :uid;
264         if (sqlca.sqlcode != 0) break;
265         u = (struct user *) malloc(sizeof(struct user));
266         strcpy(u->name, strtrim(name));
267         u->uid = uid;
268         u->lists = NULL;
269         hash_store(users, id, u);
270       }
271     EXEC SQL CLOSE u_cursor;
272
273     EXEC SQL DECLARE m_cursor2 CURSOR FOR
274       SELECT list_id, member_id
275       FROM imembers
276       WHERE member_type = 'USER'
277       ORDER BY list_id;
278     EXEC SQL OPEN m_cursor2;
279     while (1) {
280         EXEC SQL FETCH m_cursor2 INTO :lid, :id;
281         if (sqlca.sqlcode != 0) break;
282         if ((u = (struct user *) hash_lookup(users, id)) &&
283             ((l = hash_lookup(groups, lid)) != NULL)) {
284             g = (struct grp *) malloc(sizeof(struct grp));
285             g->next = u->lists;
286             u->lists = g;
287             g->lid = l;
288           }
289       }
290     EXEC SQL CLOSE m_cursor2;
291
292     for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
293         for (b = *p; b; b = b->next) {
294             u = (struct user *)b->data;
295             sprintf(buf, "%s:%d", u->name, u->uid);
296             for (g = u->lists; g; g = g->next)
297               strcat(buf, g->lid);
298             b->data = strsave(buf);
299             fprintf(fd, "%s\n", buf);
300         }
301     }
302
303     fclose(fd);
304     free(groups);
305     return(1);
306  sqlerr:
307     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
308     critical_alert("DCM", "NFS build encountered DATABASE ERROR %d",
309                    sqlca.sqlcode);
310     exit(MR_INGRES_ERR);
311 }
312
313
314 /* Now do each of the servers, linking the credentials list file and 
315  * compiling the quota and dirs files.
316  */
317
318 int do_machs(machs)
319 struct save_queue *machs;
320 {
321     EXEC SQL BEGIN DECLARE SECTION;
322     char *machname, listname[33], dev[33], dir[81], fstype[9];
323     int uid, quota, id, gid, flag1, flag2, flag3, flag4;
324     EXEC SQL END DECLARE SECTION;
325     char file[64], f1[64], f2[64], *cp, *index();
326     int prevuid, quotasum, olddev, oldmach;
327     FILE *fd;
328     struct hash *machines;
329
330     fprintf(stderr, "Building machine files\n");
331
332     /* acquire locks on machines & filesystems */
333     EXEC SQL SELECT modtime INTO :listname FROM users WHERE users_id = 0;
334     EXEC SQL SELECT modtime INTO :listname FROM machine WHERE mach_id = 0;
335     EXEC SQL SELECT modtime INTO :listname FROM filesys WHERE filsys_id = 0;
336
337     machines = create_hash(100);
338     while (sq_get_data(machs, &machname)) {
339         EXEC SQL SELECT s.value3, m.mach_id
340           INTO :listname, :id
341           FROM serverhosts s, machine m
342           WHERE s.mach_id = m.mach_id AND m.name = :machname AND 
343             s.service = 'NFS';
344         strtrim(machname);
345         sprintf(f1, "%s/list-%s", nfs_dir, strtrim(listname));
346         sprintf(f2, "%s/%s.cred", nfs_dir, machname);
347         unlink(f2); /* ignore errors on this unlink */
348         if (link(f1, f2)) {
349             fprintf(stderr, "Cannot link %s to %s\n", f1, f2);
350             exit(MR_OCONFIG);
351         }
352         hash_store(machines, id, machname);
353     }
354
355
356     olddev = oldmach = -1;
357     fd = stdin;
358
359     EXEC SQL DECLARE q_cursor CURSOR FOR
360       SELECT DISTINCT q.quota, q.entity_id, q.phys_id, n.device, n.mach_id 
361       FROM quota q, nfsphys n
362       WHERE n.nfsphys_id = q.phys_id AND q.phys_id != 0 AND
363         n.status < 16 AND q.type = 'USER'
364       ORDER BY n.mach_id, q.phys_id, q.entity_id;
365     EXEC SQL OPEN q_cursor;
366     while (1) {
367         EXEC SQL FETCH q_cursor INTO :quota, :uid, :flag1, :dev, :flag2;
368         if (sqlca.sqlcode != 0) break;
369         if (flag1 != olddev || flag2 != oldmach) {
370             if (quotasum)
371               fprintf(fd, "%d %d\n", prevuid, quotasum);
372             if (flag2 == 0 || !hash_lookup(machines, flag2))
373               continue;
374             if (fd != stdin)
375               fclose(fd);
376             olddev = flag1;
377             oldmach = flag2;
378             while (cp = index(dev, '/')) *cp = '@';
379             sprintf(file, "%s/%s.%s.quotas", nfs_dir,
380                     hash_lookup(machines, flag2), strtrim(dev));
381             fd = fopen(file, "w");
382             if (!fd) {
383                 fprintf(stderr, "cannot open %s for output\n", file);
384                 exit(MR_OCONFIG);
385             }
386             prevuid = -1;
387             quotasum = 0;
388         }
389         if (uid != prevuid) {
390             if ((cp = hash_lookup(users, prevuid)) &&
391                 (cp = index(cp, ':')))
392               prevuid = atoi(cp+1);
393             if (quotasum)
394               fprintf(fd, "%d %d\n", prevuid, quotasum);
395             prevuid = uid;
396             quotasum = quota;
397         } else {
398             quotasum += quota;
399         }
400     }
401     EXEC SQL CLOSE q_cursor;
402     if ((cp = hash_lookup(users, prevuid)) &&
403         (cp = index(cp, ':')))
404       prevuid = atoi(cp+1);
405     if (quotasum)
406       fprintf(fd, "%d %d\n", prevuid, quotasum);
407     if (fd != stdin && fclose(fd) == EOF) {
408         fprintf(stderr, "error closing %s", file);
409         exit(MR_CCONFIG);
410       }
411
412     olddev = oldmach = -1;
413     fd = stdin;
414     EXEC SQL DECLARE q_cursor2 CURSOR FOR
415       SELECT DISTINCT q.quota, q.entity_id, q.phys_id, n.device, n.mach_id,
416         n.status 
417       FROM quota q, nfsphys n
418       WHERE n.nfsphys_id = q.phys_id AND q.phys_id != 0 AND
419         n.status > 15 AND q.type = 'GROUP'
420       ORDER BY mach_id, phys_id, entity_id;
421     EXEC SQL OPEN q_cursor2;
422     while (1) {
423         EXEC SQL FETCH q_cursor2 INTO :quota, :gid, :flag1, :dev,
424                 :flag2, :flag3;
425         if (sqlca.sqlcode != 0) break;
426         if (flag1 != olddev || flag2 != oldmach) {
427             if (quotasum)
428               fprintf(fd, "%d %d\n", prevuid, quotasum);
429             if (flag2 == 0 || !hash_lookup(machines, flag2))
430               continue;
431             if (fd != stdin)
432               fclose(fd);
433             olddev = flag1;
434             oldmach = flag2;
435             while (cp = index(dev, '/')) *cp = '@';
436             sprintf(file, "%s/%s.%s.quotas", nfs_dir,
437                     hash_lookup(machines, flag2), strtrim(dev));
438             fd = fopen(file, "w");
439             if (!fd) {
440                 fprintf(stderr, "cannot open %s for output\n", file);
441                 exit(MR_OCONFIG);
442             }
443             prevuid = -1;
444             quotasum = 0;
445         }
446         if (gid != prevuid) {
447             if (cp = hash_lookup(groups, prevuid))
448               prevuid = atoi(cp + 1);
449             if (quotasum)
450               fprintf(fd, "%d %d\n", prevuid, quotasum);
451             prevuid = gid;
452             quotasum = quota;
453         } else {
454             quotasum += quota;
455         }
456     }
457     EXEC SQL CLOSE q_cursor2;
458     if (cp = hash_lookup(groups, prevuid))
459       prevuid = atoi(cp + 1);
460     if (quotasum)
461       fprintf(fd, "%d %d\n", prevuid, quotasum);
462     if (fd != stdin && fclose(fd) == EOF) {
463         fprintf(stderr, "error closing %s", file);
464         exit(MR_CCONFIG);
465       }
466
467     olddev = oldmach = -1;
468     fd = stdin;
469
470     EXEC SQL DECLARE q_cursor3 CURSOR FOR
471       SELECT DISTINCT f.name, f.lockertype, u.uid, l.gid, f.phys_id, 
472                 f.mach_id, n.device 
473       FROM users u, list l, nfsphys n, filesys f
474       WHERE u.users_id = f.owner AND 
475               l.list_id = f.owners AND
476               f.createflg != 0 AND f.phys_id != 0 AND
477               f.type = 'NFS' AND 
478               f.phys_id = n.nfsphys_id
479       ORDER BY mach_id, phys_id;
480     EXEC SQL OPEN q_cursor3;
481     while (1) {
482         EXEC SQL FETCH q_cursor3 INTO :dir, :fstype, :uid, :gid, :flag1,
483                         :flag2, :dev;
484         if (sqlca.sqlcode != 0) break;
485         if (flag1 != olddev || flag2 != oldmach) {
486             if (fd != stdin)
487               fclose(fd);
488             olddev = flag1;
489             oldmach = flag2;
490             while (cp = index(dev, '/')) *cp = '@';
491             sprintf(file, "%s/%s.%s.dirs", nfs_dir,
492                     hash_lookup(machines, flag2), strtrim(dev));
493             fd = fopen(file, "w");
494             if (!fd) {
495                 fprintf(stderr, "cannot open %s for output\n", file);
496                 exit(MR_OCONFIG);
497             }
498         }
499         fprintf(fd, "%s %d %d %s\n", strtrim(dir), uid, gid, strtrim(fstype));
500     }    
501     EXEC SQL CLOSE q_cursor3;
502     if (fclose(fd) == EOF) {
503         fprintf(stderr, "error closing %s", file);
504         exit(MR_CCONFIG);
505     }
506     return(1);
507  sqlerr:
508     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
509     critical_alert("DCM", "NFS build encountered DATABASE ERROR %d",
510                    sqlca.sqlcode);
511     exit(MR_INGRES_ERR);
512 }
This page took 0.066043 seconds and 3 git commands to generate.