1 /*
2 * Copyright (C) 2008 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 * Author: David Zeuthen <davidz@redhat.com>
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <string.h>
27 #include <grp.h>
28 #include <errno.h>
29 #include "polkitunixgroup.h"
30 #include "polkitidentity.h"
31 #include "polkiterror.h"
32 #include "polkitprivate.h"
33
34 /**
35 * SECTION:polkitunixgroup
36 * @title: PolkitUnixGroup
37 * @short_description: Unix groups
38 *
39 * An object representing a group identity on a UNIX system.
40 */
41
42 /**
43 * PolkitUnixGroup:
44 *
45 * The #PolkitUnixGroup struct should not be accessed directly.
46 */
47 struct _PolkitUnixGroup
48 {
49 GObject parent_instance;
50
51 gint gid;
52 };
53
54 struct _PolkitUnixGroupClass
55 {
56 GObjectClass parent_class;
57 };
58
59 enum
60 {
61 PROP_0,
62 PROP_GID,
63 };
64
65 static void identity_iface_init (PolkitIdentityIface *identity_iface);
66
67 G_DEFINE_TYPE_WITH_CODE (PolkitUnixGroup, polkit_unix_group, G_TYPE_OBJECT,
68 G_IMPLEMENT_INTERFACE (POLKIT_TYPE_IDENTITY, identity_iface_init)
69 );
70
71 static void
polkit_unix_group_init(PolkitUnixGroup * unix_group)72 polkit_unix_group_init (PolkitUnixGroup *unix_group)
73 {
74 unix_group->gid = -1; /* (git_t) -1 is not a valid GID under Linux */
75 }
76
77 static void
polkit_unix_group_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)78 polkit_unix_group_get_property (GObject *object,
79 guint prop_id,
80 GValue *value,
81 GParamSpec *pspec)
82 {
83 PolkitUnixGroup *unix_group = POLKIT_UNIX_GROUP (object);
84
85 switch (prop_id)
86 {
87 case PROP_GID:
88 g_value_set_int (value, unix_group->gid);
89 break;
90
91 default:
92 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
93 break;
94 }
95 }
96
97 static void
polkit_unix_group_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)98 polkit_unix_group_set_property (GObject *object,
99 guint prop_id,
100 const GValue *value,
101 GParamSpec *pspec)
102 {
103 PolkitUnixGroup *unix_group = POLKIT_UNIX_GROUP (object);
104 gint val;
105
106 switch (prop_id)
107 {
108 case PROP_GID:
109 val = g_value_get_int (value);
110 g_return_if_fail (val != -1);
111 unix_group->gid = val;
112 break;
113
114 default:
115 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
116 break;
117 }
118 }
119
120 static void
polkit_unix_group_class_init(PolkitUnixGroupClass * klass)121 polkit_unix_group_class_init (PolkitUnixGroupClass *klass)
122 {
123 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
124
125 gobject_class->get_property = polkit_unix_group_get_property;
126 gobject_class->set_property = polkit_unix_group_set_property;
127
128 /**
129 * PolkitUnixGroup:gid:
130 *
131 * The UNIX group id.
132 */
133 g_object_class_install_property (gobject_class,
134 PROP_GID,
135 g_param_spec_int ("gid",
136 "Group ID",
137 "The UNIX group ID",
138 G_MININT,
139 G_MAXINT,
140 -1,
141 G_PARAM_CONSTRUCT |
142 G_PARAM_READWRITE |
143 G_PARAM_STATIC_NAME |
144 G_PARAM_STATIC_BLURB |
145 G_PARAM_STATIC_NICK));
146
147 }
148
149 /**
150 * polkit_unix_group_get_gid:
151 * @group: A #PolkitUnixGroup.
152 *
153 * Gets the UNIX group id for @group.
154 *
155 * Returns: A UNIX group id.
156 */
157 gint
polkit_unix_group_get_gid(PolkitUnixGroup * group)158 polkit_unix_group_get_gid (PolkitUnixGroup *group)
159 {
160 g_return_val_if_fail (POLKIT_IS_UNIX_GROUP (group), -1);
161 return group->gid;
162 }
163
164 /**
165 * polkit_unix_group_set_gid:
166 * @group: A #PolkitUnixGroup.
167 * @gid: A UNIX group id.
168 *
169 * Sets @gid for @group.
170 */
171 void
polkit_unix_group_set_gid(PolkitUnixGroup * group,gint gid)172 polkit_unix_group_set_gid (PolkitUnixGroup *group,
173 gint gid)
174 {
175 g_return_if_fail (POLKIT_IS_UNIX_GROUP (group));
176 g_return_if_fail (gid != -1);
177 group->gid = gid;
178 }
179
180 /**
181 * polkit_unix_group_new:
182 * @gid: A UNIX group id.
183 *
184 * Creates a new #PolkitUnixGroup object for @gid.
185 *
186 * Returns: (transfer full): A #PolkitUnixGroup object. Free with g_object_unref().
187 */
188 PolkitIdentity *
polkit_unix_group_new(gint gid)189 polkit_unix_group_new (gint gid)
190 {
191 g_return_val_if_fail (gid != -1, NULL);
192
193 return POLKIT_IDENTITY (g_object_new (POLKIT_TYPE_UNIX_GROUP,
194 "gid", gid,
195 NULL));
196 }
197
198 /**
199 * polkit_unix_group_new_for_name:
200 * @name: A UNIX group name.
201 * @error: Return location for error.
202 *
203 * Creates a new #PolkitUnixGroup object for a group with the group name
204 * @name.
205 *
206 * Returns: (transfer full): (allow-none): A #PolkitUnixGroup object or %NULL if @error
207 * is set.
208 */
209 PolkitIdentity *
polkit_unix_group_new_for_name(const gchar * name,GError ** error)210 polkit_unix_group_new_for_name (const gchar *name,
211 GError **error)
212 {
213 struct group *group;
214 PolkitIdentity *identity;
215
216 g_return_val_if_fail (name != NULL, NULL);
217 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
218
219 identity = NULL;
220
221 group = getgrnam (name);
222 if (group == NULL)
223 {
224 g_set_error (error,
225 POLKIT_ERROR,
226 POLKIT_ERROR_FAILED,
227 "No UNIX group with name %s: %s",
228 name,
229 g_strerror (errno));
230 goto out;
231 }
232
233 identity = polkit_unix_group_new (group->gr_gid);
234
235 out:
236 return identity;
237 }
238
239 static guint
polkit_unix_group_hash(PolkitIdentity * identity)240 polkit_unix_group_hash (PolkitIdentity *identity)
241 {
242 PolkitUnixGroup *group;
243
244 group = POLKIT_UNIX_GROUP (identity);
245
246 return g_direct_hash (GINT_TO_POINTER (((gint) (group->gid)) * 2 + 1));
247 }
248
249 static gboolean
polkit_unix_group_equal(PolkitIdentity * a,PolkitIdentity * b)250 polkit_unix_group_equal (PolkitIdentity *a,
251 PolkitIdentity *b)
252 {
253 PolkitUnixGroup *group_a;
254 PolkitUnixGroup *group_b;
255
256 group_a = POLKIT_UNIX_GROUP (a);
257 group_b = POLKIT_UNIX_GROUP (b);
258
259 return group_a->gid == group_b->gid;
260 }
261
262 static gchar *
polkit_unix_group_to_string(PolkitIdentity * identity)263 polkit_unix_group_to_string (PolkitIdentity *identity)
264 {
265 PolkitUnixGroup *group = POLKIT_UNIX_GROUP (identity);
266 struct group *gr;
267
268 gr = getgrgid (group->gid);
269
270 if (gr == NULL)
271 return g_strdup_printf ("unix-group:%d", group->gid);
272 else
273 return g_strdup_printf ("unix-group:%s", gr->gr_name);
274 }
275
276 static void
identity_iface_init(PolkitIdentityIface * identity_iface)277 identity_iface_init (PolkitIdentityIface *identity_iface)
278 {
279 identity_iface->hash = polkit_unix_group_hash;
280 identity_iface->equal = polkit_unix_group_equal;
281 identity_iface->to_string = polkit_unix_group_to_string;
282 }
283