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