Lots of fixes
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / privP.c
1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <privP.h>
21 #include <priv.h>
22 #include <bits/libc-lock.h>
23
24 __libc_lock_define_recursive (extern, __priv_lock);
25 libc_freeres_ptr (static priv_data_t *__data);
26
27 priv_data_t * __priv_parse_info (const priv_impl_info_t *pii)
28 {
29   priv_data_t *data = malloc (sizeof (priv_data_t));
30   if (!data)
31     return NULL;
32   memset (data, 0, sizeof (*data));
33   data->pd_setsize = pii->priv_setsize * sizeof (priv_chunk_t);
34
35   /* Iterate over all priv_info_t's. Note that the first priv_info_t follows
36      the header.  */
37   priv_info_t *pi = (priv_info_t *)((char *)pii + pii->priv_headersize);
38   uint32_t left = pii->priv_globalinfosize;
39   while (left)
40     {
41       switch (pi->priv_info_type)
42         {
43         case PRIV_INFO_SETNAMES:
44         case PRIV_INFO_PRIVNAMES:
45           if ((pi->priv_info_type == PRIV_INFO_SETNAMES &&
46                 data->pd_setnames) || (pi->priv_info_type ==
47                 PRIV_INFO_PRIVNAMES && data->pd_privnames))
48             break;
49
50           /* XXX: In priv_get*byname we linearlly scan the list of strins;
51              we could speed this up by sorting the strings here.  */
52
53           priv_info_names_t *pi_names = (priv_info_names_t *)pi;
54
55           /* Allocate memory for the index.  */
56           char **name_list = malloc (sizeof (char *) * pi_names->cnt);
57           if (!name_list)
58             goto err;
59           if (pi->priv_info_type == PRIV_INFO_SETNAMES)
60             {
61               data->pd_setnames = name_list;
62               data->pd_setnames_cnt = pi_names->cnt;
63             }
64           else
65             {
66               data->pd_privnames = name_list;
67               data->pd_privnames_cnt = pi_names->cnt;
68             }
69           data->pd_privnames_cnt = pi_names->cnt;
70
71           /* Setup the index.  */
72           char *names_ptr = pi_names->names;
73           for (int i = 0; i < pi_names->cnt; i++)
74             {
75               name_list[i] = names_ptr;
76               names_ptr += strlen (names_ptr) + 1;
77             }
78
79           break;
80
81         case PRIV_INFO_BASICPRIVS:
82           if (data->pd_basicprivs)
83             break;
84
85           if (pi->priv_info_size != data->pd_setsize)
86             break;
87           data->pd_basicprivs = ((priv_info_set_t *)pi)->set;
88
89           break;
90         }
91
92       left -= pi->priv_info_size;
93       pi = (priv_info_t *)((char *)pi + pi->priv_info_size);
94     }
95
96   return data;
97
98 err:
99
100   free (data->pd_setnames);
101   free (data->pd_privnames);
102   free (data);
103
104   return NULL;
105 }
106
107
108 void __priv_free_info (priv_data_t *data)
109 {
110   free (data->pd_setnames);
111   free (data->pd_privnames);
112   free (data);
113 }
114
115
116 const priv_data_t * __priv_parse_data_cached (void)
117 {
118   if (__data)
119     return __data;
120
121   __libc_lock_lock_recursive (__priv_lock);
122   __data = __priv_parse_info (getprivimplinfo ());
123   __libc_lock_unlock_recursive (__priv_lock);
124
125   return __data;
126 }