49ac59497a1e3fbaa2f6721cab7d42fc902275ef
[openafs.git] / src / afs / HPUX / 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 <afsconfig.h>
17 #include "../afs/param.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 static int
26 afs_getgroups(
27     struct ucred *cred,
28     int ngroups,
29     gid_t *gidset);
30
31 static int
32 afs_setgroups(
33     struct ucred **cred,
34     int ngroups,
35     gid_t *gidset,
36     int change_parent);
37
38 int
39 Afs_xsetgroups() 
40 {
41     int code = 0;
42     struct vrequest treq;
43
44     AFS_STATCNT(afs_xsetgroups);
45     AFS_GLOCK();
46     code = afs_InitReq(&treq, p_cred(u.u_procp));
47     AFS_GUNLOCK();
48     if (code) return code;
49     setgroups();
50
51     /* Note that if there is a pag already in the new groups we don't
52      * overwrite it with the old pag.
53      */
54     if (PagInCred(p_cred(u.u_procp)) == NOPAG) {
55         if (((treq.uid >> 24) & 0xff) == 'A') {
56             struct ucred *cred;
57             AFS_GLOCK();
58             /* we've already done a setpag, so now we redo it */
59             cred = p_cred(u.u_procp);
60             AddPag(treq.uid, &cred);
61             AFS_GUNLOCK();
62         }
63     }
64     return code;
65 }
66
67 int
68 setpag(cred, pagvalue, newpag, change_parent)
69     struct ucred **cred;
70     afs_uint32 pagvalue;
71     afs_uint32 *newpag;
72     afs_uint32 change_parent;
73 {
74     gid_t gidset[NGROUPS];
75     int ngroups, code;
76     int j;
77
78     AFS_STATCNT(setpag);
79     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
80     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
81         /* We will have to shift grouplist to make room for pag */
82         if (ngroups + 2 > NGROUPS) {
83             return (setuerror(E2BIG), E2BIG);
84         }
85         for (j = ngroups -1; j >= 0; j--) {
86             gidset[j+2] = gidset[j];
87         }
88         ngroups += 2;
89     }
90     *newpag = (pagvalue == -1 ? genpag(): pagvalue);
91     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
92
93     if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
94         return (setuerror(code), code);
95     }
96     return code;
97 }
98
99
100 static int
101 afs_getgroups(
102     struct ucred *cred,
103     int ngroups,
104     gid_t *gidset)
105 {
106     int ngrps, savengrps;
107     int *gp;
108
109     gidset[0] = gidset[1] = 0;
110     AFS_STATCNT(afs_getgroups);
111
112     for (gp = &cred->cr_groups[NGROUPS]; gp > cred->cr_groups; gp--) {
113         if (gp[-1] != NOGROUP)
114                 break;
115     }
116     savengrps = ngrps = MIN(ngroups, gp - cred->cr_groups);
117     for (gp = cred->cr_groups; ngrps--; )
118         *gidset++ = *gp++;
119     return savengrps;
120 }
121
122
123
124 static int
125 afs_setgroups(
126     struct ucred **cred,
127     int ngroups,
128     gid_t *gidset,
129     int change_parent)
130 {
131     int ngrps;
132     int i;
133     int *gp;
134     struct ucred *newcr;
135     ulong_t s;
136
137     AFS_STATCNT(afs_setgroups);
138     
139     if (!change_parent)
140         {
141             newcr = (struct ucred *)crdup(*cred);
142             /* nobody else has the pointer to newcr because we
143              ** just allocated it, so no need for locking */
144         }
145     else    
146         {
147             /* somebody else might have a pointer to this structure.
148              ** make sure we do not have a race condition */
149             newcr = *cred;
150             s = UP_SPL6();
151             SPINLOCK(cred_lock);
152         }
153     
154     /* copy the group info */
155     gp = newcr->cr_groups;
156     while (ngroups--)
157         *gp++ = *gidset++;
158     for ( ; gp < &(newcr)->cr_groups[NGROUPS]; gp++)
159         *gp = ((gid_t) -1);
160     
161     if ( !change_parent)
162         {
163             /* replace the new cred structure in the proc area */
164             struct ucred*        tmp;
165             tmp = *cred;                
166             set_p_cred(u.u_procp, newcr);
167             crfree(tmp);
168         }
169     else
170         {
171             (void) UP_SPLX(s);
172             SPINUNLOCK(cred_lock);
173         }
174     return (setuerror(0), 0);
175 }