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