reindent-20030715
[openafs.git] / src / JAVA / libjafs / Group.c
1 /*
2  * Copyright (c) 2001-2002 International Business Machines Corp.
3  * All rights reserved.
4  *
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
8  * 
9  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
13  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  */
21
22 #include "Internal.h"
23 #include "org_openafs_jafs_Group.h"
24
25 #include <stdio.h>
26 #include <afs_ptsAdmin.h>
27 #include <afs_AdminPtsErrors.h>
28 #include <afs_AdminClientErrors.h>
29 #include <afs_AdminCommonErrors.h>
30 #include <pterror.h>
31
32 /////  definitions in Internal.c ///////////////
33
34 extern jclass userCls;
35 //extern jfieldID user_cellHandleField;
36 extern jfieldID user_nameField;
37 extern jfieldID user_cachedInfoField;
38
39 extern jclass groupCls;
40 extern jfieldID group_nameField;
41 extern jfieldID group_nameUidField;
42 extern jfieldID group_ownerUidField;
43 extern jfieldID group_creatorUidField;
44 extern jfieldID group_listStatusField;
45 extern jfieldID group_listGroupsOwnedField;
46 extern jfieldID group_listMembershipField;
47 extern jfieldID group_listAddField;
48 extern jfieldID group_listDeleteField;
49 extern jfieldID group_membershipCountField;
50 extern jfieldID group_ownerField;
51 extern jfieldID group_creatorField;
52
53 //////////////////////////////////////////////////////
54
55
56 /**
57  * Creates the PTS entry for a new group.  Pass in 0 for the uid if PTS is to
58  * automatically assign the group id.
59  *
60  * env      the Java environment
61  * cls      the current Java class
62  * cellHandle    the handle of the cell to which the group belongs
63  * jgroupName      the name of the group to create
64  * jownerName      the owner of this group
65  * gid     the group id to assign to the group (0 to have one 
66  *                automatically assigned)
67  */
68 JNIEXPORT void JNICALL
69 Java_org_openafs_jafs_Group_create(JNIEnv * env, jclass cls, jint cellHandle,
70                                    jstring jgroupName, jstring jownerName,
71                                    jint gid)
72 {
73     afs_status_t ast;
74     // convert java strings
75     char *groupName;
76     char *ownerName;
77
78     if (jgroupName != NULL) {
79         groupName = getNativeString(env, jgroupName);
80         if (groupName == NULL) {
81             throwAFSException(env, JAFSADMNOMEM);
82             return;
83         }
84     } else {
85         throwAFSException(env, JAFSNULLGROUP);
86         return;
87     }
88
89     if (jownerName != NULL) {
90         ownerName = getNativeString(env, jownerName);
91         if (ownerName == NULL) {
92             free(groupName);
93             throwAFSException(env, JAFSADMNOMEM);
94             return;
95         }
96     } else {
97         free(groupName);
98         throwAFSException(env, JAFSNULLOWNER);
99         return;
100     }
101
102     // make sure the name is within the allowed bounds
103     if (strlen(groupName) > PTS_MAX_NAME_LEN) {
104         // release converted java strings
105         free(groupName);
106         free(ownerName);
107         throwAFSException(env, ADMPTSGROUPNAMETOOLONG);
108         return;
109     }
110
111     if (!pts_GroupCreate
112         ((void *)cellHandle, groupName, ownerName, (int *)&gid, &ast)) {
113         // release converted java strings
114         free(groupName);
115         free(ownerName);
116         throwAFSException(env, ast);
117         return;
118     }
119     // release converted java strings
120     free(groupName);
121     free(ownerName);
122 }
123
124 /**
125  * Deletes the PTS entry for a group.  Deletes this group from the 
126  * membership list of the users that belonged to it, but does not delete 
127  * the groups owned by this group.
128  *
129  * env      the Java environment
130  * cls      the current Java class
131  * cellHandle    the handle of the cell to which the group belongs
132  * jgroupName      the name of the group to delete
133  */
134 JNIEXPORT void JNICALL
135 Java_org_openafs_jafs_Group_delete(JNIEnv * env, jclass cls, jint cellHandle,
136                                    jstring jgroupName)
137 {
138     afs_status_t ast;
139     // convert java strings
140     char *groupName;
141
142     if (jgroupName != NULL) {
143         groupName = getNativeString(env, jgroupName);
144         if (!groupName) {
145             throwAFSException(env, JAFSADMNOMEM);
146             return;
147         }
148     } else {
149         throwAFSException(env, JAFSNULLGROUP);
150         return;
151     }
152
153     if (!pts_GroupDelete((void *)cellHandle, groupName, &ast)) {
154         throwAFSException(env, ast);
155     }
156     // release converted java strings
157     free(groupName);
158 }
159
160 /**
161  * Retrieve the information for the specified group and populate the
162  * given object
163  *
164  * env      the Java environment
165  * cellHandle    the handle of the cell to which the user belongs
166  * name      the name of the group for which to get the info
167  * group      the Group object to populate with the info
168  */
169 void
170 getGroupInfoChar(JNIEnv * env, jint cellHandle, const char *name,
171                  jobject group)
172 {
173
174     jstring jowner;
175     jstring jcreator;
176     pts_GroupEntry_t entry;
177     afs_status_t ast;
178     // get the field ids if you haven't already
179     if (groupCls == 0) {
180         internal_getGroupClass(env, group);
181     }
182
183     if (!pts_GroupGet((void *)cellHandle, name, &entry, &ast)) {
184         throwAFSException(env, ast);
185         return;
186     }
187     // set the fields
188     (*env)->SetIntField(env, group, group_nameUidField, entry.nameUid);
189     (*env)->SetIntField(env, group, group_ownerUidField, entry.ownerUid);
190     (*env)->SetIntField(env, group, group_creatorUidField, entry.creatorUid);
191     (*env)->SetIntField(env, group, group_membershipCountField,
192                         entry.membershipCount);
193
194     if (entry.listStatus == PTS_GROUP_OWNER_ACCESS) {
195         (*env)->SetIntField(env, group, group_listStatusField,
196                             org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
197     } else if (entry.listStatus == PTS_GROUP_ACCESS) {
198         (*env)->SetIntField(env, group, group_listStatusField,
199                             org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
200     } else {
201         (*env)->SetIntField(env, group, group_listStatusField,
202                             org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
203     }
204
205     if (entry.listGroupsOwned == PTS_GROUP_OWNER_ACCESS) {
206         (*env)->SetIntField(env, group, group_listGroupsOwnedField,
207                             org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
208     } else if (entry.listGroupsOwned == PTS_GROUP_ACCESS) {
209         (*env)->SetIntField(env, group, group_listGroupsOwnedField,
210                             org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
211     } else {
212         (*env)->SetIntField(env, group, group_listGroupsOwnedField,
213                             org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
214     }
215
216     if (entry.listMembership == PTS_GROUP_OWNER_ACCESS) {
217         (*env)->SetIntField(env, group, group_listMembershipField,
218                             org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
219     } else if (entry.listMembership == PTS_GROUP_ACCESS) {
220         (*env)->SetIntField(env, group, group_listMembershipField,
221                             org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
222     } else {
223         (*env)->SetIntField(env, group, group_listMembershipField,
224                             org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
225     }
226
227     if (entry.listAdd == PTS_GROUP_OWNER_ACCESS) {
228         (*env)->SetIntField(env, group, group_listAddField,
229                             org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
230     } else if (entry.listAdd == PTS_GROUP_ACCESS) {
231         (*env)->SetIntField(env, group, group_listAddField,
232                             org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
233     } else {
234         (*env)->SetIntField(env, group, group_listAddField,
235                             org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
236     }
237
238     if (entry.listDelete == PTS_GROUP_OWNER_ACCESS) {
239         (*env)->SetIntField(env, group, group_listDeleteField,
240                             org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
241     } else if (entry.listDelete == PTS_GROUP_ACCESS) {
242         (*env)->SetIntField(env, group, group_listDeleteField,
243                             org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
244     } else {
245         (*env)->SetIntField(env, group, group_listDeleteField,
246                             org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
247     }
248
249     jowner = (*env)->NewStringUTF(env, entry.owner);
250     jcreator = (*env)->NewStringUTF(env, entry.creator);
251
252     (*env)->SetObjectField(env, group, group_ownerField, jowner);
253     (*env)->SetObjectField(env, group, group_creatorField, jcreator);
254 }
255
256 /**
257  * Fills in the information fields of the provided Group.  
258  * Fills in values based on the current PTS information of the group.
259  *
260  * env      the Java environment
261  * cls      the current Java class
262  * cellHandle    the handle of the cell to which the group belongs
263  * name     the name of the group for which to get the information
264  * group     the Group object in which to fill in the 
265  *                  information
266  */
267 JNIEXPORT void JNICALL
268 Java_org_openafs_jafs_Group_getGroupInfo(JNIEnv * env, jclass cls,
269                                          jint cellHandle, jstring jname,
270                                          jobject group)
271 {
272     char *name;
273
274     if (jname != NULL) {
275         name = getNativeString(env, jname);
276         if (!name) {
277             throwAFSException(env, JAFSADMNOMEM);
278             return;
279         }
280     } else {
281         throwAFSException(env, JAFSNULLGROUP);
282         return;
283     }
284     getGroupInfoChar(env, cellHandle, name, group);
285
286     // get class fields if need be
287     if (groupCls == 0) {
288         internal_getGroupClass(env, group);
289     }
290     // set name in case blank object
291     (*env)->SetObjectField(env, group, group_nameField, jname);
292
293     free(name);
294 }
295
296 /**
297  * Sets the information values of this AFS group to be the parameter values.
298  *
299  * env      the Java environment
300  * cls      the current Java class
301  * cellHandle    the handle of the cell to which the user belongs
302  * name     the name of the user for which to set the information
303  * theGroup   the group object containing the desired information
304  */
305 JNIEXPORT void JNICALL
306 Java_org_openafs_jafs_Group_setGroupInfo(JNIEnv * env, jclass cls,
307                                          jint cellHandle, jstring jname,
308                                          jobject group)
309 {
310     char *name;
311     pts_GroupUpdateEntry_t ptsEntry;
312     afs_status_t ast;
313
314     jint jlistStatus;
315     jint jlistGroupsOwned;
316     jint jlistMembership;
317     jint jlistAdd;
318     jint jlistDelete;
319
320     // get the field ids if you haven't already
321     if (groupCls == 0) {
322         internal_getGroupClass(env, group);
323     }
324
325     jlistStatus = (*env)->GetIntField(env, group, group_listStatusField);
326     jlistGroupsOwned =
327         (*env)->GetIntField(env, group, group_listGroupsOwnedField);
328     jlistMembership =
329         (*env)->GetIntField(env, group, group_listMembershipField);
330     jlistAdd = (*env)->GetIntField(env, group, group_listAddField);
331     jlistDelete = (*env)->GetIntField(env, group, group_listDeleteField);
332
333     if (jname != NULL) {
334         name = getNativeString(env, jname);
335         if (name == NULL) {
336             throwAFSException(env, JAFSADMNOMEM);
337             return;
338         }
339     } else {
340         throwAFSException(env, JAFSNULLGROUP);
341         return;
342     }
343
344     if (jlistStatus == org_openafs_jafs_Group_GROUP_OWNER_ACCESS) {
345         ptsEntry.listStatus = PTS_GROUP_OWNER_ACCESS;
346     } else if (jlistStatus == org_openafs_jafs_Group_GROUP_GROUP_ACCESS) {
347         ptsEntry.listStatus = PTS_GROUP_ACCESS;
348     } else {
349         ptsEntry.listStatus = PTS_GROUP_ANYUSER_ACCESS;
350     }
351     if (jlistGroupsOwned == org_openafs_jafs_Group_GROUP_OWNER_ACCESS) {
352         ptsEntry.listGroupsOwned = PTS_GROUP_OWNER_ACCESS;
353     } else if (jlistGroupsOwned == org_openafs_jafs_Group_GROUP_GROUP_ACCESS) {
354         ptsEntry.listGroupsOwned = PTS_GROUP_ACCESS;
355     } else {
356         ptsEntry.listGroupsOwned = PTS_GROUP_ANYUSER_ACCESS;
357     }
358     if (jlistMembership == org_openafs_jafs_Group_GROUP_OWNER_ACCESS) {
359         ptsEntry.listMembership = PTS_GROUP_OWNER_ACCESS;
360     } else if (jlistMembership == org_openafs_jafs_Group_GROUP_GROUP_ACCESS) {
361         ptsEntry.listMembership = PTS_GROUP_ACCESS;
362     } else {
363         ptsEntry.listMembership = PTS_GROUP_ANYUSER_ACCESS;
364     }
365     if (jlistAdd == org_openafs_jafs_Group_GROUP_OWNER_ACCESS) {
366         ptsEntry.listAdd = PTS_GROUP_OWNER_ACCESS;
367     } else if (jlistAdd == org_openafs_jafs_Group_GROUP_GROUP_ACCESS) {
368         ptsEntry.listAdd = PTS_GROUP_ACCESS;
369     } else {
370         ptsEntry.listAdd = PTS_GROUP_ANYUSER_ACCESS;
371     }
372     if (jlistDelete == org_openafs_jafs_Group_GROUP_OWNER_ACCESS) {
373         ptsEntry.listDelete = PTS_GROUP_OWNER_ACCESS;
374     } else if (jlistDelete == org_openafs_jafs_Group_GROUP_GROUP_ACCESS) {
375         ptsEntry.listDelete = PTS_GROUP_ACCESS;
376     } else {
377         ptsEntry.listDelete = PTS_GROUP_ANYUSER_ACCESS;
378     }
379
380     if (!pts_GroupModify((void *)cellHandle, name, &ptsEntry, &ast)) {
381         throwAFSException(env, ast);
382     }
383
384     free(name);
385 }
386
387 /**
388  * Begin the process of getting the users that belong to the group.  Returns 
389  * an iteration ID to be used by subsequent calls to 
390  * getGroupMembersNext and getGroupMembersDone.  
391  *
392  * env      the Java environment
393  * cls      the current Java class
394  * cellHandle    the handle of the cell to which the group belongs
395  * jname          the name of the group for which to get the members
396  * returns an iteration ID
397  */
398 JNIEXPORT jint JNICALL
399 Java_org_openafs_jafs_Group_getGroupMembersBegin(JNIEnv * env, jclass cls,
400                                                  jint cellHandle,
401                                                  jstring jname)
402 {
403     char *name;
404     afs_status_t ast;
405     void *iterationId;
406
407     if (jname != NULL) {
408         name = getNativeString(env, jname);
409         if (name == NULL) {
410             throwAFSException(env, JAFSADMNOMEM);
411             return 0;
412         }
413     } else {
414         throwAFSException(env, JAFSNULLGROUP);
415         return 0;
416     }
417
418     if (!pts_GroupMemberListBegin
419         ((void *)cellHandle, name, &iterationId, &ast)) {
420         throwAFSException(env, ast);
421     }
422
423     free(name);
424
425     return (jint) iterationId;
426 }
427
428 /**
429  * Returns the next members that belongs to the group.  Returns 
430  * null if there are no more members.
431  *
432  * env      the Java environment
433  * cls      the current Java class
434  * iterationId   the iteration ID of this iteration
435  * returns the name of the next member
436  */
437 JNIEXPORT jstring JNICALL
438 Java_org_openafs_jafs_Group_getGroupMembersNextString(JNIEnv * env,
439                                                       jclass cls,
440                                                       jint iterationId)
441 {
442     afs_status_t ast;
443     char *userName = (char *)malloc(sizeof(char) * PTS_MAX_NAME_LEN);
444     jstring juser;
445
446     if (!userName) {
447         throwAFSException(env, JAFSADMNOMEM);
448         return;
449     }
450
451     if (!pts_GroupMemberListNext((void *)iterationId, userName, &ast)) {
452         free(userName);
453         if (ast == ADMITERATORDONE) {
454             return NULL;
455         } else {
456             throwAFSException(env, ast);
457             return;
458         }
459     }
460
461     juser = (*env)->NewStringUTF(env, userName);
462     free(userName);
463     return juser;
464 }
465
466 /**
467  * Fills the next user object belonging to that group.  Returns 0 if there
468  * are no more users, != 0 otherwise.
469  *
470  * env      the Java environment
471  * cls      the current Java class
472  * cellHandle    the handle of the cell to which the users belong
473  * iterationId   the iteration ID of this iteration
474  * juserObject   a User object to be populated with the values of the 
475  *                  next user
476  * returns 0 if there are no more users, != 0 otherwise
477  */
478 JNIEXPORT jint JNICALL
479 Java_org_openafs_jafs_Group_getGroupMembersNext(JNIEnv * env, jclass cls,
480                                                 jint cellHandle,
481                                                 jint iterationId,
482                                                 jobject juserObject)
483 {
484     afs_status_t ast;
485     char *userName;
486     jstring juser;
487
488     userName = (char *)malloc(sizeof(char) * PTS_MAX_NAME_LEN);
489
490     if (!userName) {
491         throwAFSException(env, JAFSADMNOMEM);
492         return;
493     }
494
495     if (!pts_GroupMemberListNext((void *)iterationId, userName, &ast)) {
496         free(userName);
497         if (ast == ADMITERATORDONE) {
498             return 0;
499         } else {
500             throwAFSException(env, ast);
501             return 0;
502         }
503     }
504
505     juser = (*env)->NewStringUTF(env, userName);
506
507     if (userCls == 0) {
508         internal_getUserClass(env, juserObject);
509     }
510
511     (*env)->SetObjectField(env, juserObject, user_nameField, juser);
512
513     getUserInfoChar(env, (void *)cellHandle, userName, juserObject);
514     (*env)->SetBooleanField(env, juserObject, user_cachedInfoField, TRUE);
515
516     free(userName);
517     return 1;
518
519 }
520
521 /**
522  * Signals that the iteration is complete and will not be accessed anymore.
523  *
524  * env      the Java environment
525  * cls      the current Java class
526  * iterationId   the iteration ID of this iteration
527  */
528 JNIEXPORT void JNICALL
529 Java_org_openafs_jafs_Group_getGroupMembersDone(JNIEnv * env, jclass cls,
530                                                 jint iterationId)
531 {
532     afs_status_t ast;
533
534     if (!pts_GroupMemberListDone((void *)iterationId, &ast)) {
535         throwAFSException(env, ast);
536         return;
537     }
538 }
539
540 /**
541  * Adds a user to the specified group. 
542  *
543  * env      the Java environment
544  * cls      the current Java class
545  * cellHandle    the handle of the cell to which the group belongs
546  * jgroupName          the name of the group to which to add a member
547  * juserName      the name of the user to add
548  */
549 JNIEXPORT void JNICALL
550 Java_org_openafs_jafs_Group_addMember(JNIEnv * env, jclass cls,
551                                       jint cellHandle, jstring jgroupName,
552                                       jstring juserName)
553 {
554     afs_status_t ast;
555     char *groupName;
556     char *userName;
557
558     if (jgroupName != NULL) {
559         groupName = getNativeString(env, jgroupName);
560         if (groupName == NULL) {
561             throwAFSException(env, JAFSADMNOMEM);
562             return;
563         }
564     } else {
565         throwAFSException(env, JAFSNULLGROUP);
566         return;
567     }
568
569     if (juserName != NULL) {
570         userName = getNativeString(env, juserName);
571         if (userName == NULL) {
572             free(groupName);
573             throwAFSException(env, JAFSADMNOMEM);
574             return;
575         }
576     } else {
577         free(groupName);
578         throwAFSException(env, JAFSNULLUSER);
579         return;
580     }
581
582     if (!pts_GroupMemberAdd((void *)cellHandle, userName, groupName, &ast)) {
583         throwAFSException(env, ast);
584     }
585
586     free(userName);
587     free(groupName);
588 }
589
590 /**
591  * Removes a user from the specified group. 
592  *
593  * env      the Java environment
594  * cls      the current Java class
595  * cellHandle    the handle of the cell to which the group belongs
596  * jgroupName          the name of the group from which to remove a 
597  *                           member
598  * juserName      the name of the user to remove
599  */
600 JNIEXPORT void JNICALL
601 Java_org_openafs_jafs_Group_removeMember(JNIEnv * env, jclass cls,
602                                          jint cellHandle, jstring jgroupName,
603                                          jstring juserName)
604 {
605     afs_status_t ast;
606     char *groupName;
607     char *userName;
608
609     if (jgroupName != NULL) {
610         groupName = getNativeString(env, jgroupName);
611         if (groupName == NULL) {
612             throwAFSException(env, JAFSADMNOMEM);
613             return;
614         }
615     } else {
616         throwAFSException(env, JAFSNULLGROUP);
617         return;
618     }
619
620     if (juserName != NULL) {
621         userName = getNativeString(env, juserName);
622         if (userName == NULL) {
623             free(groupName);
624             throwAFSException(env, JAFSADMNOMEM);
625             return;
626         }
627     } else {
628         free(groupName);
629         throwAFSException(env, JAFSNULLUSER);
630         return;
631     }
632
633     if (!pts_GroupMemberRemove((void *)cellHandle, userName, groupName, &ast)) {
634         throwAFSException(env, ast);
635     }
636
637     free(groupName);
638     free(userName);
639 }
640
641 /**
642  * Change the owner of the specified group. 
643  *
644  * env      the Java environment
645  * cls      the current Java class
646  * cellHandle    the handle of the cell to which the group belongs
647  * jgroupName          the name of the group of which to change the 
648  *                           owner
649  * jownerName      the name of the new owner
650  */
651 JNIEXPORT void JNICALL
652 Java_org_openafs_jafs_Group_changeOwner(JNIEnv * env, jclass cls,
653                                         jint cellHandle, jstring jgroupName,
654                                         jstring jownerName)
655 {
656     afs_status_t ast;
657     char *groupName;
658     char *ownerName;
659
660     if (jgroupName != NULL) {
661         groupName = getNativeString(env, jgroupName);
662         if (groupName == NULL) {
663             throwAFSException(env, JAFSADMNOMEM);
664             return;
665         }
666     } else {
667         throwAFSException(env, JAFSNULLGROUP);
668         return;
669     }
670
671     if (jownerName != NULL) {
672         ownerName = getNativeString(env, jownerName);
673         if (ownerName == NULL) {
674             free(groupName);
675             throwAFSException(env, JAFSADMNOMEM);
676             return;
677         }
678     } else {
679         free(groupName);
680         throwAFSException(env, JAFSNULLOWNER);
681         return;
682     }
683
684     if (!pts_GroupOwnerChange((void *)cellHandle, groupName, ownerName, &ast)) {
685         throwAFSException(env, ast);
686     }
687
688     free(groupName);
689     free(ownerName);
690 }
691
692 /**
693  * Change the name of the specified group. 
694  *
695  * env      the Java environment
696  * cls      the current Java class
697  * cellHandle    the handle of the cell to which the group belongs
698  * joldGroupName          the old name of the group
699  * jnewGroupName      the new name for the group
700  */
701 JNIEXPORT void JNICALL
702 Java_org_openafs_jafs_Group_rename(JNIEnv * env, jclass cls, jint cellHandle,
703                                    jstring jgroupOldName,
704                                    jstring jgroupNewName)
705 {
706     afs_status_t ast;
707     char *groupOldName;
708     char *groupNewName;
709
710     if (jgroupOldName != NULL) {
711         groupOldName = getNativeString(env, jgroupOldName);
712         if (groupOldName == NULL) {
713             throwAFSException(env, JAFSADMNOMEM);
714             return;
715         }
716     } else {
717         throwAFSException(env, JAFSNULLGROUP);
718         return;
719     }
720
721     if (jgroupNewName != NULL) {
722         groupNewName = getNativeString(env, jgroupNewName);
723         if (groupNewName == NULL) {
724             free(groupOldName);
725             throwAFSException(env, JAFSADMNOMEM);
726             return;
727         }
728     } else {
729         free(groupOldName);
730         throwAFSException(env, JAFSNULLGROUP);
731         return;
732     }
733
734     if (!pts_GroupRename
735         ((void *)cellHandle, groupOldName, groupNewName, &ast)) {
736         throwAFSException(env, ast);
737     }
738
739     free(groupOldName);
740     free(groupNewName);
741 }
742
743 // reclaim global memory used by this portion
744 JNIEXPORT void JNICALL
745 Java_org_openafs_jafs_Group_reclaimGroupMemory(JNIEnv * env, jclass cls)
746 {
747     if (groupCls) {
748         (*env)->DeleteGlobalRef(env, groupCls);
749         groupCls = 0;
750     }
751 }