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