afsconfig-and-rcsid-all-around-20010705
[openafs.git] / src / afs / SOLARIS / osi_groups.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
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
10 /*
11  * Implements:
12  * setgroups (syscall)
13  * setpag
14  *
15  */
16 #include "../afs/param.h"
17 #include <afsconfig.h>
18
19 RCSID("$Header$");
20
21 #include "../afs/sysincludes.h"
22 #include "../afs/afsincludes.h"
23 #include "../afs/afs_stats.h"  /* statistics */
24
25
26 static int
27 afs_getgroups(
28     struct cred *cred,
29     gid_t *gidset);
30
31 static int
32 afs_setgroups(
33     struct cred **cred,
34     int ngroups,
35     gid_t *gidset,
36     int change_parent);
37
38
39 #if     defined(AFS_SUN55_ENV)
40 int
41 afs_xsetgroups(uap, rvp)
42 u_int uap; /* this is gidsetsize */
43 gid_t *rvp; /* this is gidset */
44 #else 
45 struct setgroupsa {
46     u_int gidsetsize;
47     gid_t *gidset;
48 };
49
50 afs_xsetgroups(uap, rvp) 
51     struct setgroupsa *uap;
52     rval_t *rvp;
53 #endif
54 {
55     int code = 0;
56     struct vrequest treq;
57     struct proc *proc = ttoproc(curthread);
58
59     AFS_STATCNT(afs_xsetgroups);
60     AFS_GLOCK();
61     code = afs_InitReq(&treq, proc->p_cred);
62     AFS_GUNLOCK();
63     if (code) return code;
64     code = setgroups(uap, rvp);
65
66     /* Note that if there is a pag already in the new groups we don't
67      * overwrite it with the old pag.
68      */
69     if (PagInCred(proc->p_cred) == NOPAG) {
70         if (((treq.uid >> 24) & 0xff) == 'A') {
71             AFS_GLOCK();
72             /* we've already done a setpag, so now we redo it */
73             AddPag(treq.uid, &proc->p_cred);
74             AFS_GUNLOCK();
75         }
76     }
77     return code;
78 }
79
80 int
81 setpag(cred, pagvalue, newpag, change_parent)
82     struct cred **cred;
83     afs_uint32 pagvalue;
84     afs_uint32 *newpag;
85     afs_uint32 change_parent;
86 {
87     gid_t *gidset;
88     int ngroups, code;
89     int j;
90
91     AFS_STATCNT(setpag);
92
93     gidset = (gid_t *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
94     ngroups = afs_getgroups(*cred, gidset);
95
96     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
97         /* We will have to shift grouplist to make room for pag */
98         if ((sizeof gidset[0])*(ngroups + 2) > AFS_SMALLOCSIZ) {
99             osi_FreeSmallSpace((char *)gidset);
100             return (E2BIG);
101         }
102         for (j = ngroups -1; j >= 0; j--) {
103             gidset[j+2] = gidset[j];
104         }
105         ngroups += 2;
106     }
107     *newpag = (pagvalue == -1 ? genpag(): pagvalue);
108     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
109     if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
110         osi_FreeSmallSpace((char *)gidset);
111         return (code);
112     }
113     osi_FreeSmallSpace((char *)gidset);
114     return code;
115 }
116
117
118 static int
119 afs_getgroups(
120     struct cred *cred,
121     gid_t *gidset)
122 {
123     int ngrps, savengrps;
124     gid_t *gp;
125
126     AFS_STATCNT(afs_getgroups);
127
128     gidset[0] = gidset[1] = 0;
129     savengrps = ngrps = cred->cr_ngroups;
130     gp = cred->cr_groups;
131     while (ngrps--)
132         *gidset++ = *gp++;   
133     return savengrps;
134 }
135
136
137
138 static int
139 afs_setgroups(
140     struct cred **cred,
141     int ngroups,
142     gid_t *gidset,
143     int change_parent)
144 {
145     int ngrps;
146     int i;
147     gid_t *gp;
148
149     AFS_STATCNT(afs_setgroups);
150
151     if (ngroups > ngroups_max)
152         return EINVAL;
153     if (!change_parent)
154         *cred = (struct cred *)crcopy(*cred);
155     (*cred)->cr_ngroups = ngroups;
156     gp = (*cred)->cr_groups;
157     while (ngroups--)
158         *gp++ = *gidset++;
159     if (!change_parent) {
160         struct proc *proc = ttoproc(curthread);
161         crset(proc, *cred); /* broadcast to all threads */
162     }
163     return (0);
164 }