X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/28cccd2fa53b5c744f0c06b30aeb93b5e1cc1718..67805159a972397342c342ee735c8acd640e1399:/afssync/sync.qc diff --git a/afssync/sync.qc b/afssync/sync.qc index 24213515..3910eb8c 100644 --- a/afssync/sync.qc +++ b/afssync/sync.qc @@ -20,47 +20,76 @@ #include #define min(x,y) ((x) < (y) ? (x) : (y)) -struct hash *users = NULL; char *whoami = "sync"; char *malloc(), *strsave(); int dbase_fd; +int ucount = 0; +int gcount = 0; +int mcount = 0; + +struct hash *users; +struct hash *groups; + +struct member { + struct entry *user; + struct entry *group; + struct member *unext; + struct member *gnext; +}; +struct entry { + long id; + struct member *members; +}; main(argc, argv) int argc; char **argv; { +## char db[9]; + int status; int ingerr(); + long t; + strcpy(db, "sms"); + + if (!strcmp(argv[1], "-db")) { + strncpy(db, argv[2], sizeof(db)-1); + argc -= 2; + argv += 2; + } if (argc != 2) { - fprintf(stderr, "usage: %s outfile\n", argv[0]); + fprintf(stderr, "usage: %s [-db sms] outfile\n", whoami); exit(MR_ARGS); } - dbase_fd = open(argv[1], O_RDWR|O_CREAT, 0660); + dbase_fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0660); if (dbase_fd < 0) { perror("opening file %s", argv[1]); exit(1); } IIseterr(ingerr); - initialize_sms_error_table (); -## ingres sms + initialize_sms_error_table(); + initialize_pt_error_table(); + Initdb(); /* Initialize prdb */ + + users = create_hash(10000); + groups = create_hash(15000); + +## ingres db ## set lockmode session where level = table ## begin transaction do_passwd(); -#if 0 -#define USERSMS 14487 - status = PR_AddToGroup(NULL, USERSMS, SYSADMINID); - if (status) { - prserror(status, "adding MR to system:administrators", 0, 0); - } -#endif do_groups(); + t = time(0); + fprintf(stderr, "Done (%d users, %d groups, %d members): %s", + ucount, gcount, mcount, ctime(&t)); + ## end transaction ## exit @@ -68,94 +97,36 @@ char **argv; } -/* - * ingerr: (supposedly) called when Ingres indicates an error. - * I have not yet been able to get this to work to intercept a - * database open error. - */ -#define INGRES_DEADLOCK 4700 - -static int ingerr(num) - int *num; -{ - char buf[256]; - int ingres_errno; - - switch (*num) { - case INGRES_DEADLOCK: - ingres_errno = MR_DEADLOCK; - break; - default: - ingres_errno = MR_INGRES_ERR; - } - com_err(whoami, MR_INGRES_ERR, " code %d\n", *num); - exit(ingres_errno); -} - - -prserror(status, msg, arg1, arg2) -int status; -char *msg; -unsigned long arg1, arg2; -{ - char buf[512]; - - sprintf(buf, msg, arg1, arg2); - switch (status) { - case PREXIST: - msg = "name already exists"; - break; - case PRIDEXIST: - msg = "ID already exists"; - break; - case PRNOIDS: - msg = "no IDs available"; - break; - case PRDBFAIL: - msg = "database failed"; - break; - case PRNOENT: - msg = "no space left in database"; - break; - case PRPERM: - msg = "permission denied"; - break; - case PRNOTGROUP: - msg = "not a group"; - break; - case PRNOTUSER: - msg = "not a user"; - break; - case PRBADNAM: - msg = "bad name"; - break; - case 0: - msg = "no error"; - break; - default: - msg = "unknown code"; - break; - } - fprintf(stderr, "%s (%d): %s\n", msg, status, buf); -} - - - do_passwd() ##{ ## char login[9]; ## int uid, id, status; + long t; + struct prentry tentry; + struct entry *u; - fprintf(stderr, "Doing users\n"); - users = create_hash(10000); + t = time(0); + fprintf(stderr, "Doing users: %s", ctime(&t)); + ## range of u is users ## retrieve (login = u.#login, uid = u.#uid, id = u.users_id) -## where u.#status = 1 or u.#status = 2 { - strtrim(login); - hash_store(users, id, uid); - status = PR_INewEntry(NULL, login, uid, 0); - if (status) { - prserror(status, "adding user %s uid %d", login, uid); +## where u.#uid > 0 and (u.#status = 1 or u.#status = 2) { + lowercase(strtrim(login)); + + if (FindByID(0,uid)) + status = PRIDEXIST; + else + status = CreateEntry(0,login,&uid,1/*idflag*/,0/*gflag*/, + SYSADMINID/*oid*/, SYSADMINID/*cid*/); + if (status) + fprintf(stderr, "Error adding user %s uid %d: %s\n", + login, uid, error_message(status)); + else { + u = (struct entry *)malloc(sizeof(struct entry)); + u->id = uid; + u->members = 0; + hash_store(users, id, u); + ucount++; } ## } ##} @@ -164,17 +135,19 @@ do_passwd() do_groups() ##{ - struct hash *groups; - long u, g, status; -## char name[33], namebuf[128]; + long status, pos; + struct prentry gentry, uentry; + struct entry *u, *g; + struct member *m; + struct bucket **p, *b; + char namebuf[40]; + long aid, t; +## char name[33]; ## int gid, id, lid, hide; - fprintf(stderr, "Doing groups\n"); + t = time(0); + fprintf(stderr, "Doing groups: %s", ctime(&t)); - /* make space for group list */ - groups = create_hash(15000); - - /* retrieve simple groups */ ## range of l is list ## range of m is imembers /* get lock records */ @@ -182,37 +155,160 @@ do_groups() ## retrieve (name = users.modtime) where users.users_id = 0 ## retrieve (name = l.#name, gid = l.#gid, lid = l.list_id, hide = l.hidden) -## where l.group != 0 and l.active != 0 { - strtrim(name); +## where l.group != 0 and l.active != 0 and l.#gid > 0 { + lowercase(strtrim(name)); sprintf(namebuf, "system:%s", name); - hash_store(groups, lid, -gid); - status = PR_INewEntry(NULL, namebuf, -gid, SYSADMINID); + aid = -gid; + + if (FindByID(0, aid)) + status = PRIDEXIST; + else + status = CreateEntry(0,namebuf,&aid,1/*idflag*/,PRGRP/*gflag*/, + SYSADMINID/*oid*/, SYSADMINID/*cid*/); if (status) - prserror(status, "adding list %s gid %d", namebuf, -gid); - if (hide) { - status = PR_SetFieldsEntry - (NULL/*call*/, -gid, - PR_SF_ALLBITS/*mask*/, - PRP_STATUS_MEM >> PRIVATE_SHIFT /*flags*/, - 0/*ngroups*/, 0/*nusers*/, 0/*spare1*/, 0/*spare2*/); - if (status) - prserror(status, "setting flags on list %s", namebuf); + fprintf(stderr, "Error adding group %s id %d: %s\n", + namebuf, aid, error_message(status)); + + if ((status==0 || status==PRIDEXIST) && + (aid!=ANYUSERID && aid!=AUTHUSERID)) { + + g = (struct entry *)malloc(sizeof(struct entry)); + g->id = aid; + g->members = 0; + hash_store(groups, lid, g); + gcount++; + + /* Set modes on hidden lists (S----) */ + if (hide) { + pos = FindByID(0, aid); + status = pr_Read(0, 0, pos, &gentry, sizeof(gentry)); + if (!status) { + gentry.flags = htonl(PRGRP|PRACCESS|PRP_STATUS_ANY); + status = pr_Write(0, 0, pos, &gentry, sizeof(gentry)); + } + if (status) + fprintf(stderr, + "Error setting flags on group %s: %s\n", + namebuf, error_message(status)); + } } ## } - - fprintf(stderr, "Doing members\n"); + t = time(0); + fprintf(stderr, "Doing members: %s", ctime(&t)); ## retrieve (lid = m.list_id, id = m.member_id) ## where m.member_type = "USER" { - if ((u = (long) hash_lookup(users, id)) && - (g = (long) hash_lookup(groups, lid))) { - status = PR_AddToGroup(NULL, u, g); - if (status) { - prserror(status, "adding %d to group %d", u, -g); - } + if ((u = (struct entry *)hash_lookup(users, id)) && + (g = (struct entry *)hash_lookup(groups, lid))) { + m = (struct member *)malloc(sizeof(struct member)); + m->user = u; + m->group = g; + m->unext = u->members; + m->gnext = g->members; + u->members = g->members = m; + mcount++; } ## } + /* Do the bulk of the membership quickly. + * Add PRSIZE members into the user/group record. After that, we + * require the use of continuation records, but we assume this is + * few enough that we do this the slow way (AddToEntry). + */ + for (p = &(users->data[users->size - 1]); p >= users->data; p--) { + for (b = *p; b; b = b->next) { + if ((u = (struct entry *)b->data)->members == 0) + continue; + pos = FindByID(0, u->id); + pr_Read(0, 0, pos, &uentry, sizeof(uentry)); + for (t=0, m=u->members; m && tunext, t++) + uentry.entries[t] = htonl(m->group->id); + uentry.count = htonl(t); + pr_Write(0, 0, pos, &uentry, sizeof(uentry)); + if (m) { + pr_ReadEntry(0, 0, pos, &uentry); + while (m) { + AddToEntry(0, &uentry, pos, m->group->id); + m = m->unext; + } + } + } + } + for (p = &(groups->data[groups->size - 1]); p >= groups->data; p--) { + for (b = *p; b; b = b->next) { + if ((g = (struct entry *)b->data)->members == 0) + continue; + pos = FindByID(0, g->id); + pr_Read(0, 0, pos, &gentry, sizeof(gentry)); + for (t=0, m=g->members; m && tgnext, t++) + gentry.entries[t] = htonl(m->user->id); + gentry.count = htonl(t); + pr_Write(0, 0, pos, &gentry, sizeof(gentry)); + if (m) { + pr_ReadEntry(0, 0, pos, &gentry); + while (m) { + AddToEntry(0, &gentry, pos, m->user->id); + m = m->gnext; + } + } + } + } +##} + +#if 0 +do_kerberos() +##{ + long status, pos; + struct prentry gentry, uentry; + struct entry *u, *g; + struct member *m; + struct bucket **p, *b; + char namebuf[40]; + int aid, t; +## char name[129]; +## int gid, id, lid, hide; + + t = time(0); + fprintf(stderr, "Doing kerberos members: %s", ctime(&t)); + +## range of s is strings +## range of m is imembers + /* get lock records */ +## retrieve (name = list.modtime) where list.list_id = 0 +## retrieve (name = s.modtime) where s.string_id = 0 + +## retrieve (lid = m.list_id, id = m.member_id) +## where m.member_type = "KERBEROS" { + xxx; + { + } +## } + ##} +#endif + + +/* + * ingerr: (supposedly) called when Ingres indicates an error. + * I have not yet been able to get this to work to intercept a + * database open error. + */ +#define INGRES_DEADLOCK 4700 +static int ingerr(num) + int *num; +{ + char buf[256]; + int ingres_errno; + + switch (*num) { + case INGRES_DEADLOCK: + ingres_errno = MR_DEADLOCK; + break; + default: + ingres_errno = MR_INGRES_ERR; + } + com_err(whoami, MR_INGRES_ERR, " code %d\n", *num); + exit(ingres_errno); +}