source: trunk/third/moira/gen/nfs.pc @ 23178

Revision 23178, 12.3 KB checked in by broder, 16 years ago (diff)
Take a new snapshot from CVS for Moira, and add a debathena-moira-update-server package
Line 
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
24EXEC SQL INCLUDE sqlca;
25
26RCSID("$Header$");
27
28#define min(x, y)       ((x) < (y) ? (x) : (y))
29
30char *whoami = "nfs.gen";
31char *db = "moira/moira";
32char nfs_dir[MAXPATHLEN];
33struct hash *users, *groups;
34
35int do_nfs(void);
36int do_lists(struct save_queue *lists);
37void do_everyone(void);
38int do_machs(struct save_queue *machs);
39
40int 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
82int 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;
118sqlerr:
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
128int 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
139  /* build the list of everyone, and store it in a file whose name
140   * corresponds to the empty list.
141   */
142  do_everyone();
143
144  fprintf(stderr, "Building specific lists\n");
145  /* now do each of the lists used by an NFS server */
146
147  while (sq_get_data(lists, &listname))
148    {
149      if (strlen(listname) == 0)
150        continue;
151      sprintf(file, "%s/list-%s", nfs_dir, listname);
152      fd = fopen(file, "w");
153      if (!fd)
154        {
155          fprintf(stderr, "cannot open %s for output\n", file);
156          exit(MR_OCONFIG);
157        }
158
159      EXEC SQL DECLARE m_cursor CURSOR FOR
160        SELECT m.member_id
161        FROM imembers m, list l
162        WHERE m.list_id = l.list_id AND l.name = :listname
163        AND m.member_type = 'USER'
164        ORDER BY member_id;
165      EXEC SQL OPEN m_cursor;
166      while (1)
167        {
168          EXEC SQL FETCH m_cursor INTO :id;
169          if (sqlca.sqlcode)
170            break;
171          if ((u = hash_lookup(users, id)))
172            fprintf(fd, "%s\n", u);
173        }
174      EXEC SQL CLOSE m_cursor;
175      if (fclose(fd) == EOF)
176        {
177          fprintf(stderr, "error closing %s\n", file);
178          exit(MR_CCONFIG);
179        }
180    }
181/* don't free here either
182    sq_destroy(lists);
183 */
184  return 1;
185sqlerr:
186  db_error(sqlca.sqlcode);
187  exit(MR_DBMS_ERR);
188}
189
190
191/*  Build the list of everybody. */
192struct grp {
193  struct grp *next;
194  char *lid;
195};
196
197struct user {
198  char name[USERS_LOGIN_SIZE];
199  int uid;
200  struct grp *lists;
201};
202
203
204void do_everyone(void)
205{
206  const buflen = MAXPATHLEN;
207  char buf[MAXPATHLEN], *l;
208  struct user *u;
209  struct grp *g;
210  struct bucket *b, **p;
211  EXEC SQL BEGIN DECLARE SECTION;
212  char name[USERS_LOGIN_SIZE];
213  int gid, id, lid, uid;
214  EXEC SQL END DECLARE SECTION;
215  FILE *fd;
216
217  fprintf(stderr, "Building the list of everybody\n");
218  sprintf(buf, "%s/list-", nfs_dir);
219  fd = fopen(buf, "w");
220  if (!fd)
221    {
222      fprintf(stderr, "cannot open %s for output\n", buf);
223      exit(MR_OCONFIG);
224    }
225
226  /* make space for group list */
227  groups = create_hash(15000);
228
229  /* retrieve simple groups */
230  EXEC SQL DECLARE l_cursor CURSOR FOR
231    SELECT gid, list_id
232    FROM list
233    WHERE nfsgroup != 0 AND grouplist != 0 AND active != 0
234    ORDER BY list_id;
235  EXEC SQL OPEN l_cursor;
236  while (1)
237    {
238      EXEC SQL FETCH l_cursor INTO :gid, :lid;
239      if (sqlca.sqlcode)
240        break;
241      sprintf(buf, ":%d", gid);
242      hash_store(groups, lid, strdup(buf));
243    }
244  EXEC SQL CLOSE l_cursor;
245
246  /* now do grplists */
247  users = create_hash(10000);
248  EXEC SQL DECLARE u_cursor CURSOR FOR
249    SELECT users_id, login, unix_uid
250    FROM users
251    WHERE status = 1
252    ORDER BY users_id;
253  EXEC SQL OPEN u_cursor;
254  while (1)
255    {
256      EXEC SQL FETCH u_cursor INTO :id, :name, :uid;
257      if (sqlca.sqlcode)
258        break;
259      u = malloc(sizeof(struct user));
260      strcpy(u->name, strtrim(name));
261      u->uid = uid;
262      u->lists = NULL;
263      hash_store(users, id, u);
264    }
265  EXEC SQL CLOSE u_cursor;
266
267  EXEC SQL DECLARE m_cursor2 CURSOR FOR
268    SELECT list_id, member_id
269    FROM imembers
270    WHERE member_type = 'USER'
271    ORDER BY list_id;
272  EXEC SQL OPEN m_cursor2;
273  while (1)
274    {
275      EXEC SQL FETCH m_cursor2 INTO :lid, :id;
276      if (sqlca.sqlcode)
277        break;
278      if ((u = hash_lookup(users, id)) && (l = hash_lookup(groups, lid)))
279        {
280          g = malloc(sizeof(struct grp));
281          g->next = u->lists;
282          u->lists = g;
283          g->lid = l;
284        }
285    }
286  EXEC SQL CLOSE m_cursor2;
287
288  for (p = &(users->data[users->size - 1]); p >= users->data; p--)
289    {
290      for (b = *p; b; b = b->next)
291        {
292          u = (struct user *)b->data;
293          sprintf(buf, "%s:%d:101", u->name, u->uid);
294          for (g = u->lists; g; g = g->next)
295            {
296              if ((strlen(buf) + strlen(g->lid)) <= buflen)
297                strcat(buf, g->lid);
298              else
299                {
300                  com_err(whoami, 0, "truncated server-side grp list for %s",
301                          u->name);
302                  break;
303                }
304            }
305          b->data = strdup(buf);
306          fprintf(fd, "%s\n", buf);
307        }
308    }
309
310  fclose(fd);
311  return;
312
313sqlerr:
314  db_error(sqlca.sqlcode);
315  exit(MR_DBMS_ERR);
316}
317
318
319/* Now do each of the servers, linking the credentials list file and
320 * compiling the quota and dirs files.
321 */
322
323int do_machs(struct save_queue *machs)
324{
325  EXEC SQL BEGIN DECLARE SECTION;
326  char *machname, listname[SERVERHOSTS_VALUE3_SIZE];
327  char dev[NFSPHYS_DEVICE_SIZE], dir[FILESYS_NAME_SIZE];
328  char fstype[FILESYS_LOCKERTYPE_SIZE];
329  int uid, quota, id, gid, flag1, flag2, flag3;
330  EXEC SQL END DECLARE SECTION;
331  char file[MAXPATHLEN], f1[MAXPATHLEN], f2[MAXPATHLEN], *cp;
332  int prevuid, quotasum, olddev, oldmach;
333  FILE *fd;
334  struct hash *machines;
335
336  fprintf(stderr, "Building machine files\n");
337
338  machines = create_hash(100);
339  while (sq_get_data(machs, &machname))
340    {
341      EXEC SQL SELECT s.value3, m.mach_id
342        INTO :listname, :id
343        FROM serverhosts s, machine m
344        WHERE s.mach_id = m.mach_id AND m.name = :machname AND
345        s.service = 'NFS';
346      strtrim(machname);
347      sprintf(f1, "%s/list-%s", nfs_dir, strtrim(listname));
348      sprintf(f2, "%s/%s.cred", nfs_dir, machname);
349      unlink(f2); /* ignore errors on this unlink */
350      if (link(f1, f2))
351        {
352          fprintf(stderr, "Cannot link %s to %s\n", f1, f2);
353          exit(MR_OCONFIG);
354        }
355      hash_store(machines, id, machname);
356    }
357
358  olddev = oldmach = -1;
359  fd = stdin;
360
361  EXEC SQL DECLARE q_cursor CURSOR FOR
362    SELECT DISTINCT q.quota, q.entity_id, q.phys_id, n.device, n.mach_id
363    FROM quota q, nfsphys n
364    WHERE n.nfsphys_id = q.phys_id AND q.phys_id != 0 AND
365    n.status < 16 AND q.type = 'USER'
366    ORDER BY n.mach_id, q.phys_id, q.entity_id;
367  EXEC SQL OPEN q_cursor;
368  while (1)
369    {
370      EXEC SQL FETCH q_cursor INTO :quota, :uid, :flag1, :dev, :flag2;
371      if (sqlca.sqlcode)
372        break;
373      if (flag1 != olddev || flag2 != oldmach)
374        {
375          if (quotasum)
376            fprintf(fd, "%d %d\n", prevuid, quotasum);
377          if (flag2 == 0 || !hash_lookup(machines, flag2))
378            continue;
379          if (fd != stdin)
380            fclose(fd);
381          olddev = flag1;
382          oldmach = flag2;
383          while ((cp = strchr(dev, '/')))
384            *cp = '@';
385          sprintf(file, "%s/%s.%s.quotas", nfs_dir,
386                  (char *)hash_lookup(machines, flag2), strtrim(dev));
387          fd = fopen(file, "w");
388          if (!fd)
389            {
390              fprintf(stderr, "cannot open %s for output\n", file);
391              exit(MR_OCONFIG);
392            }
393          prevuid = -1;
394          quotasum = 0;
395        }
396      if (uid != prevuid)
397        {
398          if ((cp = hash_lookup(users, prevuid)) &&
399              (cp = strchr(cp, ':')))
400            prevuid = atoi(cp + 1);
401          if (quotasum)
402            fprintf(fd, "%d %d\n", prevuid, quotasum);
403          prevuid = uid;
404          quotasum = quota;
405        }
406      else
407        quotasum += quota;
408    }
409  EXEC SQL CLOSE q_cursor;
410  if ((cp = hash_lookup(users, prevuid)) &&
411      (cp = strchr(cp, ':')))
412    prevuid = atoi(cp + 1);
413  if (quotasum)
414    fprintf(fd, "%d %d\n", prevuid, quotasum);
415  if (fd != stdin && fclose(fd) == EOF)
416    {
417      fprintf(stderr, "error closing %s", file);
418      exit(MR_CCONFIG);
419    }
420
421  olddev = oldmach = -1;
422  fd = stdin;
423  EXEC SQL DECLARE q_cursor2 CURSOR FOR
424    SELECT DISTINCT q.quota, q.entity_id, q.phys_id, n.device, n.mach_id,
425    n.status
426    FROM quota q, nfsphys n
427    WHERE n.nfsphys_id = q.phys_id AND q.phys_id != 0 AND
428    n.status > 15 AND q.type = 'GROUP'
429    ORDER BY mach_id, phys_id, entity_id;
430  EXEC SQL OPEN q_cursor2;
431  while (1)
432    {
433      EXEC SQL FETCH q_cursor2 INTO :quota, :gid, :flag1, :dev,
434        :flag2, :flag3;
435      if (sqlca.sqlcode)
436        break;
437      if (flag1 != olddev || flag2 != oldmach)
438        {
439          if (quotasum)
440            fprintf(fd, "%d %d\n", prevuid, quotasum);
441          if (flag2 == 0 || !hash_lookup(machines, flag2))
442            continue;
443          if (fd != stdin)
444            fclose(fd);
445          olddev = flag1;
446          oldmach = flag2;
447          while ((cp = strchr(dev, '/')))
448            *cp = '@';
449          sprintf(file, "%s/%s.%s.quotas", nfs_dir,
450                  (char *)hash_lookup(machines, flag2), strtrim(dev));
451          fd = fopen(file, "w");
452          if (!fd)
453            {
454              fprintf(stderr, "cannot open %s for output\n", file);
455              exit(MR_OCONFIG);
456            }
457          prevuid = -1;
458          quotasum = 0;
459        }
460      if (gid != prevuid)
461        {
462          if ((cp = hash_lookup(groups, prevuid)))
463            prevuid = atoi(cp + 1);
464          if (quotasum)
465            fprintf(fd, "%d %d\n", prevuid, quotasum);
466          prevuid = gid;
467          quotasum = quota;
468        }
469      else
470        quotasum += quota;
471    }
472  EXEC SQL CLOSE q_cursor2;
473  if ((cp = hash_lookup(groups, prevuid)))
474    prevuid = atoi(cp + 1);
475  if (quotasum)
476    fprintf(fd, "%d %d\n", prevuid, quotasum);
477  if (fd != stdin && fclose(fd) == EOF)
478    {
479      fprintf(stderr, "error closing %s", file);
480      exit(MR_CCONFIG);
481    }
482
483  olddev = oldmach = -1;
484  fd = stdin;
485
486  EXEC SQL DECLARE q_cursor3 CURSOR FOR
487    SELECT DISTINCT f.name, f.lockertype, u.unix_uid, l.gid, f.phys_id,
488    f.mach_id, n.device
489    FROM users u, list l, nfsphys n, filesys f
490    WHERE u.users_id = f.owner AND l.list_id = f.owners
491    AND f.createflg != 0 AND f.phys_id != 0 AND f.type = 'NFS'
492    AND f.phys_id = n.nfsphys_id
493    ORDER BY mach_id, phys_id;
494  EXEC SQL OPEN q_cursor3;
495  while (1)
496    {
497      EXEC SQL FETCH q_cursor3 INTO :dir, :fstype, :uid, :gid, :flag1,
498        :flag2, :dev;
499      if (sqlca.sqlcode)
500        break;
501      if ((flag1 != olddev || flag2 != oldmach) &&
502          hash_lookup(machines, flag2))
503        {
504          if (fd != stdin)
505            fclose(fd);
506          olddev = flag1;
507          oldmach = flag2;
508          while ((cp = strchr(dev, '/')))
509            *cp = '@';
510          sprintf(file, "%s/%s.%s.dirs", nfs_dir,
511                  (char *)hash_lookup(machines, flag2), strtrim(dev));
512          fd = fopen(file, "w");
513          if (!fd)
514            {
515              fprintf(stderr, "cannot open %s for output\n", file);
516              exit(MR_OCONFIG);
517            }
518        }
519      fprintf(fd, "%s %d %d %s\n", strtrim(dir), uid, gid, strtrim(fstype));
520    }
521  EXEC SQL CLOSE q_cursor3;
522  if (fclose(fd) == EOF)
523    {
524      fprintf(stderr, "error closing %s", file);
525      exit(MR_CCONFIG);
526    }
527  return 1;
528sqlerr:
529  db_error(sqlca.sqlcode);
530  exit(MR_DBMS_ERR);
531}
532
Note: See TracBrowser for help on using the repository browser.