1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
3 nautilus-users-groups-cache.c: cache of users' and groups' names.
5 Copyright (C) 2006 Zbigniew Chyla
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Author: Zbigniew Chyla <mail@zbigniew.chyla.pl>
26 #include "nautilus-users-groups-cache.h"
33 typedef struct _ExpiringCache ExpiringCache
;
35 /* times in milliseconds */
36 #define USERS_CACHE_EXPIRE_TIME (60 * 1000)
37 #define GROUPS_CACHE_EXPIRE_TIME (60 * 1000)
39 /* cache of users' names */
40 static ExpiringCache
*users_cache
= NULL
;
42 /* cache of groups' names */
43 static ExpiringCache
*groups_cache
= NULL
;
47 * Generic implementation of cache with guint keys and values which expire
48 * after specified amount of time.
51 typedef gpointer (*ExpiringCacheGetValFunc
) (guint key
);
56 /* Expiration time of cached value */
59 /* Called to obtain a value by a key */
60 ExpiringCacheGetValFunc get_value_func
;
62 /* Called to destroy a value */
63 GDestroyNotify value_destroy_func
;
65 /* Stores cached values */
66 GHashTable
*cached_values
;
70 typedef struct _ExpiringCacheEntry ExpiringCacheEntry
;
72 struct _ExpiringCacheEntry
80 static ExpiringCache
*
81 expiring_cache_new (time_t expire_time
, ExpiringCacheGetValFunc get_value_func
,
82 GDestroyNotify value_destroy_func
)
86 g_assert (get_value_func
!= NULL
);
88 cache
= g_new (ExpiringCache
, 1);
89 cache
->expire_time
= expire_time
;
90 cache
->get_value_func
= get_value_func
;
91 cache
->value_destroy_func
= value_destroy_func
;
92 cache
->cached_values
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
, NULL
, NULL
);
97 static ExpiringCacheEntry
*
98 expiring_cache_entry_new (ExpiringCache
*cache
, guint key
, gpointer value
)
100 ExpiringCacheEntry
*entry
;
102 entry
= g_slice_new (ExpiringCacheEntry
);
103 entry
->cache
= cache
;
105 entry
->value
= value
;
111 expiring_cache_entry_destroy (ExpiringCacheEntry
*entry
)
113 if (entry
->cache
->value_destroy_func
!= NULL
) {
114 entry
->cache
->value_destroy_func (entry
->value
);
116 g_slice_free (ExpiringCacheEntry
, entry
);
120 cb_cache_entry_expired (ExpiringCacheEntry
*entry
)
122 g_hash_table_remove (entry
->cache
->cached_values
, GSIZE_TO_POINTER (entry
->key
));
123 expiring_cache_entry_destroy (entry
);
129 expiring_cache_get_value (ExpiringCache
*cache
, guint key
)
131 ExpiringCacheEntry
*entry
;
133 g_assert (cache
!= NULL
);
135 if (!g_hash_table_lookup_extended (cache
->cached_values
, GSIZE_TO_POINTER (key
),
136 NULL
, (gpointer
) &entry
)) {
137 entry
= expiring_cache_entry_new (cache
, key
, cache
->get_value_func (key
));
138 g_hash_table_insert (cache
->cached_values
, GSIZE_TO_POINTER (key
), entry
);
139 g_timeout_add (cache
->expire_time
, (GSourceFunc
) cb_cache_entry_expired
, entry
);
147 * Cache of users' names based on ExpiringCache.
150 typedef struct _UserInfo UserInfo
;
159 user_info_new (struct passwd
*password_info
)
163 if (password_info
!= NULL
) {
164 uinfo
= g_slice_new (UserInfo
);
165 uinfo
->name
= g_strdup (password_info
->pw_name
);
166 uinfo
->gecos
= g_strdup (password_info
->pw_gecos
);
175 user_info_free (UserInfo
*uinfo
)
178 g_free (uinfo
->name
);
179 g_free (uinfo
->gecos
);
180 g_slice_free (UserInfo
, uinfo
);
185 users_cache_get_value (guint key
)
187 return user_info_new (getpwuid (key
));
191 get_cached_user_info(guint uid
)
193 if (users_cache
== NULL
) {
194 users_cache
= expiring_cache_new (USERS_CACHE_EXPIRE_TIME
, users_cache_get_value
,
195 (GDestroyNotify
) user_info_free
);
198 return expiring_cache_get_value (users_cache
, uid
);
202 * nautilus_users_cache_get_name:
204 * Returns name of user with given uid (using cached data if possible) or
205 * NULL in case a user with given uid can't be found.
207 * Returns: Newly allocated string or NULL.
210 nautilus_users_cache_get_name (uid_t uid
)
214 uinfo
= get_cached_user_info (uid
);
216 return g_strdup (uinfo
->name
);
223 * nautilus_users_cache_get_gecos:
225 * Returns gecos of user with given uid (using cached data if possible) or
226 * NULL in case a user with given uid can't be found.
228 * Returns: Newly allocated string or NULL.
231 nautilus_users_cache_get_gecos (uid_t uid
)
235 uinfo
= get_cached_user_info (uid
);
237 return g_strdup (uinfo
->gecos
);
244 * Cache of groups' names based on ExpiringCache.
248 groups_cache_get_value (guint key
)
250 struct group
*group_info
;
252 group_info
= getgrgid (GPOINTER_TO_SIZE (key
));
253 if (group_info
!= NULL
) {
254 return g_strdup (group_info
->gr_name
);
262 * nautilus_groups_cache_get_name:
264 * Returns name of group with given gid (using cached data if possible) or
265 * NULL in case a group with given gid can't be found.
267 * Returns: Newly allocated string or NULL.
270 nautilus_groups_cache_get_name (gid_t gid
)
272 if (groups_cache
== NULL
) {
273 groups_cache
= expiring_cache_new (GROUPS_CACHE_EXPIRE_TIME
, groups_cache_get_value
, g_free
);
276 return g_strdup (expiring_cache_get_value (groups_cache
, gid
));