2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
26 #include "afs_ptsAdmin.h"
27 #include "../adminutil/afs_AdminInternal.h"
28 #include <afs/afs_AdminErrors.h>
29 #include <afs/afs_utilAdmin.h>
30 #include <afs/ptint.h>
31 #include <afs/ptserver.h>
34 * The list of external functions that aren't prototyped anywhere
37 extern int PR_NameToID();
38 extern int PR_AddToGroup();
39 extern int PR_ChangeEntry();
40 extern int PR_RemoveFromGroup();
41 extern int PR_INewEntry();
42 extern int PR_NewEntry();
43 extern int PR_Delete();
44 extern int PR_IDToName();
45 extern int PR_ListEntry();
46 extern int PR_SetMax();
47 extern int PR_ListElements();
48 extern int PR_SetFieldsEntry();
49 extern int PR_IsAMemberOf();
50 extern int PR_ListMax();
51 extern int PR_ListOwned();
52 extern int PR_ListEntries();
55 * IsValidCellHandle - validate the cell handle for making pts
60 * IN cellHandle - a previously opened cellHandle that is to be validated.
64 * No locks are obtained or released by this function
68 * Returns != 0 upon successful completion.
72 static int IsValidCellHandle(
73 const afs_cell_handle_p c_handle,
79 if (!CellHandleIsValid((void *) c_handle, &tst)) {
80 goto fail_IsValidCellHandle;
83 if (c_handle->pts_valid == 0) {
84 tst = ADMCLIENTCELLPTSINVALID;
85 goto fail_IsValidCellHandle;
88 if (c_handle->pts == NULL) {
89 tst = ADMCLIENTCELLPTSNULL;
90 goto fail_IsValidCellHandle;
95 fail_IsValidCellHandle:
105 * TranslatePTSNames - translate character representations of pts names
106 * into their numeric equivalent.
110 * IN cellHandle - a previously opened cellHandle that corresponds
111 * to the cell where the id's exist.
113 * IN names - the list of names to be translated.
115 * OUT ids - the list of translated names
119 * No locks are obtained or released by this function
123 * Returns != 0 upon successful completion.
127 static int TranslatePTSNames(
128 const afs_cell_handle_p cellHandle,
134 afs_status_t tst = 0;
139 * Lowercase the names to translate
142 for(i=0;i<names->namelist_len;i++) {
143 p = names->namelist_val[i];
150 tst = ubik_Call(PR_NameToID, cellHandle->pts, 0, names, ids);
153 goto fail_TranslatePTSNames;
158 * Check to see if the lookup failed
161 for(i=0;i<ids->idlist_len;i++) {
162 if (ids->idlist_val[i] == ANONYMOUSID) {
163 tst = ADMPTSFAILEDNAMETRANSLATE;
164 goto fail_TranslatePTSNames;
169 fail_TranslatePTSNames:
178 * TranslateTwoNames - translate two pts names to their pts ids.
182 * IN cellHandle - a previously opened cellHandle that corresponds
183 * to the cell where the group exists.
185 * IN id1 - one id to be translated
187 * IN error1 - the error status to be returned in the event that id1 is
190 * IN id2 - one id to be translated
192 * IN error2 - the error status to be returned in the event that id2 is
196 * OUT idlist - the list of pts id's
200 * No locks are obtained or released by this function
204 * Returns != 0 upon successful completion.
208 static int TranslateTwoNames(
209 const afs_cell_handle_p c_handle,
218 afs_status_t tst = 0;
220 char tmp_array[2*PTS_MAX_NAME_LEN];
223 * Copy the group and user names in order to translate them
226 names.namelist_len = 2;
227 names.namelist_val = (prname *) &tmp_array[0];
229 strncpy(names.namelist_val[0],id1,PTS_MAX_NAME_LEN);
230 strncpy(names.namelist_val[1],id2,PTS_MAX_NAME_LEN);
235 * Check that user and group aren't too long
236 * This is a cheaper check than calling strlen
239 if (names.namelist_val[0][PTS_MAX_NAME_LEN-1] != 0) {
241 goto fail_TranslateTwoNames;
244 if (names.namelist_val[0][PTS_MAX_NAME_LEN-1] != 0) {
246 goto fail_TranslateTwoNames;
250 * Translate user and group into pts ID's
253 if(TranslatePTSNames(c_handle, &names, ids, &tst) == 0) {
254 goto fail_TranslateTwoNames;
259 fail_TranslateTwoNames:
268 * TranslateOneName - translate a pts name to its pts id.
272 * IN cellHandle - a previously opened cellHandle that corresponds
273 * to the cell where the group exists.
275 * IN userName - the user to be translated.
277 * OUT idlist - the user pts id.
281 * No locks are obtained or released by this function
285 * Returns != 0 upon successful completion.
289 static int TranslateOneName(
290 const afs_cell_handle_p c_handle,
292 afs_status_t tooLongError,
297 afs_status_t tst = 0;
299 char tmp_array[PTS_MAX_NAME_LEN];
303 * Copy the name in order to translate it
306 names[0].namelist_len = 1;
307 names[0].namelist_val = (prname *) &tmp_array[0];
309 strncpy(names[0].namelist_val,ptsName,PTS_MAX_NAME_LEN);
314 * Check that user isn't too long
315 * This is a cheaper check than calling strlen
318 if (names[0].namelist_val[0][PTS_MAX_NAME_LEN-1] != 0) {
320 goto fail_TranslateOneName;
324 * Translate user into pts ID
327 if(TranslatePTSNames(c_handle, names, &ids, &tst) == 0) {
328 goto fail_TranslateOneName;
330 if (ids.idlist_val != NULL) {
331 *ptsId = *ids.idlist_val;
332 free(ids.idlist_val);
338 fail_TranslateOneName:
347 * TranslatePTSIds - translate numeric representations of pts names
348 * into their character equivalent.
352 * IN cellHandle - a previously opened cellHandle that corresponds
353 * to the cell where the id's exist.
355 * IN ids - the list of ids to be translated.
357 * OUT names - the list of translated names
361 * No locks are obtained or released by this function
365 * Returns != 0 upon successful completion.
369 static int TranslatePTSIds(
370 const afs_cell_handle_p cellHandle,
376 afs_status_t tst = 0;
378 tst = ubik_Call(PR_IDToName, cellHandle->pts, 0, ids, names);
381 goto fail_TranslatePTSIds;
385 fail_TranslatePTSIds:
394 * pts_GroupMemberAdd - add one member to a pts group
398 * IN cellHandle - a previously opened cellHandle that corresponds
399 * to the cell where the group exists.
401 * IN userName - the name to be added to the group.
403 * IN groupName - the group to be modified.
407 * No locks are obtained or released by this function
411 * Returns != 0 upon successful completion.
415 int ADMINAPI pts_GroupMemberAdd(
416 const void *cellHandle,
417 const char *userName,
418 const char *groupName,
422 afs_status_t tst = 0;
423 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
430 if (!IsValidCellHandle(c_handle, &tst)) {
431 goto fail_pts_GroupMemberAdd;
434 if ((userName == NULL) || (*userName == 0)) {
435 tst = ADMPTSUSERNAMENULL;
436 goto fail_pts_GroupMemberAdd;
439 if ((groupName == NULL) || (*groupName == 0)) {
440 tst = ADMPTSGROUPNAMENULL;
441 goto fail_pts_GroupMemberAdd;
444 if (!TranslateTwoNames(c_handle, userName, ADMPTSUSERNAMETOOLONG, groupName,
445 ADMPTSGROUPNAMETOOLONG, &ids, &tst)) {
446 goto fail_pts_GroupMemberAdd;
453 tst = ubik_Call(PR_AddToGroup, c_handle->pts, 0, ids.idlist_val[0],
457 goto fail_pts_GroupMemberAdd;
461 fail_pts_GroupMemberAdd:
463 if (ids.idlist_val != 0) {
464 free(ids.idlist_val);
474 * pts_GroupOwnerChange - change the owner of a group
478 * IN cellHandle - a previously opened cellHandle that corresponds
479 * to the cell where the group exists.
481 * IN targetGroup - the group to be modified.
483 * IN userName - the new owner of the group.
487 * No locks are obtained or released by this function
491 * Returns != 0 upon successful completion.
495 int ADMINAPI pts_GroupOwnerChange(
496 const void *cellHandle,
497 const char *targetGroup,
498 const char *newOwner,
502 afs_status_t tst = 0;
503 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
510 if (!IsValidCellHandle(c_handle, &tst)) {
511 goto fail_pts_GroupOwnerChange;
514 if ((newOwner == NULL) || (*newOwner == 0)) {
515 tst = ADMPTSNEWOWNERNULL;
516 goto fail_pts_GroupOwnerChange;
519 if ((targetGroup == NULL) || (*targetGroup == 0)) {
520 tst = ADMPTSTARGETGROUPNULL;
521 goto fail_pts_GroupOwnerChange;
524 if (!TranslateTwoNames(c_handle, newOwner, ADMPTSNEWOWNERTOOLONG,
525 targetGroup, ADMPTSTARGETGROUPTOOLONG, &ids, &tst)) {
526 goto fail_pts_GroupOwnerChange;
533 tst = ubik_Call(PR_ChangeEntry, c_handle->pts, 0, ids.idlist_val[1],
534 "", ids.idlist_val[0], 0);
537 goto fail_pts_GroupOwnerChange;
541 fail_pts_GroupOwnerChange:
543 if (ids.idlist_val != 0) {
544 free(ids.idlist_val);
554 * pts_GroupCreate - create a new group
558 * IN cellHandle - a previously opened cellHandle that corresponds
559 * to the cell where the group exists.
561 * IN newGroup - the group to be created.
563 * IN newOwner - the owner of the group. Pass NULL if the current user
564 * is to be the new owner, or the character string of the owner otherwise.
566 * IN/OUT newGroupId - the pts id of the group. Pass 0 to have ptserver
567 * generate a value, != 0 to assign a value on your own. The group id
568 * that is used to create the group is copied into this parameter in the
569 * event you pass in 0.
573 * No locks are obtained or released by this function
577 * Returns != 0 upon successful completion.
581 int ADMINAPI pts_GroupCreate(
582 const void *cellHandle,
583 const char *newGroup,
584 const char *newOwner,
589 afs_status_t tst = 0;
590 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
591 afs_int32 newOwnerId = 0;
597 if (!IsValidCellHandle(c_handle, &tst)) {
598 goto fail_pts_GroupCreate;
601 if ((newGroup == NULL) || (*newGroup == 0)) {
602 tst = ADMPTSNEWGROUPNULL;
603 goto fail_pts_GroupCreate;
606 if (newGroupId == NULL) {
607 tst = ADMPTSNEWGROUPIDNULL;
608 goto fail_pts_GroupCreate;
611 if (*newGroupId > 0) {
612 tst = ADMPTSNEWGROUPIDPOSITIVE;
613 goto fail_pts_GroupCreate;
617 * If a newOwner was specified, validate that it exists
620 if (newOwner != NULL) {
621 if (!TranslateOneName(c_handle, newOwner, ADMPTSNEWOWNERTOOLONG,
622 &newOwnerId, &tst)) {
623 goto fail_pts_GroupCreate;
628 * We make a different rpc based upon the input to this function
631 if (*newGroupId != 0) {
632 tst = ubik_Call(PR_INewEntry, c_handle->pts, 0, newGroup, *newGroupId,
635 tst = ubik_Call(PR_NewEntry, c_handle->pts, 0, newGroup, PRGRP,
636 newOwnerId, newGroupId);
640 goto fail_pts_GroupCreate;
644 fail_pts_GroupCreate:
653 * GetGroupAccess - a small convenience function for setting
658 * IN access - a pointer to a pts_groupAccess_t to be set with the
659 * correct permission.
661 * IN flag - the current permission flag used to derive the permission.
665 * No locks are obtained or released by this function
669 * Since this function cannot fail, it returns void.
673 static void GetGroupAccess(
674 pts_groupAccess_p access,
678 *access = PTS_GROUP_OWNER_ACCESS;
680 *access = PTS_GROUP_OWNER_ACCESS;
681 } else if (flag == 1) {
682 *access = PTS_GROUP_ACCESS;
683 } else if (flag == 2) {
684 *access = PTS_GROUP_ANYUSER_ACCESS;
690 * pts_GroupGet - retrieve information about a particular group.
694 * IN cellHandle - a previously opened cellHandle that corresponds
695 * to the cell where the group exists.
697 * IN groupName - the group to retrieve.
699 * OUT groupP - a pointer to a pts_GroupEntry_t structure that upon
700 * successful completion is filled with information about groupName.
704 * No locks are obtained or released by this function
708 * Returns != 0 upon successful completion.
712 int ADMINAPI pts_GroupGet(
713 const void *cellHandle,
714 const char *groupName,
715 pts_GroupEntry_p groupP,
719 afs_status_t tst = 0;
720 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
721 afs_int32 groupId = 0;
724 struct prcheckentry groupEntry;
733 if (!IsValidCellHandle(c_handle, &tst)) {
734 goto fail_pts_GroupGet;
737 if ((groupName == NULL) || (*groupName == 0)) {
738 tst = ADMPTSGROUPNAMENULL;
739 goto fail_pts_GroupGet;
742 if (groupP == NULL) {
743 tst = ADMPTSGROUPPNULL;
744 goto fail_pts_GroupGet;
748 * Translate the group name into an id.
751 if (!TranslateOneName(c_handle, groupName, ADMPTSGROUPNAMETOOLONG,
753 goto fail_pts_GroupGet;
757 * Retrieve information about the group
760 tst = ubik_Call(PR_ListEntry, c_handle->pts, 0, groupId, &groupEntry);
763 goto fail_pts_GroupGet;
766 groupP->membershipCount = groupEntry.count;
767 groupP->nameUid = groupEntry.id;
768 groupP->ownerUid = groupEntry.owner;
769 groupP->creatorUid = groupEntry.creator;
770 strcpy(groupP->name, groupEntry.name);
772 * Set the access rights based upon the value of the flags member
773 * of the groupEntry struct.
775 * To the best of my ability to decypher the pts code, it looks like
776 * the rights are stored in flags as follows:
778 * I number my bits from least significant to most significant starting
782 * if bit 0 == 0 -> r access is denied
783 * if bit 0 == 1 -> r access is granted
786 * if bit 2 == 0 and bit 1 == 0 -> a access is denied
787 * if bit 2 == 0 and bit 1 == 1 -> a access is granted
788 * if bit 2 == 1 and bit 1 == 0 -> A access is granted
789 * if bit 2 == 1 and bit 1 == 1 -> this is an error
791 * membership - bits 3 and 4
792 * if bit 4 == 0 and bit 3 == 0 -> m access is denied
793 * if bit 4 == 0 and bit 3 == 1 -> m access is granted
794 * if bit 4 == 1 and bit 3 == 0 -> M access is granted
795 * if bit 4 == 1 and bit 3 == 1 -> this is an error
798 * if bit 5 == 0 -> O access is denied
799 * if bit 5 == 1 -> O access is granted
801 * status - bits 6 and 7
802 * if bit 7 == 0 and bit 6 == 0 -> s access is denied
803 * if bit 7 == 0 and bit 6 == 1 -> s access is granted
804 * if bit 7 == 1 and bit 6 == 0 -> S access is granted
805 * if bit 7 == 1 and bit 6 == 1 -> this is an error
807 * For cases where the permission doesn't make sense for the
808 * type of entry, or where an error occurs, we ignore it.
809 * This is the behavior of the pts code.
812 flags = groupEntry.flags;
814 groupP->listDelete = PTS_GROUP_ACCESS;
816 groupP->listDelete = PTS_GROUP_OWNER_ACCESS;
822 GetGroupAccess(&groupP->listAdd, twobit);
827 GetGroupAccess(&groupP->listMembership, twobit);
832 groupP->listGroupsOwned = PTS_GROUP_ANYUSER_ACCESS;
834 groupP->listGroupsOwned = PTS_GROUP_OWNER_ACCESS;
840 GetGroupAccess(&groupP->listStatus, twobit);
843 * Make another rpc and translate the owner and creator ids into
848 ids.idlist_val = ptsids;
849 ptsids[0] = groupEntry.owner;
850 ptsids[1] = groupEntry.creator;
851 names.namelist_len = 0;
852 names.namelist_val = 0;
855 if (!TranslatePTSIds(c_handle, &names, &ids, &tst)) {
856 goto fail_pts_GroupGet;
859 strcpy(groupP->owner, names.namelist_val[0]);
860 strcpy(groupP->creator, names.namelist_val[1]);
861 free(names.namelist_val);
873 * EntryDelete - delete a pts entry (group or user).
877 * IN cellHandle - a previously opened cellHandle that corresponds
878 * to the cell where the group exists.
880 * IN entryName - the entry to be deleted.
882 * IN error1 - the error status to be returned in the event that entryName is
885 * IN error2 - the error status to be returned in the event that entryName is
890 * No locks are obtained or released by this function
894 * Returns != 0 upon successful completion.
898 static int EntryDelete(
899 const void *cellHandle,
900 const char *entryName,
906 afs_status_t tst = 0;
907 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
908 afs_int32 entryId = 0;
914 if (!IsValidCellHandle(c_handle, &tst)) {
915 goto fail_EntryDelete;
918 if ((entryName == NULL) || (*entryName == 0)) {
920 goto fail_EntryDelete;
924 * Translate the entry name into an id.
927 if (!TranslateOneName(c_handle, entryName, error2,
929 goto fail_EntryDelete;
936 tst = ubik_Call(PR_Delete, c_handle->pts, 0, entryId);
939 goto fail_EntryDelete;
953 * pts_GroupDelete - delete a group
957 * IN cellHandle - a previously opened cellHandle that corresponds
958 * to the cell where the group exists.
960 * IN groupName - the group to be deleted.
964 * No locks are obtained or released by this function
968 * Returns != 0 upon successful completion.
972 int ADMINAPI pts_GroupDelete(
973 const void *cellHandle,
974 const char *groupName,
978 return EntryDelete(cellHandle, groupName, ADMPTSGROUPNAMENULL,
979 ADMPTSGROUPNAMETOOLONG, st);
983 * pts_GroupMaxGet - get the maximum in use group id.
987 * IN cellHandle - a previously opened cellHandle that corresponds
988 * to the cell where the group exists.
990 * OUT maxGroupId - upon successful completion contains the maximum
991 * group Id in use at the server.
995 * No locks are obtained or released by this function
999 * Returns != 0 upon successful completion.
1003 int ADMINAPI pts_GroupMaxGet(
1004 const void *cellHandle,
1009 afs_status_t tst = 0;
1010 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1011 afs_int32 maxUserId = 0;
1014 * Validate arguments
1017 if (!IsValidCellHandle(c_handle, &tst)) {
1018 goto fail_pts_GroupMaxGet;
1021 if (maxGroupId == NULL) {
1022 tst = ADMPTSMAXGROUPIDNULL;
1023 goto fail_pts_GroupMaxGet;
1026 tst = ubik_Call(PR_ListMax, c_handle->pts, 0, &maxUserId, maxGroupId);
1029 goto fail_pts_GroupMaxGet;
1033 fail_pts_GroupMaxGet:
1042 * pts_GroupMaxSet - set the maximum in use group id.
1046 * IN cellHandle - a previously opened cellHandle that corresponds
1047 * to the cell where the group exists.
1049 * IN maxGroupId - the new maximum group id.
1053 * No locks are obtained or released by this function
1057 * Returns != 0 upon successful completion.
1061 int ADMINAPI pts_GroupMaxSet(
1062 const void *cellHandle,
1067 afs_status_t tst = 0;
1068 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1071 * Validate arguments
1074 if (!IsValidCellHandle(c_handle, &tst)) {
1075 goto fail_pts_GroupMaxSet;
1078 tst = ubik_Call(PR_SetMax, c_handle->pts, 0, maxGroupId, PRGRP);
1081 goto fail_pts_GroupMaxSet;
1085 fail_pts_GroupMaxSet:
1096 * I'm not using the common iterator pattern here since the retrival
1097 * of the member list is actually accomplished in 1 rpc. There's no
1098 * sense in trying to fit this pts specific behavior into the more
1099 * generic model, so instead the Begin functions actually do all the
1100 * rpc work and the next/done functions just manipulate the retrieved
1104 typedef struct pts_group_member_list_iterator {
1107 pthread_mutex_t mutex; /* hold to manipulate this structure */
1112 } pts_group_member_list_iterator_t, *pts_group_member_list_iterator_p;
1115 * pts_GroupMemberListBegin - begin iterating over the list of members
1116 * of a particular group.
1120 * IN iter - an iterator previously returned by pts_GroupMemberListBegin
1124 * No locks are obtained or released by this function
1128 * Returns != 0 upon successful completion.
1132 static int IsValidPtsGroupMemberListIterator(
1133 pts_group_member_list_iterator_p iter,
1137 afs_status_t tst = 0;
1140 tst = ADMITERATORNULL;
1141 goto fail_IsValidPtsGroupMemberListIterator;
1144 if ((iter->begin_magic != BEGIN_MAGIC) ||
1145 (iter->end_magic != END_MAGIC)) {
1146 tst = ADMITERATORBADMAGICNULL;
1147 goto fail_IsValidPtsGroupMemberListIterator;
1150 if (iter->is_valid == 0) {
1151 tst = ADMITERATORINVALID;
1152 goto fail_IsValidPtsGroupMemberListIterator;
1156 fail_IsValidPtsGroupMemberListIterator:
1164 * MemberListBegin - an internal function which is used to get both
1165 * the list of members in a group and the list of groups a user belongs
1170 * IN cellHandle - a previously opened cellHandle that corresponds
1171 * to the cell where the group exists.
1173 * IN name - the name whose membership will be retrieved.
1175 * OUT iterationIdP - upon successful completion contains a iterator that
1176 * can be passed to pts_GroupMemberListNext or pts_UserMemberListNext
1180 * No locks are obtained or released by this function
1184 * Returns != 0 upon successful completion.
1188 static int MemberListBegin(
1189 const void *cellHandle,
1191 afs_status_t error1,
1192 afs_status_t error2,
1193 void **iterationIdP,
1197 afs_status_t tst = 0;
1198 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1199 afs_int32 groupId = 0;
1200 afs_int32 exceeded = 0;
1201 pts_group_member_list_iterator_p iter = (pts_group_member_list_iterator_p) malloc(sizeof(pts_group_member_list_iterator_t));
1202 int iter_allocated = 0;
1203 int ids_allocated = 0;
1204 int names_allocated = 0;
1205 int mutex_inited = 0;
1208 * Validate arguments
1211 if (!IsValidCellHandle(c_handle, &tst)) {
1212 goto fail_MemberListBegin;
1215 if ((name == NULL) || (*name == 0)) {
1216 tst = ADMPTSGROUPNAMENULL;
1217 goto fail_MemberListBegin;
1220 if (iterationIdP == NULL) {
1221 tst = ADMITERATORNULL;
1222 goto fail_MemberListBegin;
1227 goto fail_MemberListBegin;
1233 * Translate the name into an id.
1236 if (!TranslateOneName(c_handle, name, ADMPTSGROUPNAMETOOLONG,
1238 goto fail_MemberListBegin;
1241 if (pthread_mutex_init(&iter->mutex, 0)) {
1243 goto fail_MemberListBegin;
1248 iter->ids.prlist_len = 0;
1249 iter->ids.prlist_val = 0;
1251 tst = ubik_Call(PR_ListElements, c_handle->pts, 0, groupId, &iter->ids,
1255 goto fail_MemberListBegin;
1258 if (exceeded != 0) {
1259 tst = ADMPTSGROUPMEMEXCEEDED;
1260 goto fail_MemberListBegin;
1264 iter->names.namelist_len = 0;
1265 iter->names.namelist_val = 0;
1267 if (!TranslatePTSIds(c_handle, &iter->names, (idlist *) &iter->ids, &tst)) {
1268 goto fail_MemberListBegin;
1271 names_allocated = 1;
1272 iter->begin_magic = BEGIN_MAGIC;
1273 iter->end_magic = END_MAGIC;
1277 *iterationIdP = (void *) iter;
1280 fail_MemberListBegin:
1282 if (ids_allocated) {
1283 free(iter->ids.prlist_val);
1287 if (names_allocated) {
1288 free(iter->names.namelist_val);
1291 pthread_mutex_destroy(&iter->mutex);
1293 if (iter_allocated) {
1305 * pts_GroupMemberListBegin - begin iterating over the list of members
1306 * of a particular group.
1310 * IN cellHandle - a previously opened cellHandle that corresponds
1311 * to the cell where the group exists.
1313 * IN groupName - the group whose members will be returned.
1315 * OUT iterationIdP - upon successful completion contains a iterator that
1316 * can be passed to pts_GroupMemberListNext.
1320 * No locks are obtained or released by this function
1324 * Returns != 0 upon successful completion.
1328 int ADMINAPI pts_GroupMemberListBegin(
1329 const void *cellHandle,
1330 const char *groupName,
1331 void **iterationIdP,
1334 return MemberListBegin(cellHandle, groupName, ADMPTSGROUPNAMENULL,
1335 ADMPTSGROUPNAMETOOLONG, iterationIdP, st);
1339 * pts_GroupMemberListNext - get the next member of a group
1343 * IN iterationId - an iterator previously returned by pts_GroupMemberListBegin
1345 * OUT memberName - upon successful completion contains the next member of
1350 * The iterator mutex is held during the retrieval of the next member.
1354 * Returns != 0 upon successful completion.
1358 int ADMINAPI pts_GroupMemberListNext(
1359 const void *iterationId,
1364 afs_status_t tst = 0;
1365 pts_group_member_list_iterator_p iter = (pts_group_member_list_iterator_p) iterationId;
1366 int mutex_locked = 0;
1369 * Validate arguments
1373 tst = ADMITERATORNULL;
1374 goto fail_pts_GroupMemberListNext;
1377 if (memberName == NULL) {
1378 tst = ADMPTSMEMBERNAMENULL;
1379 goto fail_pts_GroupMemberListNext;
1383 * Lock the mutex and check the validity of the iterator
1386 if (pthread_mutex_lock(&iter->mutex)) {
1388 goto fail_pts_GroupMemberListNext;
1393 if (!IsValidPtsGroupMemberListIterator(iter, &tst)) {
1394 goto fail_pts_GroupMemberListNext;
1398 * Check to see if we've copied out all the data. If we haven't,
1399 * copy another item. If we have, mark the iterator done.
1402 if (iter->index >= iter->names.namelist_len) {
1403 tst = ADMITERATORDONE;
1404 goto fail_pts_GroupMemberListNext;
1406 strcpy(memberName,iter->names.namelist_val[iter->index]);
1411 fail_pts_GroupMemberListNext:
1414 pthread_mutex_unlock(&iter->mutex);
1424 * pts_GroupMemberListDone - finish using a member list iterator
1428 * IN iterationId - an iterator previously returned by pts_GroupMemberListBegin
1432 * The iterator is locked and then destroyed
1436 * Returns != 0 upon successful completion.
1440 * It is the user's responsibility to make sure pts_GroupMemberListDone
1441 * is called only once for each iterator.
1444 int ADMINAPI pts_GroupMemberListDone(
1445 const void *iterationId,
1449 afs_status_t tst = 0;
1450 pts_group_member_list_iterator_p iter = (pts_group_member_list_iterator_p) iterationId;
1451 int mutex_locked = 0;
1454 * Validate arguments
1458 tst = ADMITERATORNULL;
1459 goto fail_pts_GroupMemberListDone;
1463 * Lock the mutex and check the validity of the iterator
1466 if (pthread_mutex_lock(&iter->mutex)) {
1468 goto fail_pts_GroupMemberListDone;
1473 if (!IsValidPtsGroupMemberListIterator(iter,&tst)) {
1474 goto fail_pts_GroupMemberListDone;
1478 * Free the namelist and the iterator.
1481 pthread_mutex_destroy(&iter->mutex);
1484 free(iter->names.namelist_val);
1488 fail_pts_GroupMemberListDone:
1491 pthread_mutex_unlock(&iter->mutex);
1501 * pts_GroupMemberRemove - remove a member from a group.
1505 * IN cellHandle - a previously opened cellHandle that corresponds
1506 * to the cell where the group exists.
1508 * IN userName - the user to remove.
1510 * IN groupName - the group to modify
1514 * No locks are held by this function
1518 * Returns != 0 upon successful completion.
1522 int ADMINAPI pts_GroupMemberRemove(
1523 const void *cellHandle,
1524 const char *userName,
1525 const char *groupName,
1529 afs_status_t tst = 0;
1530 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1534 * Validate arguments
1537 if (!IsValidCellHandle(c_handle, &tst)) {
1538 goto fail_pts_GroupMemberRemove;
1541 if ((userName == NULL) || (*userName == 0)) {
1542 tst = ADMPTSUSERNAMENULL;
1543 goto fail_pts_GroupMemberRemove;
1546 if ((groupName == NULL) || (*groupName == 0)) {
1547 tst = ADMPTSGROUPNAMENULL;
1548 goto fail_pts_GroupMemberRemove;
1551 if (!TranslateTwoNames(c_handle, userName, ADMPTSUSERNAMETOOLONG, groupName,
1552 ADMPTSGROUPNAMETOOLONG, &ids, &tst)) {
1553 goto fail_pts_GroupMemberRemove;
1560 tst = ubik_Call(PR_RemoveFromGroup, c_handle->pts, 0, ids.idlist_val[0],
1564 goto fail_pts_GroupMemberRemove;
1568 fail_pts_GroupMemberRemove:
1570 if (ids.idlist_val != 0) {
1571 free(ids.idlist_val);
1581 * pts_GroupRename - change the name of a group
1585 * IN cellHandle - a previously opened cellHandle that corresponds
1586 * to the cell where the group exists.
1588 * IN oldName - the current group name
1590 * IN newName - the new group name
1594 * No locks are held by this function
1598 * Returns != 0 upon successful completion.
1602 int ADMINAPI pts_GroupRename(
1603 const void *cellHandle,
1604 const char *oldName,
1605 const char *newName,
1609 afs_status_t tst = 0;
1610 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1611 afs_int32 groupId = 0;
1614 * Validate arguments
1617 if (!IsValidCellHandle(c_handle, &tst)) {
1618 goto fail_pts_GroupRename;
1621 if ((newName == NULL) || (*newName == 0)) {
1622 tst = ADMPTSNEWNAMENULL;
1623 goto fail_pts_GroupRename;
1626 if ((oldName == NULL) || (*oldName == 0)) {
1627 tst = ADMPTSOLDNAMENULL;
1628 goto fail_pts_GroupRename;
1632 * Translate the group name into an id.
1635 if (!TranslateOneName(c_handle, oldName, ADMPTSOLDNAMETOOLONG,
1637 goto fail_pts_GroupRename;
1644 tst = ubik_Call(PR_ChangeEntry, c_handle->pts, 0, groupId, newName, 0, 0);
1647 goto fail_pts_GroupRename;
1651 fail_pts_GroupRename:
1660 * SetGroupAccess - translate our Access notation to pts flags.
1664 * IN rights - the permissions.
1666 * OUT flags - a pointer to an afs_int32 structure that
1667 * contains the flags to pass to pts.
1671 * No locks are held by this function
1675 * Returns != 0 upon successful completion.
1679 static int SetGroupAccess(
1680 const pts_GroupUpdateEntry_p rights,
1685 afs_status_t tst = 0;
1689 if (rights->listDelete == PTS_GROUP_ACCESS) {
1691 } else if (rights->listDelete == PTS_GROUP_ANYUSER_ACCESS) {
1692 tst = ADMPTSINVALIDGROUPDELETEPERM;
1693 goto fail_SetGroupAccess;
1696 if (rights->listAdd == PTS_GROUP_ACCESS) {
1698 } else if (rights->listAdd == PTS_GROUP_ANYUSER_ACCESS) {
1702 if (rights->listMembership == PTS_GROUP_ACCESS) {
1704 } else if (rights->listMembership == PTS_GROUP_ANYUSER_ACCESS) {
1708 if (rights->listGroupsOwned == PTS_GROUP_ANYUSER_ACCESS) {
1710 } else if (rights->listGroupsOwned == PTS_GROUP_ACCESS) {
1711 tst = ADMPTSINVALIDGROUPSOWNEDPERM;
1712 goto fail_SetGroupAccess;
1715 if (rights->listStatus == PTS_GROUP_ACCESS) {
1717 } else if (rights->listStatus == PTS_GROUP_ANYUSER_ACCESS) {
1722 fail_SetGroupAccess:
1731 * pts_GroupModify - change the contents of a group entry.
1735 * IN cellHandle - a previously opened cellHandle that corresponds
1736 * to the cell where the group exists.
1738 * IN groupName - the group to change
1740 * OUT newEntryP - a pointer to a pts_GroupUpdateEntry_t structure that
1741 * contains the new information for the group.
1745 * No locks are held by this function
1749 * Returns != 0 upon successful completion.
1753 int ADMINAPI pts_GroupModify(
1754 const void *cellHandle,
1755 const char *groupName,
1756 const pts_GroupUpdateEntry_p newEntryP,
1760 afs_status_t tst = 0;
1761 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1762 afs_int32 groupId = 0;
1763 afs_int32 flags = 0;
1766 * Validate arguments
1769 if (!IsValidCellHandle(c_handle, &tst)) {
1770 goto fail_pts_GroupModify;
1773 if ((groupName == NULL) || (*groupName == 0)) {
1774 tst = ADMPTSGROUPNAMENULL;
1775 goto fail_pts_GroupModify;
1779 if (newEntryP == NULL) {
1780 tst = ADMPTSNEWENTRYPNULL;
1781 goto fail_pts_GroupModify;
1785 * Translate the group name into an id.
1788 if (!TranslateOneName(c_handle, groupName, ADMPTSGROUPNAMETOOLONG,
1790 goto fail_pts_GroupModify;
1794 * Set the flags argument
1797 if (!SetGroupAccess(newEntryP, &flags, &tst)) {
1798 goto fail_pts_GroupModify;
1805 tst = ubik_Call(PR_SetFieldsEntry, c_handle->pts, 0, groupId,
1806 PR_SF_ALLBITS, flags, 0, 0, 0, 0);
1809 goto fail_pts_GroupModify;
1813 fail_pts_GroupModify:
1822 * pts_UserCreate - create a new user.
1826 * IN cellHandle - a previously opened cellHandle that corresponds
1827 * to the cell where the group exists.
1829 * IN newUser - the name of the new user.
1831 * IN newUserId - the id to assign to the new user. Pass 0 to have the
1832 * id assigned by pts.
1836 * No locks are held by this function
1840 * Returns != 0 upon successful completion.
1844 int ADMINAPI pts_UserCreate(
1845 const void *cellHandle,
1846 const char *userName,
1851 afs_status_t tst = 0;
1852 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1853 afs_int32 userId = 0;
1856 * Validate arguments
1859 if (!IsValidCellHandle(c_handle, &tst)) {
1860 goto fail_pts_UserCreate;
1863 if ((userName == NULL) || (*userName == 0)) {
1864 tst = ADMPTSUSERNAMENULL;
1865 goto fail_pts_UserCreate;
1868 if (newUserId == NULL) {
1869 tst = ADMPTSNEWUSERIDNULL;
1870 goto fail_pts_UserCreate;
1874 * We make a different rpc based upon the input to this function
1877 if (*newUserId != 0) {
1878 tst = ubik_Call(PR_INewEntry, c_handle->pts, 0, userName, *newUserId,
1881 tst = ubik_Call(PR_NewEntry, c_handle->pts, 0, userName, 0,
1886 goto fail_pts_UserCreate;
1890 fail_pts_UserCreate:
1899 * pts_UserDelete - delete a user.
1903 * IN cellHandle - a previously opened cellHandle that corresponds
1904 * to the cell where the group exists.
1906 * IN user - the name of the user to delete.
1910 * No locks are held by this function
1914 * Returns != 0 upon successful completion.
1918 int ADMINAPI pts_UserDelete(
1919 const void *cellHandle,
1920 const char *userName,
1923 return EntryDelete(cellHandle, userName, ADMPTSUSERNAMENULL,
1924 ADMPTSUSERNAMETOOLONG, st);
1929 * GetUserAccess - a small convenience function for setting
1934 * IN access - a pointer to a pts_userAccess_t to be set with the
1935 * correct permission.
1937 * IN flag - the current permission flag used to derive the permission.
1941 * No locks are obtained or released by this function
1945 * Since this function cannot fail, it returns void.
1949 static void GetUserAccess(
1950 pts_userAccess_p access,
1954 *access = PTS_USER_OWNER_ACCESS;
1956 *access = PTS_USER_ANYUSER_ACCESS;
1961 * IsAdministrator - determine if a user is an administrator.
1965 * IN cellHandle - a previously opened cellHandle that corresponds
1966 * to the cell where the group exists.
1968 * IN userEntry - the user data for the user in question.
1970 * OUT admin - set to 1 if the user is an administrator, 0 otherwise.
1974 * No locks are held by this function
1978 * Returns != 0 upon successful completion.
1982 static int IsAdministrator(
1983 const afs_cell_handle_p c_handle,
1989 afs_status_t tst = 0;
1990 afs_int32 adminId = 0;
1991 afs_int32 isAdmin = 0;
1995 if (userId == SYSADMINID) {
1998 if (!TranslateOneName(c_handle, "system:administrators",
1999 ADMPTSGROUPNAMETOOLONG, &adminId, &tst)) {
2000 goto fail_IsAdministrator;
2002 tst = ubik_Call(PR_IsAMemberOf, c_handle->pts, 0, userId, adminId, &isAdmin);
2004 goto fail_IsAdministrator;
2012 fail_IsAdministrator:
2021 * pts_UserGet - retrieve information about a particular user.
2025 * IN cellHandle - a previously opened cellHandle that corresponds
2026 * to the cell where the group exists.
2028 * IN userName - the name of the user to retrieve.
2030 * OUT userP - a pointer to a pts_UserEntry_t that is filled upon successful
2035 * No locks are held by this function
2039 * Returns != 0 upon successful completion.
2043 int ADMINAPI pts_UserGet(
2044 const void *cellHandle,
2045 const char *userName,
2046 pts_UserEntry_p userP,
2050 afs_status_t tst = 0;
2051 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2052 struct prcheckentry userEntry;
2053 afs_int32 userId = 0;
2057 afs_int32 ptsids[2];
2063 * Validate arguments
2066 if (!IsValidCellHandle(c_handle, &tst)) {
2067 goto fail_pts_UserGet;
2070 if ((userName == NULL) || (*userName == 0)) {
2071 tst = ADMPTSUSERNAMENULL;
2072 goto fail_pts_UserGet;
2075 if (userP == NULL) {
2076 tst = ADMPTSUSERPNULL;
2077 goto fail_pts_UserGet;
2081 * Translate the group name into an id.
2084 if (!TranslateOneName(c_handle, userName, ADMPTSUSERNAMETOOLONG,
2086 goto fail_pts_UserGet;
2090 * Retrieve information about the group
2093 tst = ubik_Call(PR_ListEntry, c_handle->pts, 0, userId, &userEntry);
2096 goto fail_pts_UserGet;
2099 userP->groupMembershipCount = userEntry.count;
2100 userP->groupCreationQuota = userEntry.ngroups;
2102 * The administrator id, or any member of "system:administrators"
2103 * has unlimited group creation quota. Denote this by setting
2107 if (!IsAdministrator(c_handle, userEntry.id, &admin, &tst)) {
2108 goto fail_pts_UserGet;
2112 userP->groupCreationQuota = -1;
2115 userP->nameUid = userEntry.id;
2116 userP->ownerUid = userEntry.owner;
2117 userP->creatorUid = userEntry.creator;
2118 strcpy(userP->name, userEntry.name);
2121 * The permission bits are described in the GroupGet function above.
2122 * The user entry only uses 3 of the 5 permissions, so we shift
2123 * past the unused entries.
2126 flags = userEntry.flags;
2130 GetUserAccess(&userP->listMembership, twobit);
2135 userP->listGroupsOwned = PTS_USER_ANYUSER_ACCESS;
2137 userP->listGroupsOwned = PTS_USER_OWNER_ACCESS;
2143 GetUserAccess(&userP->listStatus, twobit);
2146 * Make another rpc and translate the owner and creator ids into
2147 * character strings.
2151 ids.idlist_val = ptsids;
2152 ptsids[0] = userEntry.owner;
2153 ptsids[1] = userEntry.creator;
2154 names.namelist_len = 0;
2155 names.namelist_val = 0;
2158 if (!TranslatePTSIds(c_handle, &names, &ids, &tst)) {
2159 goto fail_pts_UserGet;
2162 strcpy(userP->owner, names.namelist_val[0]);
2163 strcpy(userP->creator, names.namelist_val[1]);
2164 free(names.namelist_val);
2176 * pts_UserRename - rename a user.
2180 * IN cellHandle - a previously opened cellHandle that corresponds
2181 * to the cell where the group exists.
2183 * IN oldName - the name of the user to rename.
2185 * IN newName - the new user name.
2189 * No locks are held by this function
2193 * Returns != 0 upon successful completion.
2197 int ADMINAPI pts_UserRename(
2198 const void *cellHandle,
2199 const char *oldName,
2200 const char *newName,
2204 afs_status_t tst = 0;
2205 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2206 afs_int32 userId = 0;
2209 * Validate arguments
2212 if (!IsValidCellHandle(c_handle, &tst)) {
2213 goto fail_pts_UserRename;
2216 if ((oldName == NULL) || (*oldName == 0)) {
2217 tst = ADMPTSOLDNAMENULL;
2218 goto fail_pts_UserRename;
2221 if ((newName == NULL) || (*newName == 0)) {
2222 tst = ADMPTSNEWNAMENULL;
2223 goto fail_pts_UserRename;
2227 * Translate the user name into an id.
2230 if (!TranslateOneName(c_handle, oldName, ADMPTSOLDNAMETOOLONG,
2232 goto fail_pts_UserRename;
2239 tst = ubik_Call(PR_ChangeEntry, c_handle->pts, 0, userId, newName, 0, 0);
2242 goto fail_pts_UserRename;
2246 fail_pts_UserRename:
2255 * SetUserAccess - translate our Access notation to pts flags.
2259 * IN userP - the user structure that contains the new permissions.
2261 * OUT flags - a pointer to an afs_int32 structure that
2262 * contains the flags to pass to pts.
2266 * No locks are held by this function
2270 * Returns != 0 upon successful completion.
2274 static int SetUserAccess(
2275 const pts_UserUpdateEntry_p userP,
2280 afs_status_t tst = 0;
2284 if (userP->listMembership == PTS_USER_ANYUSER_ACCESS) {
2288 if (userP->listGroupsOwned == PTS_USER_ANYUSER_ACCESS) {
2292 if (userP->listStatus == PTS_USER_ANYUSER_ACCESS) {
2307 * pts_UserModify - update a user entry.
2311 * IN cellHandle - a previously opened cellHandle that corresponds
2312 * to the cell where the group exists.
2314 * IN userName - the name of the user to update.
2316 * IN newEntryP - a pointer to a pts_UserUpdateEntry_t that contains the
2317 * new information for user.
2321 * No locks are held by this function
2325 * Returns != 0 upon successful completion.
2329 int ADMINAPI pts_UserModify(
2330 const void *cellHandle,
2331 const char *userName,
2332 const pts_UserUpdateEntry_p newEntryP,
2336 afs_status_t tst = 0;
2337 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2338 afs_int32 userId = 0;
2339 afs_int32 newQuota = 0;
2341 afs_int32 flags = 0;
2344 * Validate arguments
2347 if (!IsValidCellHandle(c_handle, &tst)) {
2348 goto fail_pts_UserModify;
2351 if ((userName == NULL) || (*userName == 0)) {
2352 tst = ADMPTSUSERNAMENULL;
2353 goto fail_pts_UserModify;
2356 if (newEntryP == NULL) {
2357 tst = ADMPTSNEWENTRYPNULL;
2358 goto fail_pts_UserModify;
2362 * Translate the user name into an id.
2365 if (!TranslateOneName(c_handle, userName, ADMPTSUSERNAMETOOLONG,
2367 goto fail_pts_UserModify;
2371 if (newEntryP->flag & PTS_USER_UPDATE_GROUP_CREATE_QUOTA) {
2372 mask |= PR_SF_NGROUPS;
2373 newQuota = newEntryP->groupCreationQuota;
2376 if (newEntryP->flag & PTS_USER_UPDATE_PERMISSIONS) {
2377 mask |= PR_SF_ALLBITS;
2378 if (!SetUserAccess(newEntryP, &flags, &tst)) {
2379 goto fail_pts_UserModify;
2387 tst = ubik_Call(PR_SetFieldsEntry, c_handle->pts, 0, userId, mask, flags,
2391 goto fail_pts_UserModify;
2395 fail_pts_UserModify:
2404 * pts_UserMaxGet - get the maximum in use user id.
2408 * IN cellHandle - a previously opened cellHandle that corresponds
2409 * to the cell where the group exists.
2411 * OUT maxUserId - upon successful completion contains the max in use id.
2415 * No locks are held by this function
2419 * Returns != 0 upon successful completion.
2423 int ADMINAPI pts_UserMaxGet(
2424 const void *cellHandle,
2429 afs_status_t tst = 0;
2430 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2431 afs_int32 maxGroupId = 0;
2434 * Validate arguments
2437 if (!IsValidCellHandle(c_handle, &tst)) {
2438 goto fail_pts_UserMaxGet;
2441 if (maxUserId == NULL) {
2442 tst = ADMPTSMAXUSERIDNULL;
2443 goto fail_pts_UserMaxGet;
2446 tst = ubik_Call(PR_ListMax, c_handle->pts, 0, maxUserId, &maxGroupId);
2449 goto fail_pts_UserMaxGet;
2453 fail_pts_UserMaxGet:
2462 * pts_UserMaxSet - set the maximum user id.
2466 * IN cellHandle - a previously opened cellHandle that corresponds
2467 * to the cell where the group exists.
2469 * IN maxUserId - the new max user id.
2473 * No locks are held by this function
2477 * Returns != 0 upon successful completion.
2481 int ADMINAPI pts_UserMaxSet(
2482 const void *cellHandle,
2487 afs_status_t tst = 0;
2488 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2491 * Validate arguments
2494 if (!IsValidCellHandle(c_handle, &tst)) {
2495 goto fail_pts_UserMaxSet;
2498 tst = ubik_Call(PR_SetMax, c_handle->pts, 0, maxUserId, 0);
2501 goto fail_pts_UserMaxSet;
2505 fail_pts_UserMaxSet:
2514 * pts_UserMemberListBegin - begin iterating over the list of groups
2515 * a particular user belongs to.
2519 * IN cellHandle - a previously opened cellHandle that corresponds
2520 * to the cell where the group exists.
2522 * IN groupName - the group whose members will be returned.
2524 * OUT iterationIdP - upon successful completion contains a iterator that
2525 * can be passed to pts_GroupMemberListNext.
2529 * No locks are obtained or released by this function
2533 * Returns != 0 upon successful completion.
2537 int ADMINAPI pts_UserMemberListBegin(
2538 const void *cellHandle,
2539 const char *userName,
2540 void **iterationIdP,
2543 return MemberListBegin(cellHandle, userName, ADMPTSUSERNAMENULL,
2544 ADMPTSUSERNAMETOOLONG, iterationIdP, st);
2549 * pts_UserMemberListNext - get the next group a user belongs to
2553 * IN iterationId - an iterator previously returned by pts_UserMemberListBegin
2555 * OUT userName - upon successful completion contains the next group a user
2560 * The iterator mutex is held during the retrieval of the next member.
2564 * Returns != 0 upon successful completion.
2568 int ADMINAPI pts_UserMemberListNext(
2569 const void *iterationId,
2573 return pts_GroupMemberListNext(iterationId, userName, st);
2577 * pts_UserMemberListDone - finish using a user list iterator
2581 * IN iterationId - an iterator previously returned by pts_UserMemberListBegin
2585 * The iterator is locked and then destroyed
2589 * Returns != 0 upon successful completion.
2593 * It is the user's responsibility to make sure pts_UserMemberListDone
2594 * is called only once for each iterator.
2597 int ADMINAPI pts_UserMemberListDone(
2598 const void *iterationId,
2601 return pts_GroupMemberListDone(iterationId, st);
2604 typedef struct owned_group_list {
2605 namelist owned_names; /* the list of character names owned by this id */
2606 prlist owned_ids; /* the list of pts ids owned by this id */
2607 afs_int32 index; /* the index into owned_names for the next group */
2608 afs_int32 owner; /* the pts id of the owner */
2609 afs_int32 more; /* the last parameter to PR_ListOwned */
2610 int finished_retrieving; /* set when we've processed the last owned_names */
2611 afs_cell_handle_p c_handle; /* ubik client to pts server's from c_handle */
2612 char group[CACHED_ITEMS][PTS_MAX_NAME_LEN]; /* cache of names */
2613 } owned_group_list_t, *owned_group_list_p;
2615 static int DeleteOwnedGroupSpecificData(
2620 afs_status_t tst = 0;
2621 owned_group_list_p list = (owned_group_list_p) rpc_specific;
2623 if (list->owned_names.namelist_val != NULL) {
2624 free(list->owned_names.namelist_val);
2627 if (list->owned_ids.prlist_val != NULL) {
2628 free(list->owned_ids.prlist_val);
2638 static int GetOwnedGroupRPC(
2642 int *last_item_contains_data,
2646 afs_status_t tst = 0;
2647 owned_group_list_p list = (owned_group_list_p) rpc_specific;
2650 * We really don't make an rpc for every entry we return here
2651 * since the pts interface allows several members to be returned
2652 * with one rpc, but we fake it to make the iterator happy.
2656 * Check to see if we are done retrieving data
2659 if ((list->finished_retrieving) &&
2660 (list->owned_names.namelist_len == 0)) {
2662 *last_item_contains_data = 0;
2663 goto fail_GetOwnedGroupRPC;
2667 * Check to see if we really need to make an rpc
2670 if ((!list->finished_retrieving) && (list->owned_names.namelist_len == 0)) {
2671 tst = ubik_Call(PR_ListOwned, list->c_handle->pts, 0, list->owner,
2672 &list->owned_ids, &list->more);
2674 goto fail_GetOwnedGroupRPC;
2677 if (!TranslatePTSIds(list->c_handle, &list->owned_names,
2678 (idlist *) &list->owned_ids, &tst)) {
2679 goto fail_GetOwnedGroupRPC;
2683 if (list->owned_names.namelist_val == NULL) {
2685 *last_item_contains_data = 0;
2686 goto fail_GetOwnedGroupRPC;
2691 * We can retrieve the next group from data we already received
2694 strcpy(&list->group[slot], &list->owned_names.namelist_val[list->index]);
2698 * Check to see if there is more data to be retrieved
2699 * We need to free up the previously retrieved data here
2700 * and then check to see if the last rpc indicated that there
2701 * were more items to retrieve.
2704 if (list->index >= list->owned_names.namelist_len) {
2705 list->owned_names.namelist_len = 0;
2706 free(list->owned_names.namelist_val);
2707 list->owned_names.namelist_val = 0;
2709 list->owned_ids.prlist_len = 0;
2710 free(list->owned_ids.prlist_val);
2711 list->owned_ids.prlist_val = 0;
2714 list->finished_retrieving = 1;
2719 fail_GetOwnedGroupRPC:
2727 static int GetOwnedGroupFromCache(
2734 afs_status_t tst = 0;
2735 owned_group_list_p list = (owned_group_list_p) rpc_specific;
2737 strcpy((char *) dest, &list->group[slot]);
2748 * pts_OwnedGroupListBegin - begin iterating over the list of groups
2749 * a particular user owns.
2753 * IN cellHandle - a previously opened cellHandle that corresponds
2754 * to the cell where the group exists.
2756 * IN ownerName - the owner of the groups of interest.
2758 * OUT iterationIdP - upon successful completion contains a iterator that
2759 * can be passed to pts_OwnedGroupListNext.
2763 * No locks are held by this function
2767 * Returns != 0 upon successful completion.
2771 int ADMINAPI pts_OwnedGroupListBegin(
2772 const void *cellHandle,
2773 const char *userName,
2774 void **iterationIdP,
2778 afs_status_t tst = 0;
2779 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2780 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2781 owned_group_list_p list = (owned_group_list_p) malloc(sizeof(owned_group_list_t));
2784 * Validate arguments
2787 if (!IsValidCellHandle(c_handle, &tst)) {
2788 goto fail_pts_OwnedGroupListBegin;
2791 if ((userName == NULL) || (*userName == 0)) {
2792 tst = ADMPTSUSERNAMENULL;
2793 goto fail_pts_OwnedGroupListBegin;
2796 if (iterationIdP == NULL) {
2797 tst = ADMITERATORNULL;
2798 goto fail_pts_OwnedGroupListBegin;
2801 if ((iter == NULL) || (list == NULL)) {
2803 goto fail_pts_OwnedGroupListBegin;
2807 * Initialize the iterator specific data
2811 list->finished_retrieving = 0;
2812 list->c_handle = c_handle;
2813 list->owned_names.namelist_len = 0;
2814 list->owned_names.namelist_val = 0;
2815 list->owned_ids.prlist_len = 0;
2816 list->owned_ids.prlist_val = 0;
2819 * Translate the user name into an id.
2822 if (!TranslateOneName(c_handle, userName, ADMPTSUSERNAMETOOLONG,
2823 &list->owner, &tst)) {
2824 goto fail_pts_OwnedGroupListBegin;
2827 if (IteratorInit(iter, (void *) list, GetOwnedGroupRPC,
2828 GetOwnedGroupFromCache, NULL,
2829 DeleteOwnedGroupSpecificData, &tst)) {
2830 *iterationIdP = (void *) iter;
2834 fail_pts_OwnedGroupListBegin:
2852 * pts_OwnedGroupListNext - get the next group a user owns.
2856 * IN iterationId - an iterator previously returned by pts_OwnedGroupListBegin
2858 * OUT groupName - upon successful completion contains the next group a user
2863 * The iterator mutex is held during the retrieval of the next member.
2867 * Returns != 0 upon successful completion.
2871 int ADMINAPI pts_OwnedGroupListNext(
2872 const void *iterationId,
2877 afs_status_t tst = 0;
2878 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2881 * Validate arguments
2884 if (iterationId == NULL) {
2885 tst = ADMITERATORNULL;
2886 goto fail_pts_OwnedGroupListNext;
2889 if (groupName == NULL) {
2890 tst = ADMPTSGROUPNAMENULL;
2891 goto fail_pts_OwnedGroupListNext;
2894 rc = IteratorNext(iter, (void *) groupName, &tst);
2896 fail_pts_OwnedGroupListNext:
2905 * pts_OwnedGroupListDone - finish using a group list iterator
2909 * IN iterationId - an iterator previously returned by pts_OwnedGroupListBegin
2913 * The iterator is locked and then destroyed
2917 * Returns != 0 upon successful completion.
2921 * It is the user's responsibility to make sure pts_OwnedGroupListDone
2922 * is called only once for each iterator.
2925 int ADMINAPI pts_OwnedGroupListDone(
2926 const void *iterationId,
2930 afs_status_t tst = 0;
2931 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2934 * Validate arguments
2937 if (iterationId == NULL) {
2938 tst = ADMITERATORNULL;
2939 goto fail_pts_OwnedGroupListDone;
2942 rc = IteratorDone(iter, &tst);
2944 fail_pts_OwnedGroupListDone:
2952 typedef struct pts_list {
2953 prlistentries *names; /* the current list of pts names in this cell */
2954 prlistentries *currName; /* the current pts entry */
2955 afs_int32 index; /* the index into names for the next pts entry */
2956 afs_int32 nextstartindex; /* the next start index for the RPC */
2957 afs_int32 nentries; /* the number of entries in names */
2958 afs_int32 flag; /* the type of the list */
2959 int finished_retrieving; /* set when we've processed the last owned_names */
2960 afs_cell_handle_p c_handle; /* ubik client to pts server's from c_handle */
2961 char entries[CACHED_ITEMS][PTS_MAX_NAME_LEN]; /* cache of pts names */
2962 } pts_list_t, *pts_list_p;
2964 static int DeletePTSSpecificData(
2969 afs_status_t tst = 0;
2970 pts_list_p list = (pts_list_p) rpc_specific;
2984 static int GetPTSRPC(
2988 int *last_item_contains_data,
2992 afs_status_t tst = 0;
2993 pts_list_p list = (pts_list_p) rpc_specific;
2996 * We really don't make an rpc for every entry we return here
2997 * since the pts interface allows several members to be returned
2998 * with one rpc, but we fake it to make the iterator happy.
3002 * Check to see if we are done retrieving data
3005 if (list->finished_retrieving) {
3007 *last_item_contains_data = 0;
3008 goto fail_GetPTSRPC;
3012 * Check to see if we really need to make an rpc
3015 if ((!list->finished_retrieving) && (list->index >= list->nentries) ) {
3016 afs_int32 start = list->nextstartindex;
3017 prentries bulkentries;
3018 list->nextstartindex = -1;
3019 bulkentries.prentries_val = 0;
3020 bulkentries.prentries_len = 0;
3022 tst = ubik_Call(PR_ListEntries, list->c_handle->pts, 0, list->flag, start,
3023 &bulkentries, &(list->nextstartindex) );
3026 goto fail_GetPTSRPC;
3029 list->nentries = bulkentries.prentries_len;
3030 list->names = bulkentries.prentries_val;
3033 list->currName = list->names;
3038 * We can retrieve the next entry from data we already received
3041 strcpy(&list->entries[slot], list->currName->name);
3047 * Check to see if there is more data to be retrieved
3048 * We need to free up the previously retrieved data here
3049 * and then check to see if the last rpc indicated that there
3050 * were more items to retrieve.
3053 if (list->index >= list->nentries) {
3059 if (list->nextstartindex == -1) {
3060 list->finished_retrieving = 1;
3074 static int GetPTSFromCache(
3081 afs_status_t tst = 0;
3082 pts_list_p list = (pts_list_p) rpc_specific;
3084 strcpy((char *) dest, &list->entries[slot]);
3095 * pts_UserListBegin - begin iterating over the list of users
3096 * in a particular cell
3100 * IN cellHandle - a previously opened cellHandle that corresponds
3101 * to the cell where the users exist.
3103 * OUT iterationIdP - upon successful completion contains a iterator that
3104 * can be passed to pts_UserListNext.
3108 * No locks are held by this function
3112 * Returns != 0 upon successful completion.
3116 int ADMINAPI pts_UserListBegin(
3117 const void *cellHandle,
3118 void **iterationIdP,
3122 afs_status_t tst = 0;
3123 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3124 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
3125 pts_list_p list = (pts_list_p) malloc(sizeof(pts_list_t));
3128 * Validate arguments
3131 if (!IsValidCellHandle(c_handle, &tst)) {
3132 goto fail_pts_UserListBegin;
3135 if (iterationIdP == NULL) {
3136 tst = ADMITERATORNULL;
3137 goto fail_pts_UserListBegin;
3140 if ((iter == NULL) || (list == NULL)) {
3142 goto fail_pts_UserListBegin;
3146 * Initialize the iterator specific data
3150 list->finished_retrieving = 0;
3151 list->c_handle = c_handle;
3153 list->nextstartindex = 0;
3155 list->flag = PRUSERS;
3157 if (IteratorInit(iter, (void *) list, GetPTSRPC,
3158 GetPTSFromCache, NULL,
3159 DeletePTSSpecificData, &tst)) {
3160 *iterationIdP = (void *) iter;
3164 fail_pts_UserListBegin:
3182 * pts_UserListNext - get the next user in the cell.
3186 * IN iterationId - an iterator previously returned by pts_UserListBegin
3188 * OUT groupName - upon successful completion contains the next user
3192 * The iterator mutex is held during the retrieval of the next member.
3196 * Returns != 0 upon successful completion.
3200 int ADMINAPI pts_UserListNext(
3201 const void *iterationId,
3206 afs_status_t tst = 0;
3207 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3210 * Validate arguments
3213 if (iterationId == NULL) {
3214 tst = ADMITERATORNULL;
3215 goto fail_pts_UserListNext;
3218 if (userName == NULL) {
3219 tst = ADMPTSUSERNAMENULL;
3220 goto fail_pts_UserListNext;
3223 rc = IteratorNext(iter, (void *) userName, &tst);
3225 fail_pts_UserListNext:
3234 * pts_UserListDone - finish using a user list iterator
3238 * IN iterationId - an iterator previously returned by pts_UserListBegin
3242 * The iterator is locked and then destroyed
3246 * Returns != 0 upon successful completion.
3250 * It is the user's responsibility to make sure pts_UserListDone
3251 * is called only once for each iterator.
3254 int ADMINAPI pts_UserListDone(
3255 const void *iterationId,
3259 afs_status_t tst = 0;
3260 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3263 * Validate arguments
3266 if (iterationId == NULL) {
3267 tst = ADMITERATORNULL;
3268 goto fail_pts_UserListDone;
3271 rc = IteratorDone(iter, &tst);
3273 fail_pts_UserListDone:
3282 * pts_GroupListBegin - begin iterating over the list of groups
3283 * in a particular cell.
3287 * IN cellHandle - a previously opened cellHandle that corresponds
3288 * to the cell where the groups exist.
3290 * OUT iterationIdP - upon successful completion contains a iterator that
3291 * can be passed to pts_GroupListNext.
3295 * No locks are held by this function
3299 * Returns != 0 upon successful completion.
3303 int ADMINAPI pts_GroupListBegin(
3304 const void *cellHandle,
3305 void **iterationIdP,
3309 afs_status_t tst = 0;
3310 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3311 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
3312 pts_list_p list = (pts_list_p) malloc(sizeof(pts_list_t));
3315 * Validate arguments
3318 if (!IsValidCellHandle(c_handle, &tst)) {
3319 goto fail_pts_GroupListBegin;
3322 if (iterationIdP == NULL) {
3323 tst = ADMITERATORNULL;
3324 goto fail_pts_GroupListBegin;
3327 if ((iter == NULL) || (list == NULL)) {
3329 goto fail_pts_GroupListBegin;
3333 * Initialize the iterator specific data
3337 list->finished_retrieving = 0;
3338 list->c_handle = c_handle;
3340 list->nextstartindex = 0;
3342 list->flag = PRGROUPS;
3344 if (IteratorInit(iter, (void *) list, GetPTSRPC,
3345 GetPTSFromCache, NULL,
3346 DeletePTSSpecificData, &tst)) {
3347 *iterationIdP = (void *) iter;
3351 fail_pts_GroupListBegin:
3369 * pts_UserListNext - get the next group in a cell.
3373 * IN iterationId - an iterator previously returned by pts_GroupListBegin
3375 * OUT groupName - upon successful completion contains the next group
3379 * The iterator mutex is held during the retrieval of the next member.
3383 * Returns != 0 upon successful completion.
3387 int ADMINAPI pts_GroupListNext(
3388 const void *iterationId,
3393 afs_status_t tst = 0;
3394 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3397 * Validate arguments
3400 if (iterationId == NULL) {
3401 tst = ADMITERATORNULL;
3402 goto fail_pts_GroupListNext;
3405 if (groupName == NULL) {
3406 tst = ADMPTSGROUPNAMENULL;
3407 goto fail_pts_GroupListNext;
3410 rc = IteratorNext(iter, (void *) groupName, &tst);
3412 fail_pts_GroupListNext:
3421 * pts_GroupListDone - finish using a group list iterator
3425 * IN iterationId - an iterator previously returned by pts_GroupListBegin
3429 * The iterator is locked and then destroyed
3433 * Returns != 0 upon successful completion.
3437 * It is the user's responsibility to make sure pts_GroupListDone
3438 * is called only once for each iterator.
3441 int ADMINAPI pts_GroupListDone(
3442 const void *iterationId,
3446 afs_status_t tst = 0;
3447 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3450 * Validate arguments
3453 if (iterationId == NULL) {
3454 tst = ADMITERATORNULL;
3455 goto fail_pts_GroupListDone;
3458 rc = IteratorDone(iter, &tst);
3460 fail_pts_GroupListDone: