On Thu, Aug 19, 1999 at 03:35:45PM -0700, Coda wrote: > > Here I go again, asking more questions... > > After adding and deleting a bunch of users and groups via pdbtool (testing > scripts and such) I seem to have broken it. > > now, if I try to add a new user or group I get the following: > > pdbtool> nui testu 570 > Assertion failed: uid >= 0 && gid <= 0, file "pdbdb.c", line 181 > VENUS IS EXITTING! Bye! > > pdbtool> ng testg 500 > Assertion failed: uid >= 0 && gid <= 0, file "pdbdb.c", line 181 > VENUS IS EXITTING! Bye! This is due to a bug related to updating the maxids entry in the database. It was fixed in the development tree. I'll attach the diff of coda-src/al/* between 5.2.7 and the current version. If you compiled from source you can apply this to get a correctly working pdbtool. > Below I've included a pdbtool> list in case it helps illuminate something. > > I seee that USER jrs belongs to group -255 (one that has been deleted). > I've tried: Great, you found a new bug. When a group is deleted, the id was not removed correctly from group members. The fix for that is also in the attached patch (the one-liner in pdb.c). > pdbtool> rg -255 500 > Assertion failed: r.id != 0, file "pdb.c", line 84 > VENUS IS EXITTING! Bye! > > pdbtool> d 500 > Assertion failed: p.id != 0, file "pdb.c", line 252 > VENUS IS EXITTING! Bye! Yeah, the code is a bit extreme on assertions. You'll not be able to remove someone from a non-existant group, even when that user is registered as a group-member. (But with the bug fixed, that shouldn't occur) > What do I need to do to be able to use pdbtool again? Best thing is to patch the source, and start over again. Although you could get the maxid's back to normal values with the `maxids' command, you won't be able to remove the bad group-id from user jrs's list. > -- Jonathan l8r, Jan
? pdbtool.patch Index: alprocs.c =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/alprocs.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- alprocs.c 1999/05/11 20:08:00 1.2 +++ alprocs.c 1999/08/06 19:40:14 1.3 @@ -42,6 +42,7 @@ #include <stdio.h> #include <ctype.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> Index: pdb.c =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdb.c,v retrieving revision 1.7 diff -u -r1.7 pdb.c --- pdb.c 1999/05/11 18:07:44 1.7 +++ pdb.c 1999/08/19 22:49:19 @@ -348,7 +348,7 @@ while(nextid != 0){ PDB_readProfile(h, nextid, &p); CODA_ASSERT(p.id != 0); - pdb_array_del(&(p.groups_or_members), id); + pdb_array_del(&(p.member_of), id); if(PDB_ISGROUP(p.id)) PDB_updateCps(h, &p); else Index: pdbdb.c =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdbdb.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- pdbdb.c 1999/06/16 03:17:02 1.8 +++ pdbdb.c 1999/07/17 19:30:41 1.9 @@ -176,7 +176,7 @@ int rc; char zero = 0; int32_t olduid, oldgid; - int32_t *ids = NULL; + int32_t ids[2]; CODA_ASSERT(uid >= 0 && gid <= 0); @@ -190,18 +190,16 @@ if ( rc != RET_SUCCESS ) { CODA_ASSERT( (uid == 0) && (gid == 0) ); - olduid = -1; - oldgid = 1; - value.size = 2 * sizeof(int32_t); - ids = malloc(value.size); - value.data = (void *) ids; - } else { + ids[0] = htonl(0); + ids[1] = htonl(0); + } else { CODA_ASSERT(value.size == 2*sizeof(int32_t)); - ids = (int32_t *) value.data; - olduid = ntohl(ids[0]); - oldgid = ntohl(ids[1]); - CODA_ASSERT(olduid >= 0 || oldgid <= 0); + ids[0] = ((int32_t *)value.data)[0]; + ids[1] = ((int32_t *)value.data)[1]; } + olduid = ntohl(ids[0]); + oldgid = ntohl(ids[1]); + CODA_ASSERT(olduid >= 0 || oldgid <= 0); if ( mode != PDB_MAXID_FORCE ) { if ( uid > olduid ) @@ -214,6 +212,9 @@ ids[1] = htonl(gid); } + value.size = 2 * sizeof(int32_t); + value.data = (void *) &ids; + rc = h->main->put(h->main, &key, &value, 0); CODA_ASSERT(rc == RET_SUCCESS); } @@ -361,7 +362,7 @@ /* this record has a special 1-byte key equal to zero */ memset(&key, 0, sizeof(DBT)); - key.size = 1; + key.size = sizeof(zero); key.data = &zero; /* open the profile database in read mode */ Index: pdbtool.c =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdbtool.c,v retrieving revision 1.3 retrieving revision 1.6 diff -u -r1.3 -r1.6 --- pdbtool.c 1999/03/17 00:57:55 1.3 +++ pdbtool.c 1999/08/19 15:57:05 1.6 @@ -49,18 +49,33 @@ else return 0; } +/* Convert a name or id argument into a numerical id value */ +int32_t get_id(char *n) +{ + int32_t id; + + /* try to interpret the passed argument as a numeric id */ + id = atoi(n); + if(id != 0) return id; + + /* Attempt to find the argument as a name */ + PDB_lookupByName(n, &id); + + return id; +} + /* LOOKUP BY ID */ -void tool_byId(int argc,char *argv[]){ +void tool_byNameOrId(int argc,char *argv[]){ PDB_profile sample; PDB_HANDLE h; - long arg1; + int32_t arg1; if(check_args_num(argc,2)){ printf("Usage: i idnum\nidnum\t\tnumber of user/group\n"); return; } - arg1 = atol(argv[1]); + arg1 = get_id(argv[1]); if(arg1 == 0){ - printf("Give numerical value.\n"); + printf("'%s' not found.\n", argv[1]); return; } h = PDB_db_open(O_RDONLY); @@ -70,24 +85,6 @@ PDB_db_close(h); } -/* LOOKUP BY NAME */ -void tool_byName(int argc,char *argv[]){ - int32_t id; - PDB_profile sample; - PDB_HANDLE h; - if(check_args_num(argc,2)){ - printf("Usage: n name\nnamet\tname of user/group\n"); - return; - } - PDB_lookupByName(argv[1], &id); - h = PDB_db_open(O_RDONLY); - PDB_readProfile(h, id, &sample); - PDB_printProfile(stdout, &sample); - PDB_freeProfile(&sample); - PDB_db_close(h); -} - - /* LIST EVERTHING */ void tool_list(int argc,char *argv[]){ int32_t id; @@ -127,15 +124,15 @@ void tool_newUser_Id(int argc,char *argv[]){ char *s; int32_t id; - long arg2; + int32_t arg2; if(check_args_num(argc,3)){ printf("Usage: nui name id\nname\t\t" "name of new user\nid\t\tid of new user\n"); return; } - arg2 = atol(argv[2]); - if(arg2 == 0){ - printf("Give numerical value.\n"); + arg2 = atoi(argv[2]); + if(!PDB_ISUSER(arg2)){ + printf("Not a valid user-id (it needs to be > 0).\n"); return; } PDB_lookupById((int32_t) arg2, &s); @@ -144,7 +141,6 @@ free(s); return; } - free(s); PDB_createUser(argv[1], &id); if (id == 0){ printf("Failed to creat user.\n"); @@ -157,13 +153,13 @@ /* CREATE NEW USER */ void tool_changeName(int argc,char *argv[]){ - long arg1; + int32_t arg1; if(check_args_num(argc,3)){ printf("Usage: cn id name\nid\t\t" "id number of user\n\nname\t\tnew name of user\n"); return; } - arg1 = atol(argv[1]); + arg1 = atoi(argv[1]); if(arg1 == 0){ printf("Give numerical value.\n"); return; @@ -176,25 +172,19 @@ void tool_newGroup(int argc,char *argv[]){ char *s; int32_t id; - long arg2; + int32_t arg2; if(check_args_num(argc,3)){ printf("Usage: ng name owner\nname\t\t" "name of new group\nowner\t\t" - "id number of group owner\n"); - return; - } - arg2 = atol(argv[2]); - if(arg2 == 0){ - printf("Give numerical value.\n"); - return; - } - if(!PDB_ISUSER(arg2)){ - printf("Owner must be a user!\n"); + "id/name number of group owner\n"); return; } + arg2 = get_id(argv[2]); PDB_lookupById((int32_t) arg2, &s); - if(s == NULL){ - printf("No user %ld!\n",arg2); + if(!PDB_ISUSER(arg2) || s == NULL){ + printf("Owner must be a valid username/id, %s not found!\n", + argv[2]); + if (s) free(s); return; } free(s); @@ -269,29 +259,23 @@ long arg1, arg2; if(check_args_num(argc,3)){ printf("Usage: ag group user\ngroup\t\t" - "id of group to add to\nuser\t\t" - "id number of user to add\n"); - return; - } - arg1 = atol(argv[1]); - if(arg1 == 0){ - printf("Give numerical value.\n"); + "id or name of group to add to\nuser\t\t" + "id or name of user to add\n"); return; } + arg1 = get_id(argv[1]); PDB_lookupById((int32_t) arg1, &s); - if(s == NULL){ - printf("No group %ld!\n",arg1); + if(!PDB_ISGROUP(arg1) || s == NULL){ + printf("No group %s found!\n", argv[1]); + if (s) free(s); return; } free(s); - arg2 = atol(argv[2]); - if(arg2 == 0){ - printf("Give numerical value.\n"); - return; - } + arg2 = get_id(argv[2]); PDB_lookupById((int32_t) arg2, &s); if(s == NULL){ - printf("No user %ld!\n",arg2); + printf("No user or group %s found!\n", argv[2]); + if (s) free(s); return; } free(s); @@ -300,21 +284,21 @@ /* REMOVE SOMEONE (USER OR GROUP) TO A GROUP */ void tool_removefromGroup(int argc,char *argv[]){ - long arg1, arg2; + int32_t arg1, arg2; if(check_args_num(argc,3)){ printf("Usage: rg group user\ngroup\t\t" - "id of group to remove from\nuser\t\t" - "id number of user to remove\n"); + "id or name of group to remove from\nuser\t\t" + "id or name of user to remove\n"); return; } - arg1 = atol(argv[1]); - if(arg1 == 0){ - printf("Give numerical value.\n"); + arg1 = get_id(argv[1]); + if(!PDB_ISGROUP(arg1)) { + printf("No group %s found!\n", argv[1]); return; } - arg2 = atol(argv[2]); - if(arg2 == 0){ - printf("Give numerical value.\n"); + arg2 = get_id(argv[2]); + if(arg2 == 0) { + printf("No user or group %s found!\n", argv[2]); return; } PDB_removeFromGroup(arg2, arg1); @@ -325,17 +309,14 @@ char *s; long arg1; if(check_args_num(argc,2)){ - printf("Usage: d id\nid\t\tid number of user/group\n"); - return; - } - arg1 = atol(argv[1]); - if(arg1 == 0){ - printf("Give numerical value.\n"); + printf("Usage: d id/name\n" + "id/name\t\tid or name of user/group\n"); return; } + arg1 = get_id(argv[1]); PDB_lookupById((int32_t) arg1, &s); if(s == NULL){ - printf("No user %ld!\n",arg1); + printf("%s not found!\n",argv[1]); return; } free(s); @@ -352,13 +333,14 @@ PDB_HANDLE h; PDB_profile p; if(check_args_num(argc,2)){ - printf("Usage: u id\nid\t\tid number of user/group\n"); + printf("Usage: u id/name\n" + "id/name\t\tid or name of user/group\n"); return; } h = PDB_db_open(O_RDWR); - arg1 = atol(argv[1]); + arg1 = get_id(argv[1]); if(arg1 == 0){ - printf("Give numerical value.\n"); + printf("%s not found.\n", argv[1]); return; } PDB_readProfile(h, arg1, &p); @@ -379,6 +361,18 @@ PDB_db_close(h); } +/* SHOW MAXIDS */ +void tool_get_maxids(int argc,char *argv[]){ + PDB_HANDLE h; + int maxuid, maxgid; + if(check_args_num(argc,1)){ + printf("Usage: get_maxids\n"); + } + h = PDB_db_open(O_RDWR); + PDB_db_maxids(h, &maxuid, &maxgid); + PDB_db_close(h); + printf("maxuid %d maxgid %d\n", maxuid, maxgid); +} /* SET MAXIDS */ void tool_maxids(int argc,char *argv[]){ @@ -409,48 +403,227 @@ int32_t id; long arg2; if(check_args_num(argc,3)) { - printf("Usage %s username newid\n", argv[0]); + printf("Usage %s user/group newid\n", argv[0]); return; } - arg2 = atol(argv[2]); - if(arg2 == 0){ - printf("Give numerical value.\n"); + id = get_id(argv[1]); + if (id == 0) { + printf("%s not found.\n", argv[1]); return; } - PDB_lookupByName(argv[1], &id); - if (id == 0){ - printf("Invalid user.\n"); + arg2 = atol(argv[2]); + if(arg2 == 0){ + printf("Give numerical value for newid.\n"); return; } PDB_changeId(id,arg2); } +/* dump/restore database contents */ +void tool_export(int argc, char *argv[]) +{ + int32_t id, i; + PDB_profile rec; + PDB_HANDLE h; + FILE *userfile, *groupfile; + char *s; + int rc; + + if (check_args_num(argc, 3)) { + printf("Usage: export <userfile> <groupfile>\n"); + return; + } + + userfile = fopen(argv[1], "w"); + groupfile = fopen(argv[2], "w"); + + h = PDB_db_open(O_RDONLY); + while ((rc = PDB_db_nextkey(h, &id))) { + if (rc == -1) continue; + + PDB_readProfile(h, id, &rec); + { + if (PDB_ISUSER(rec.id)) { + /* users are dumped in an /etc/passwd like format + * "<username>:x:<userid>:500::/:" */ + fprintf(userfile, "%s:*:%d:500::/:\n", rec.name, rec.id); + } else { + /* groups and group members are dumped in an /etc/group like + * format "<groupname>:x:<groupid>:<owner>[,<members>]*" */ + + /* escape the :'s in the group names */ + s = rec.name; while ((s = strchr(s, ':')) != NULL) *s = '%'; + + fprintf(groupfile, "%s:*:%d:%s", rec.name, rec.id, + rec.owner_name); + for (i = 0; i < rec.groups_or_members.size; i++) { + if (rec.groups_or_members.data[i] == rec.owner_id) + continue; + + PDB_lookupById(rec.groups_or_members.data[i], &s); + if (s == NULL) continue; + + fprintf(groupfile, ",%s", s); + free(s); + } + fprintf(groupfile, "\n"); + } + } + PDB_freeProfile(&rec); + } + PDB_db_close(h); + + fclose(userfile); + fclose(groupfile); +} + +void tool_import(int argc, char *argv[]) +{ + FILE *userfile, *groupfile; + char user[64], group[64], owner_and_members[1024], *owner, *member, *s; + int32_t user_id, group_id, owner_id, member_id, create_id; + int rc; + + if (check_args_num(argc, 3)) { + printf("Usage: import <userfile> <groupfile>\n"); + return; + } + + /* recreate all users */ + userfile = fopen(argv[1], "r"); + while(1) { + rc = fscanf(userfile, "%[^:]:%*[^:]:%d:%*s\n", user, &user_id); + if (rc < 0) break; + + /* create user */ + PDB_lookupById(user_id, &s); + if (s) { + printf("Duplicate user for id %d, found both %s and %s\n", + user_id, s, user); + free(s); + continue; + } + + PDB_createUser(user, &create_id); + PDB_changeId(create_id, user_id); + printf("Created user %s, id %d\n", user, user_id); + } + fclose(userfile); + + /* recreate groups */ + groupfile = fopen(argv[2], "r"); + while (1) { + rc = fscanf(groupfile, "%[^:]:%*[^:]:%d:%s\n", + group, &group_id, owner_and_members); + if (rc < 0) break; + + /* restore the :'s in the group name */ + s = group; while ((s = strchr(s, '%')) != NULL) *s = ':'; + + owner = strtok(owner_and_members, ","); + + /* create group */ + PDB_lookupByName(owner, &owner_id); + if (owner_id == 0) { + printf("Group %s's owner %s cannot be found\n", group, owner); + continue; + } + if (!PDB_ISUSER(owner_id)) { + printf("Group %s's owner %s is a group but should be a user\n", + group, owner); + continue; + } + PDB_createGroup(group, owner_id, &create_id); + PDB_changeId(create_id, group_id); + printf("Created group %s, id %d, owner %s\n", group, group_id, owner); + } + + /* add group members*/ + rewind(groupfile); + while (1) { + rc = fscanf(groupfile, "%[^:]:%*[^:]:%d:%s\n", + group, &group_id, owner_and_members); + if (rc < 0) break; + + /* restore the :'s in the group name */ + s = group; while ((s = strchr(s, '%')) != NULL) *s = ':'; + + /* skip the owner */ + (void)strtok(owner_and_members, ","); + + /* add group members */ + printf("Adding members to %s\n\t", group); + while ((member = strtok(NULL, ",")) != NULL) { + /* restore the :'s in the name */ + s = member; while ((s = strchr(s, '%')) != NULL) *s = ':'; + + PDB_lookupByName(member, &member_id); + if (member_id == 0) { + printf("\nGroup %s's member %s cannot be found\n\t", + group, member); + continue; + } + PDB_addToGroup(member_id, group_id); + printf(" %s", member); + } + printf("\n"); + } + fclose(groupfile); +} + +void tool_source(int argc, char *argv[]) +{ + char line[1024]; + char *nl; + + FILE *file = fopen(argv[1], "r"); + if ( !file ) { + perror(""); + return; + } + while ( fgets(line, 1024, file) ) { + if ( (nl = strchr(line, '\n')) ) + *nl = '\0'; + execute_line(line); + } +} /* HELP */ -void tool_help(int argc, char *argv[]){ - printf("i\tread database by user ID\n"); - printf("n\tread database by user name\n"); - printf("nu\tcreate a new user\n"); - printf("nui\tcreate a new user with id\n"); - printf("ng\tcreate a new group\n"); - printf("l\tlook up an ID by name\n"); - printf("list\tlist all entries\n"); - printf("cu\tclone a user\n"); - printf("ag\tadd a group or user to a group\n"); - printf("rg\tremove a group or user from a group\n"); - printf("d\tdelete a user or a group\n"); - printf("cm\tcompact the database (RARE)\n"); - printf("ci\tchange the Id of a new user or group\n"); - printf("cn\tchange the Name of a user\n"); - printf("maxids\tset the database maxids\n"); - printf("u\tupdate an id\n"); +void tool_help(int argc, char *argv[]) +{ + if (argc > 1) { + Parser_help(argc, argv); + return; + } + + printf("i <id/name>\t\t\tget info from database about ID/name\n"); + printf("nu <username>\t\t\tcreate a new user\n"); + printf("nui <username> <userid>\t\tcreate a new user with id\n"); + printf("ng <groupname> <ownerid/name>\tcreate a new group\n"); + printf("l <name>\t\t\tlook up an ID by name\n"); + printf("list\t\t\t\tlist all entries\n"); + printf("cu <newusername> <userid>\tclone a user\n"); + printf("ag <groupid/name> <id/name>\tadd a group or user to a group\n"); + printf("rg <groupid/name> <id/name>\tremove a group or user from a group\n"); + printf("d <id/name>\t\t\t\tdelete a user or a group\n"); + printf("cm\t\t\t\tcompact the database (RARE)\n"); + printf("ci <name> <newid>\t\tchange the Id of a user or group\n"); + printf("cn <id> <newname>\t\tchange the Name of a user or group\n"); + printf("u <id/name>\t\t\tupdate an id/name\n"); + printf("ids\t\t\t\tget the database maxids\n"); + printf("maxids <userid> <groupid>\tset the database maxids\n"); + printf("export <userfile> <groupfile>\tdump the contents of the pdb +database\n"); + printf("import <userfile> <groupfile>\tread a dumped pdb database\n"); + printf("source <file>\t\t\tread commands from file\n"); + printf("exit\t\t\t\texit the pdbtool\n"); } command_t pdbcmds[] = { - {"i", tool_byId, 0, "read database by user ID"}, - {"n", tool_byName, 0, "read database by user name"}, + {"i", tool_byNameOrId, 0, "get info from the database (by name or id)"}, + /* 'n' only for compatibility with pre-5.3 pdbtool */ + {"n", tool_byNameOrId, 0, "get info from the database (by name or id)"}, {"nu", tool_newUser, 0, "create a new user"}, {"nui", tool_newUser_Id, 0, "create a new user with id"}, {"ng", tool_newGroup, 0, "create a new group"}, @@ -465,7 +638,11 @@ {"ci", tool_changeId, 0, "change the Id of a user or group"}, {"cn", tool_changeName, 0, "change the Name of a user"}, {"u", tool_update, 0, "update an id"}, + {"ids", tool_get_maxids, 0, "get the database maxids"}, {"maxids", tool_maxids, 0, "set the database maxids"}, + {"export", tool_export, 0, "dump the contents of the database"}, + {"import", tool_import, 0, "load the contents of the database"}, + {"source", tool_source, 0, "read commands from file"}, {"help", tool_help, 0, "print help on commands"}, {"quit", Parser_exit, 0, "get me out of here"}, {"exit", Parser_exit, 0, "get me out of here"}, @@ -475,8 +652,7 @@ int main(int argc, char **argv) { - char *nl; - + int i; coda_assert_action = CODA_ASSERT_EXIT; PDB_setupdb(); @@ -485,16 +661,12 @@ Parser_commands(); else { char line[1024]; - FILE *file = fopen(argv[1], "r"); - if ( !file ) { - perror(""); - return 1; - } - while ( fgets(line, 1024, file) ) { - if ( (nl = strchr(line, '\n')) ) - *nl = '\0'; - execute_line(line); + strcpy(line, argv[1]); + for (i = 2; i < argc; i++) { + strcat(line, " "); + strcat(line, argv[i]); } + execute_line(line); } return 0; }