]> andersk Git - moira.git/blob - afssync/pt_util.c
Deal with pts groups with whitespace and other "weird" characters in
[moira.git] / afssync / pt_util.c
1 /*
2  *
3  * pt_util: Program to dump the AFS protection server database
4  *         into an ascii file.
5  *
6  *      Assumptions: We *cheat* here and read the datafile directly, ie.
7  *                   not going through the ubik distributed data manager.
8  *                   therefore the database must be quiescent for the
9  *                   output of this program to be valid.
10  */
11
12 #include <sys/types.h>
13 #include <sys/time.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <sys/file.h>
18 #include <stdlib.h>
19
20 #include <afs/param.h>
21 #include <lock.h>
22 #include <netinet/in.h>
23 #define UBIK_INTERNALS
24 #include <ubik.h>
25 #include <rx/xdr.h>
26 #include <rx/rx.h>
27 #include "ptint.h"
28 #include "ptserver.h"
29 #include "pterror.h"
30 #ifdef HAVE_STRVIS
31 #include <strvis.h>
32 #else
33 #include "vis.h"
34 #endif
35
36 #define IDHash(x) (abs(x) % HASHSIZE)
37 #define print_id(x) ( ((flags&DO_SYS)==0 && (x<-32767 || x>97536)) || \
38                       ((flags&DO_OTR)==0 && (x>-32768 && x<97537)))
39
40 extern char *optarg;
41 extern int optind;
42 extern int errno;
43 extern char *sys_errlist[];
44 #define strerror(a) sys_errlist[a]
45
46 int display_entry();
47 void add_group();
48 void display_groups();
49 void display_group();
50 void fix_pre();
51 char *checkin();
52 char *check_core();
53 char *id_to_name();
54
55 struct hash_entry {
56     char h_name[PR_MAXNAMELEN];
57     int h_id;
58     struct hash_entry *next;
59 };
60 struct hash_entry *hat[HASHSIZE];
61
62 static struct contentry prco;
63 static struct prentry pre;
64 static struct prheader prh;
65 static struct ubik_version uv;
66
67 struct grp_list {
68     struct grp_list     *next;
69     long                groups[1024];
70 };
71 static struct grp_list *grp_head=0;
72 static long grp_count=0;
73
74 struct usr_list {
75     struct usr_list *next;
76     char name[PR_MAXNAMELEN];
77     long uid;
78 };
79 static struct usr_list *usr_head=0;
80
81 char buffer[1024];
82 int dbase_fd;
83 FILE *dfp;
84
85 #define FMT_BASE "%-10s %d/%d %d %d %d\n"
86 #define FMT_MEM  "   %-8s %d\n"
87
88 #define DO_USR 1
89 #define DO_GRP 2
90 #define DO_MEM 4
91 #define DO_SYS 8
92 #define DO_OTR 16
93
94 int nflag = 0;
95 int wflag = 0;
96 int flags = 0;
97
98 main(argc, argv)
99 int argc;
100 char **argv;
101 {
102     register int i;
103     register long code;
104     long cc, upos, gpos;
105     struct prentry uentry, gentry;
106     struct ubik_hdr *uh;
107     char *dfile = 0;
108     char *pfile = "/usr/afs/db/prdb.DB0";
109     char *str;
110     
111     while ((cc = getopt(argc, argv, "wugmxsnp:d:")) != EOF) {
112         switch (cc) {
113         case 'p':
114             pfile = optarg;
115             break;
116         case 'd':
117             dfile = optarg;
118             break;
119         case 'n':
120             nflag++;
121             break;
122         case 'w':
123             wflag++;
124             break;
125         case 'u':
126             flags |= DO_USR;
127             break;
128         case 'm':
129             flags |= (DO_GRP|DO_MEM);
130             break;
131         case 'g':
132             flags |= DO_GRP;
133             break;
134         case 's':
135             flags |= DO_SYS;
136             break;
137         case 'x':
138             flags |= DO_OTR;
139             break;
140         default:
141             fprintf(stderr,
142                     "Usage: pt_util [options] [-d data] [-p prdb]\n");
143             fputs("  Options:\n", stderr);
144             fputs("    -w  Update prdb with contents of data file\n", stderr);
145             fputs("    -u  Display users\n", stderr);
146             fputs("    -g  Display groups\n", stderr);
147             fputs("    -m  Display group members\n", stderr);
148             fputs("    -n  Follow name hash chains (not id hashes)\n", stderr);
149             fputs("    -s  Display only system (Moira) data\n", stderr);
150             fputs("    -x  Display extra users/groups\n", stderr);
151             exit(1);
152         }
153     }
154     if ((dbase_fd = open(pfile, wflag ? O_RDWR : O_RDONLY, 0600)) < 0) {
155         fprintf(stderr, "pt_util: cannot open %s: %s\n",
156                 pfile, sys_errlist[errno]);
157         exit (1);
158     }
159     if (read(dbase_fd, buffer, HDRSIZE) < 0) {
160         fprintf(stderr, "pt_util: error reading %s: %s\n",
161                 pfile, sys_errlist[errno]);
162         exit (1);
163     }
164
165     if (dfile) {
166         if ((dfp = fopen(dfile, wflag ? "r" : "w")) == 0) {
167             fprintf(stderr, "pt_util: error opening %s: %s\n",
168                     dfile, sys_errlist[errno]);
169             exit(1);
170         }
171     } else
172         dfp = (wflag ? stdin : stdout);
173
174     uh = (struct ubik_hdr *)buffer;
175     if (ntohl(uh->magic) != UBIK_MAGIC)
176         fprintf(stderr, "pt_util: %s: Bad UBIK_MAGIC. Is %x should be %x\n",
177                 pfile, ntohl(uh->magic), UBIK_MAGIC);
178     memcpy(&uv, &uh->version, sizeof(struct ubik_version));
179     if (wflag && uv.epoch==0 && uv.counter==0) {
180         uv.epoch=2; /* a ubik version of 0 or 1 has special meaning */
181         memcpy(&uh->version, &uv, sizeof(struct ubik_version));
182         lseek(dbase_fd, 0, SEEK_SET);
183         if (write(dbase_fd, buffer, HDRSIZE) < 0) {
184             fprintf(stderr, "pt_util: error writing ubik version to %s: %s\n",
185                     pfile, sys_errlist[errno]);
186             exit (1);
187         }
188     }
189     fprintf(stderr, "Ubik Version is: %d.%d\n",
190             uv.epoch, uv.counter);
191     if (read(dbase_fd, &prh, sizeof(struct prheader)) < 0) {
192         fprintf(stderr, "pt_util: error reading %s: %s\n",
193                 pfile, sys_errlist[errno]);
194         exit (1);
195     }
196
197     Initdb();
198     initialize_pt_error_table();
199
200     if (wflag) {
201         struct usr_list *u;
202
203         while(fgets(buffer, sizeof(buffer), dfp)) {
204             int id, oid, cid, flags, quota, uid;
205             char name[PR_MAXNAMELEN], mem[PR_MAXNAMELEN];
206
207             if (isspace(*buffer)) {
208                 sscanf(buffer, "%s %d", mem, &uid);
209
210                 for (u=usr_head; u; u=u->next)
211                     if (u->uid && u->uid==uid) break;
212                 if (u) {
213                     /* Add user - deferred because it is probably foreign */
214                     u->uid = 0;
215                     if (FindByID(0, uid))
216                         code = PRIDEXIST;
217                     else {
218                         if (!code && (flags&(PRGRP|PRQUOTA))==(PRGRP|PRQUOTA)){
219                             gentry.ngroups++;
220                             code = pr_WriteEntry(0,0,gpos,&gentry);
221                             if (code)
222                                 fprintf(stderr, "Error setting group count on %s: %s\n",
223                                         name, error_message(code));
224                         }
225                         code = CreateEntry
226                             (0, u->name, &uid, 1/*idflag*/, 1/*gflag*/,
227                              SYSADMINID/*oid*/, SYSADMINID/*cid*/);
228                     }
229                     if (code)
230                         fprintf(stderr, "Error while creating %s: %s\n",
231                                 u->name, error_message(code));
232                     continue;
233                 }
234                 /* Add user to group */
235                 if (id==ANYUSERID || id==AUTHUSERID || uid==ANONYMOUSID) {
236                     code = PRPERM;
237                 } else if ((upos=FindByID(0,uid)) && (gpos=FindByID(0,id))) {
238                     code = pr_ReadEntry(0,0,upos,&uentry);
239                     if (!code) code = pr_ReadEntry(0,0,gpos,&gentry);
240                     if (!code) code = AddToEntry (0, &gentry, gpos, uid);
241                     if (!code) code = AddToEntry (0, &uentry, upos, id);
242                 } else
243                     code = PRNOENT;
244
245                 if (code)
246                     fprintf(stderr, "Error while adding %s to %s: %s\n",
247                             mem, name, error_message(code));
248             } else {
249                 sscanf(buffer, "%s %d/%d %d %d %d",
250                        name, &flags, &quota, &id, &oid, &cid);
251
252                 str = malloc(strlen(name) + 1);
253                 if (!str)
254                   {
255                     fprintf(stderr, "malloc failed!");
256                     exit(1);
257                   }
258                 strunvis(str, name);
259                 strcpy(name, str);
260
261                 if (FindByID(0, id))
262                     code = PRIDEXIST;
263                 else
264                     code = CreateEntry(0, name, &id, 1/*idflag*/,
265                                        flags&PRGRP, oid, cid);
266                 if (code == PRBADNAM) {
267                     u = (struct usr_list *)malloc(sizeof(struct usr_list));
268                     u->next = usr_head;
269                     u->uid = id;
270                     strcpy(u->name, name);
271                     usr_head = u;
272                 } else
273                 if (code) {
274                     fprintf(stderr, "Error while creating %s: %s\n",
275                             name, error_message(code));
276                 } else if ((flags&PRACCESS) ||
277                            (flags&(PRGRP|PRQUOTA))==(PRGRP|PRQUOTA)) {
278                     gpos = FindByID(0, id);
279                     code = pr_ReadEntry(0,0,gpos,&gentry);
280                     if (!code) {
281                         gentry.flags = flags;
282                         gentry.ngroups = quota;
283                         code = pr_WriteEntry(0,0,gpos,&gentry);
284                     }
285                     if (code)
286                         fprintf(stderr,"Error while setting flags on %s: %s\n",
287                                 name, error_message(code));
288                 }
289             }
290         }
291         for (u=usr_head; u; u=u->next)
292             if (u->uid)
293                 fprintf(stderr, "Error while creating %s: %s\n",
294                         u->name, error_message(PRBADNAM));
295     } else {
296         for (i = 0; i < HASHSIZE; i++) {
297             upos = nflag ? ntohl(prh.nameHash[i]) : ntohl(prh.idHash[i]);
298             while (upos)
299                 upos = display_entry(upos);
300         }
301         if (flags & DO_GRP)
302             display_groups();
303     }
304
305     lseek (dbase_fd, 0, L_SET);         /* rewind to beginning of file */
306     if (read(dbase_fd, buffer, HDRSIZE) < 0) {
307         fprintf(stderr, "pt_util: error reading %s: %s\n",
308                 pfile, sys_errlist[errno]);
309         exit (1);
310     }
311     uh = (struct ubik_hdr *)buffer;
312     if ((uh->version.epoch != uv.epoch) ||
313         (uh->version.counter != uv.counter)) {
314         fprintf(stderr, "pt_util: Ubik Version number changed during execution.\n");
315         fprintf(stderr, "Old Version = %d.%d, new version = %d.%d\n",
316                 uv.epoch, uv.counter, uh->version.epoch,
317                 uh->version.counter);
318     }
319     close (dbase_fd);
320     exit (0);
321 }
322
323 int display_entry (offset)
324 int offset;
325 {
326     register int i;
327
328     lseek (dbase_fd, offset+HDRSIZE, L_SET);
329     read(dbase_fd, &pre, sizeof(struct prentry));
330
331     fix_pre(&pre);
332
333     if ((pre.flags & PRFREE) == 0) {
334         if (pre.flags & PRGRP) {
335             if (flags & DO_GRP)
336                 add_group(pre.id);
337         } else {
338             if (print_id(pre.id) && (flags&DO_USR))
339                 fprintf(dfp, FMT_BASE,
340                         pre.name, pre.flags, pre.ngroups,
341                         pre.id, pre.owner, pre.creator);
342             checkin(&pre);
343         }
344     }
345     return(nflag ? pre.nextName: pre.nextID);
346 }
347
348 void add_group(id)
349     long id;
350 {
351     struct grp_list *g;
352     register long i;
353
354     i = grp_count++ % 1024;
355     if (i == 0) {
356         g = (struct grp_list *)malloc(sizeof(struct grp_list));
357         g->next = grp_head;
358         grp_head = g;
359     }
360     g = grp_head;
361     g->groups[i] = id;
362 }
363
364 void display_groups()
365 {
366     register int i, id;
367     struct grp_list *g;
368
369     g = grp_head;
370     while (grp_count--) {
371         i = grp_count%1024;
372         id = g->groups[i];
373         display_group(id);
374         if (i==0) {
375             grp_head = g->next;
376             free(g);
377             g = grp_head;
378         }
379     }
380 }
381
382 void display_group(id)
383     int id;
384 {
385     register int i, offset;
386     int print_grp = 0;
387
388     offset = ntohl(prh.idHash[IDHash(id)]);
389     while (offset) {
390         lseek(dbase_fd, offset+HDRSIZE, L_SET);
391         if (read(dbase_fd, &pre, sizeof(struct prentry)) < 0) {
392             fprintf(stderr, "pt_util: read i/o error: %s\n",
393                     strerror(errno));
394             exit (1);
395         }
396         fix_pre(&pre);
397         if (pre.id == id)
398             break;
399         offset = pre.nextID;
400     }
401
402     if (print_id(id)) {
403         fprintf(dfp, FMT_BASE,
404                 pre.name, pre.flags, pre.ngroups,
405                 pre.id, pre.owner, pre.creator);
406         print_grp = 1;
407     }
408
409     if ((flags&DO_MEM) == 0)
410         return;
411
412     for (i=0; i<PRSIZE; i++) {
413         if ((id=pre.entries[i]) == 0)
414             break;
415         if (id==PRBADID) continue;
416         if (print_id(id) || print_grp==1) {
417             if (print_grp==0) {
418                 fprintf(dfp, FMT_BASE,
419                         pre.name, pre.flags, pre.ngroups,
420                         pre.id, pre.owner, pre.creator);
421                 print_grp = 2;
422             }
423             fprintf(dfp, FMT_MEM, id_to_name(id), id);
424         }
425     }
426     if (i == PRSIZE) {
427         offset = pre.next;
428         while (offset) {
429             lseek(dbase_fd, offset+HDRSIZE, L_SET);
430             read(dbase_fd, &prco, sizeof(struct contentry));
431             prco.next = ntohl(prco.next);
432             for (i = 0; i < COSIZE; i++) {
433                 prco.entries[i] = ntohl(prco.entries[i]);
434                 if ((id=prco.entries[i]) == 0)
435                     break;
436                 if (id==PRBADID) continue;
437                 if (print_id(id) || print_grp==1) {
438                     if (print_grp==0) {
439                         fprintf(dfp, FMT_BASE,
440                                 pre.name, pre.flags, pre.ngroups,
441                                 pre.id, pre.owner, pre.creator);
442                         print_grp = 2;
443                     }
444                     fprintf(dfp, FMT_MEM, id_to_name(id), id);
445                 }
446             }
447             if ((i == COSIZE) && prco.next)
448                 offset = prco.next;
449             else offset = 0;
450         }
451     }
452 }
453
454 void fix_pre(pre)
455     struct prentry *pre;
456 {
457     register int i;
458     char *str = malloc(4 * strlen(pre->name) + 1);
459
460     if (!str)
461       {
462         fprintf(stderr, "malloc failed in fix_pre()!");
463         exit(1);
464       }
465     strvis(str, pre->name, VIS_WHITE);
466     strcpy(pre->name, str);
467     pre->flags = ntohl(pre->flags);
468     pre->id = ntohl(pre->id);
469     pre->cellid = ntohl(pre->cellid);
470     pre->next = ntohl(pre->next);
471     pre->nextID = ntohl(pre->nextID);
472     pre->nextName = ntohl(pre->nextName);
473     pre->owner = ntohl(pre->owner);
474     pre->creator = ntohl(pre->creator);
475     pre->ngroups = ntohl(pre->ngroups);
476     pre->nusers = ntohl(pre->nusers);
477     pre->count = ntohl(pre->count);
478     pre->instance = ntohl(pre->instance);
479     pre->owned = ntohl(pre->owned);
480     pre->nextOwned = ntohl(pre->nextOwned);
481     pre->parent = ntohl(pre->parent);
482     pre->sibling = ntohl(pre->sibling);
483     pre->child = ntohl(pre->child);
484     for (i = 0; i < PRSIZE; i++) {
485         pre->entries[i] = ntohl(pre->entries[i]);
486     }
487 }
488
489 char *id_to_name(id)
490 int id;
491 {
492     register int offset;
493     static struct prentry pre;
494     char *name;
495
496     name = check_core(id);
497     if (name) return(name);
498     offset = ntohl(prh.idHash[IDHash(id)]);
499     while (offset) {
500         lseek(dbase_fd, offset+HDRSIZE, L_SET);
501         if (read(dbase_fd, &pre, sizeof(struct prentry)) < 0) {
502             fprintf(stderr, "pt_util: read i/o error: %s\n",
503                     sys_errlist[errno]);
504             exit (1);
505         }
506         pre.id = ntohl(pre.id);
507         if (pre.id == id) {
508             name = checkin(&pre);
509             return(name);
510         }
511         offset = ntohl(pre.nextID);
512     }
513     return 0;
514 }
515
516 char *checkin(pre)
517 struct prentry *pre;
518 {
519     struct hash_entry *he, *last;
520     register int id;
521
522     id = pre->id;
523     last = (struct hash_entry *)0;
524     he = hat[IDHash(id)];
525     while (he) {
526         if (id == he->h_id) return(he->h_name);
527         last = he;
528         he = he->next;
529     }
530     he = (struct hash_entry *)malloc(sizeof(struct hash_entry));
531     if (he == 0) {
532         fprintf(stderr, "pt_util: No Memory for internal hash table.\n");
533         exit (1);
534     }
535     he->h_id = id;
536     he->next = (struct hash_entry *)0;
537     strncpy(he->h_name, pre->name, PR_MAXNAMELEN);
538     if (last == (struct hash_entry *)0) hat[IDHash(id)] = he;
539     else last->next = he;
540     return(he->h_name);
541 }
542
543 char *check_core(id)
544 register int id;
545 {
546     struct hash_entry *he;
547     he = hat[IDHash(id)];
548     while (he) {
549         if (id == he->h_id) return(he->h_name);
550         he = he->next;
551     }
552     return 0;
553 }
This page took 1.719382 seconds and 5 git commands to generate.