[liboobs] Add convenience users/groups functions from the gnome-system-tools



commit b960c650728adfc8b6e9c9a47c7435f328726bd1
Author: Milan Bouchet-Valat <nalimilan club fr>
Date:   Sat Dec 5 13:19:32 2009 +0100

    Add convenience users/groups functions from the gnome-system-tools
    
    Move standard functions from users-admin that make sense to have in a library:
    - in Oobs(Users|Groups)Config: _get_from_(login|name)(), _get_from_[ug]id(), _is_(login|name)_used(), _is_[ug]id_used(), _find_free_[ug]id()
    - in Oobs(User|Group): _is_root(), oobs_user_is_in_group()
    
    Getters are simple accessor methods walking over the internal lists. _is_root() merely checks that name is "root". _find_free_[ug]id walks over the list to find an ID to use. All functions are slightly improved versions of what we had in users-admin.
    
    Remove now rendundant internal functions: get_group_with_gid() in oobs-usersconfig.c, and find_user() in oobs-groupsconfig.c. Make the code use the new public functions.

 oobs/oobs-group.c        |   24 +++++
 oobs/oobs-group.h        |    2 +
 oobs/oobs-groupsconfig.c |  232 ++++++++++++++++++++++++++++++++++++++-----
 oobs/oobs-groupsconfig.h |   23 ++++-
 oobs/oobs-user.c         |   55 ++++++++++
 oobs/oobs-user.h         |    4 +-
 oobs/oobs-usersconfig.c  |  248 ++++++++++++++++++++++++++++++++++++++++------
 oobs/oobs-usersconfig.h  |   14 +++
 8 files changed, 540 insertions(+), 62 deletions(-)
---
diff --git a/oobs/oobs-group.c b/oobs/oobs-group.c
index cc93b37..ceef8ce 100644
--- a/oobs/oobs-group.c
+++ b/oobs/oobs-group.c
@@ -28,6 +28,7 @@
 #include "oobs-defines.h"
 #include "utils.h"
 #include <crypt.h>
+#include <string.h>
 
 /**
  * SECTION:oobs-group
@@ -429,3 +430,26 @@ oobs_group_remove_user (OobsGroup *group,
   /* there might be several instances */
   priv->users = g_list_remove_all (priv->users, user);
 }
+
+/**
+ * oobs_group_is_root:
+ * @group: An #OobsGroup.
+ *
+ * Checks whether a group is the root group, according to its name.
+ *
+ * Return value: %TRUE if @group is the root group, %FALSE otherwise.
+ **/
+gboolean
+oobs_group_is_root (OobsGroup *group)
+{
+  const gchar *name;
+
+  g_return_val_if_fail (OOBS_IS_GROUP (group), FALSE);
+
+  name = oobs_group_get_name (group);
+
+  if (!name)
+    return FALSE;
+
+  return (strcmp (name, "root") == 0);
+}
diff --git a/oobs/oobs-group.h b/oobs/oobs-group.h
index 08fd1bc..46a8d90 100644
--- a/oobs/oobs-group.h
+++ b/oobs/oobs-group.h
@@ -68,6 +68,8 @@ void       oobs_group_clear_users  (OobsGroup *group);
 void       oobs_group_add_user     (OobsGroup *group, OobsUser *user);
 void       oobs_group_remove_user  (OobsGroup *group, OobsUser *user);
 
+gboolean   oobs_group_is_root      (OobsGroup *group);
+
 
 G_END_DECLS
 
diff --git a/oobs/oobs-groupsconfig.c b/oobs/oobs-groupsconfig.c
index 8debeca..032b36d 100644
--- a/oobs/oobs-groupsconfig.c
+++ b/oobs/oobs-groupsconfig.c
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- * Authors: Carlos Garnacho Parro  <carlosg gnome org>
+ * Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+ *          Milan Bouchet-Valat <nalimilan club fr>.
  */
 
 #include <dbus/dbus.h>
@@ -304,43 +305,19 @@ create_dbus_struct_from_group (GObject         *group,
   g_free (passwd);
 }
 
-static OobsUser*
-find_user (OobsList *users_list, gchar *username)
-{
-  OobsListIter iter;
-  OobsUser *user;
-  gboolean valid;
-
-  valid = oobs_list_get_iter_first (users_list, &iter);
-
-  while (valid)
-    {
-      user = OOBS_USER (oobs_list_get (users_list, &iter));
-
-      if (strcmp (username, oobs_user_get_login_name (user)) == 0)
-	return user;
-
-      valid = oobs_list_iter_next (users_list, &iter);
-      g_object_unref (user);
-    }
-
-  return NULL;
-}
-
 static void
 query_users_foreach (OobsGroup *group,
 		     GList     *users,
 		     gpointer   data)
 {
   OobsUsersConfig *users_config = OOBS_USERS_CONFIG (data);
-  OobsList *users_list = oobs_users_config_get_users (users_config);
   OobsUser *user;
 
   oobs_group_clear_users (group);
 
   while (users)
     {
-      user = find_user (users_list, users->data);
+      user = oobs_users_config_get_from_login (users_config, users->data);
 
       if (user)
 	{
@@ -483,3 +460,206 @@ oobs_groups_config_get_groups (OobsGroupsConfig *config)
 
   return priv->groups_list;
 }
+
+
+/**
+ * oobs_groups_config_get_from_name:
+ * @config: An #OobsGroupsConfig.
+ * @name: the name of the wanted group.
+ *
+ * Gets the (first) group called @name. This is a convenience function
+ * to avoid walking manually over the groups list.
+ *
+ * Return value: an #OobsGroup corresponding to the passed named,
+ * or %NULL if no such group exists. Don't forget to unref group when you're done.
+ **/
+OobsGroup *
+oobs_groups_config_get_from_name (OobsGroupsConfig *config, const gchar *name)
+{
+  OobsList *groups_list;
+  OobsListIter iter;
+  OobsGroup *group;
+  gboolean valid;
+  const gchar *group_name;
+
+  groups_list = oobs_groups_config_get_groups (config);
+  valid = oobs_list_get_iter_first (groups_list, &iter);
+
+  while (valid) {
+    group = OOBS_GROUP (oobs_list_get (groups_list, &iter));
+    group_name = oobs_group_get_name (group);
+
+    if (group_name && strcmp (name, group_name) == 0)
+      return group;
+
+    /* only the returned group is not unreferenced here */
+    g_object_unref (group);
+
+    valid = oobs_list_iter_next (groups_list, &iter);
+  }
+
+  return NULL;
+}
+
+/**
+ * oobs_groups_config_get_from_uid:
+ * @config: An #OobsGroupsConfig.
+ * @gid: the UID of the wanted group.
+ *
+ * Gets the (first) group whose GID is @gid. This is a convenience function
+ * to avoid walking manually over the groups list.
+ *
+ * Return value: an #OobsGroup corresponding to the passed GID,
+ * or %NULL if no such group exists. Don't forget to group user when you're done.
+ **/
+OobsGroup *
+oobs_groups_config_get_from_gid (OobsGroupsConfig *config, gid_t gid)
+{
+  OobsGroupsConfigPrivate *priv;
+  OobsGroup *group;
+  OobsListIter iter;
+  gboolean valid;
+  gid_t group_gid;
+
+  g_return_val_if_fail (config != NULL, NULL);
+  g_return_val_if_fail (OOBS_IS_GROUPS_CONFIG (config), NULL);
+
+  priv = config->_priv;
+
+  valid = oobs_list_get_iter_first (priv->groups_list, &iter);
+
+  while (valid) {
+    group = OOBS_GROUP (oobs_list_get (priv->groups_list, &iter));
+    group_gid = oobs_group_get_gid (group);
+
+    if (group_gid == gid)
+      return group;
+
+    /* only the returned group is not unreferenced here */
+    g_object_unref (group);
+
+    valid = oobs_list_iter_next (priv->groups_list, &iter);
+  }
+
+  return NULL;
+}
+
+/**
+ * oobs_groups_config_is_name_used:
+ * @config: An #OobsGroupsConfig.
+ * @name: the name to check.
+ *
+ * Check whether @name is already used by an existing group or not. This is
+ * a convenience function to avoid walking manually over the groups list.
+ *
+ * Return value: %TRUE if a group called @name already exists, %FALSE otherwise.
+ **/
+gboolean
+oobs_groups_config_is_name_used (OobsGroupsConfig *config, const gchar *name)
+{
+  OobsGroup *group;
+  gboolean name_used;
+
+  group = oobs_groups_config_get_from_name (config, name);
+  name_used = (group != NULL);
+
+  if (group)
+    g_object_unref (group);
+
+  return name_used;
+}
+
+/**
+ * oobs_groups_config_is_gid_used:
+ * @config: An #OobsGroupsConfig.
+ * @gid: the gid to check.
+ *
+ * Check whether @gid is already used by an existing group or not. This is
+ * a convenience function to avoid walking manually over the groups list.
+ *
+ * Return value: %TRUE if an group with such an gid already exists, %FALSE otherwise.
+ **/
+gboolean
+oobs_groups_config_is_gid_used (OobsGroupsConfig *config, gid_t gid)
+{
+  OobsGroup *group;
+  gboolean gid_used;
+
+  group = oobs_groups_config_get_from_gid (config, gid);
+  gid_used = (group != NULL);
+
+  if (group)
+    g_object_unref (group);
+
+  return gid_used;
+}
+
+
+/**
+ * oobs_groups_config_find_free_uid:
+ * @config: An #OobsGroupsConfig.
+ * @gid_min: the minimum wanted GID.
+ * @gid_max: the maximum wanted GID.
+ *
+ * Finds a GID that is not used by any user in the list. The returned GID is
+ * the highest used GID in the range plus one if @gid_max is not used.
+ * Else, the first free GID in the range is returned.
+ *
+ * If both @gid_min and @gid_max are equal to 0, the default range is used.
+ *
+ * Return value: a free GID in the requested range,
+ * or @gid_max to indicate wrong use or failure to find a free GID.
+ **/
+gid_t
+oobs_groups_config_find_free_gid (OobsGroupsConfig *config, gid_t gid_min, gid_t gid_max)
+{
+  OobsGroupsConfigPrivate *priv;
+  OobsList *list;
+  OobsListIter list_iter;
+  GObject *group;
+  gboolean valid;
+  gid_t new_gid, gid;
+
+  g_return_val_if_fail (config != NULL, gid_max);
+  g_return_val_if_fail (OOBS_IS_GROUPS_CONFIG (config), gid_max);
+  g_return_val_if_fail (gid_min <= gid_max, gid_max);
+
+  priv = config->_priv;
+
+  if (gid_min == 0 && gid_max == 0) {
+    gid_min = priv->minimum_gid;
+    gid_max = priv->maximum_gid;
+  }
+
+  new_gid = gid_min - 1;
+
+  list = oobs_groups_config_get_groups (config);
+  valid = oobs_list_get_iter_first (list, &list_iter);
+
+  /* Find the highest used GID in the range */
+  while (valid) {
+    group = oobs_list_get (list, &list_iter);
+    gid = oobs_group_get_gid (OOBS_GROUP (group));
+    g_object_unref (group);
+
+    if (gid < gid_max && gid >= gid_min && new_gid < gid)
+      new_gid = gid;
+
+    valid = oobs_list_iter_next (list, &list_iter);
+  }
+
+  new_gid++;
+
+  if (!oobs_groups_config_is_gid_used (config, new_gid))
+    return new_gid;
+
+
+  /* If the fast method failed, iterate over the whole range */
+  new_gid = gid_min;
+  while (oobs_groups_config_is_gid_used (config, new_gid) && new_gid < gid_max)
+    new_gid++;
+
+  /* In the extreme case where no GID is free in the range,
+   * we return the gid_max, which is the best we can do */
+  return new_gid;
+}
diff --git a/oobs/oobs-groupsconfig.h b/oobs/oobs-groupsconfig.h
index 940a39f..163bbb2 100644
--- a/oobs/oobs-groupsconfig.h
+++ b/oobs/oobs-groupsconfig.h
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- * Authors: Carlos Garnacho Parro  <carlosg gnome org>
+ * Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+ *          Milan Bouchet-Valat <nalimilan club fr>.
  */
 
 #ifndef __OOBS_GROUPS_CONFIG_H
@@ -25,6 +26,7 @@ G_BEGIN_DECLS
 
 #include "oobs-object.h"
 #include "oobs-list.h"
+#include "oobs-group.h"
 
 #define OOBS_TYPE_GROUPS_CONFIG         (oobs_groups_config_get_type ())
 #define OOBS_GROUPS_CONFIG(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), OOBS_TYPE_GROUPS_CONFIG, OobsGroupsConfig))
@@ -54,11 +56,24 @@ struct _OobsGroupsConfigClass
   void (*_oobs_padding4) (void);
 };
 
-GType       oobs_groups_config_get_type     (void);
+GType       oobs_groups_config_get_type      (void);
 
-OobsObject* oobs_groups_config_get          (void);
-OobsList*   oobs_groups_config_get_groups   (OobsGroupsConfig *config);
+OobsObject* oobs_groups_config_get           (void);
+OobsList*   oobs_groups_config_get_groups    (OobsGroupsConfig *config);
 
+OobsGroup*  oobs_groups_config_get_from_name (OobsGroupsConfig *config,
+                                              const gchar      *name);
+OobsGroup*  oobs_groups_config_get_from_gid  (OobsGroupsConfig *config,
+                                              gid_t             gid);
+
+gboolean    oobs_groups_config_is_name_used  (OobsGroupsConfig *config,
+                                              const gchar      *name);
+gboolean    oobs_groups_config_is_gid_used   (OobsGroupsConfig *config,
+                                              gid_t             gid);
+
+gid_t       oobs_groups_config_find_free_gid (OobsGroupsConfig *config,
+                                              gid_t             gid_min,
+                                              gid_t             gid_max);
 
 G_END_DECLS
 
diff --git a/oobs/oobs-user.c b/oobs/oobs-user.c
index 09cc670..d3e4b61 100644
--- a/oobs/oobs-user.c
+++ b/oobs/oobs-user.c
@@ -830,3 +830,58 @@ oobs_user_get_active (OobsUser *user)
 
   return match;
 }
+
+/**
+ * oobs_user_is_root:
+ * @user: An #OobsUser.
+ *
+ * Checks whether a group is the superuser, according to its name.
+ *
+ * Return value: %TRUE if @user is the root user, %FALSE otherwise.
+ **/
+gboolean
+oobs_user_is_root (OobsUser *user)
+{
+  const gchar *login;
+
+  g_return_val_if_fail (OOBS_IS_USER (user), FALSE);
+
+  login = oobs_user_get_login_name (user);
+
+  if (!login)
+    return FALSE;
+
+  return (strcmp (login, "root") == 0);
+}
+
+/**
+ * oobs_user_is_in_group:
+ * @user: An #OobsUser.
+ * @group: An #OobsGroup.
+ *
+ * Checks whether a user member of @group.
+ *
+ * Return value: %TRUE if @user is in @group, %FALSE otherwise.
+ **/
+gboolean
+oobs_user_is_in_group (OobsUser *user, OobsGroup *group)
+{
+  OobsUser *tmp_user;
+  GList *users = NULL;
+  GList *l;
+
+  g_return_val_if_fail (OOBS_IS_USER (user), FALSE);
+  g_return_val_if_fail (OOBS_IS_GROUP (group), FALSE);
+
+  users = oobs_group_get_users (group);
+
+  for (l = users; l; l = l->next) {
+    tmp_user = l->data;
+    if (tmp_user == user)
+      break;
+  }
+
+  g_list_free (users);
+
+  return l != NULL;
+}
diff --git a/oobs/oobs-user.h b/oobs/oobs-user.h
index ae29f18..f399f7c 100644
--- a/oobs/oobs-user.h
+++ b/oobs/oobs-user.h
@@ -88,7 +88,9 @@ void oobs_user_set_home_phone_number (OobsUser *user, const gchar *phone_number)
 G_CONST_RETURN gchar* oobs_user_get_other_data (OobsUser *user);
 void oobs_user_set_other_data (OobsUser *user, const gchar *data);
 
-gboolean oobs_user_get_active (OobsUser *user);
+gboolean oobs_user_get_active  (OobsUser *user);
+gboolean oobs_user_is_root     (OobsUser *user);
+gboolean oobs_user_is_in_group (OobsUser *user, OobsGroup *group);
 
 G_END_DECLS
 
diff --git a/oobs/oobs-usersconfig.c b/oobs/oobs-usersconfig.c
index 09815db..5c80f36 100644
--- a/oobs/oobs-usersconfig.c
+++ b/oobs/oobs-usersconfig.c
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- * Authors: Carlos Garnacho Parro  <carlosg gnome org>
+ * Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+ *          Milan Bouchet-Valat <nalimilan club fr>.
  */
 
 #include <dbus/dbus.h>
@@ -408,41 +409,15 @@ create_dbus_struct_from_user (OobsUser        *user,
   return TRUE;
 }
 
-static OobsGroup*
-get_group_with_gid (OobsGroupsConfig *config,
-		    gint              gid)
-{
-  OobsList *groups_list;
-  OobsListIter iter;
-  OobsGroup *group;
-  gboolean valid;
-
-  groups_list = oobs_groups_config_get_groups (config);
-  valid = oobs_list_get_iter_first (groups_list, &iter);
-
-  while (valid)
-    {
-      group = OOBS_GROUP (oobs_list_get (groups_list, &iter));
-
-      if (oobs_group_get_gid (group) == gid)
-	return group;
-
-      g_object_unref (group);
-      valid = oobs_list_iter_next (groups_list, &iter);
-    }
-
-  return NULL;
-}
-
 static void
 query_groups_foreach (OobsUser *user,
-		      gint      gid,
+		      uid_t     gid,
 		      gpointer  data)
 {
   OobsGroupsConfig *groups_config = OOBS_GROUPS_CONFIG (data);
   OobsGroup *group;
 
-  group = get_group_with_gid (groups_config, gid);
+  group = oobs_groups_config_get_from_gid (groups_config, gid);
   oobs_user_set_main_group (user, group);
 
   if (group)
@@ -462,7 +437,7 @@ oobs_users_config_groups_updated (OobsUsersConfig  *users,
   /* get the default group */
   if (priv->default_gid > 0)
     {
-      group = get_group_with_gid (groups, priv->default_gid);
+      group = oobs_groups_config_get_from_gid (groups, priv->default_gid);
       priv->default_group = group;
 
       if (group)
@@ -760,7 +735,7 @@ oobs_users_config_get_default_home_dir (OobsUsersConfig *config)
 
 /**
  * oobs_users_config_set_default_home_dir:
- * @config: An #OobsIfacesConfig.
+ * @config: An #OobsUsersConfig.
  * @home_dir: new default home directory prefix.
  * 
  * Sets a new home directory prefix used for newly created users, replacing the old one.
@@ -817,3 +792,214 @@ oobs_users_config_get_available_shells (OobsUsersConfig *config)
 
   return priv->shells;
 }
+
+
+/*
+ * Convenience functions to make working with the users list easier.
+ */
+
+/**
+ * oobs_users_config_get_from_login:
+ * @config: An #OobsUsersConfig.
+ * @login: the login name of the wanted user.
+ *
+ * Gets the (first) user whose login is @login. This is a convenience function
+ * to avoid walking manually over the users list.
+ *
+ * Return value: an #OobsUser corresponding to the passed login,
+ * or %NULL if no such user exists. Don't forget to unref user when you're done.
+ **/
+OobsUser *
+oobs_users_config_get_from_login (OobsUsersConfig *config, const gchar *login)
+{
+  OobsUsersConfigPrivate *priv;
+  OobsUser *user;
+  OobsListIter iter;
+  gboolean valid;
+  const gchar *user_login;
+
+  g_return_val_if_fail (config != NULL, NULL);
+  g_return_val_if_fail (OOBS_IS_USERS_CONFIG (config), NULL);
+  g_return_val_if_fail (login != NULL, NULL);
+
+  priv = config->_priv;
+
+  valid = oobs_list_get_iter_first (priv->users_list, &iter);
+
+  while (valid) {
+    user = OOBS_USER (oobs_list_get (priv->users_list, &iter));
+    user_login = oobs_user_get_login_name (user);
+
+    if (user_login && strcmp (login, user_login) == 0)
+      return user;
+
+    /* only the returned user is not unreferenced here */
+    g_object_unref (user);
+
+    valid = oobs_list_iter_next (priv->users_list, &iter);
+  }
+
+  return NULL;
+}
+
+/**
+ * oobs_users_config_get_from_uid:
+ * @config: An #OobsUsersConfig.
+ * @uid: the UID of the wanted user.
+ *
+ * Gets the (first) user whose UID is @uid. This is a convenience function
+ * to avoid walking manually over the users list.
+ *
+ * Return value: an #OobsUser corresponding to the passed UID,
+ * or %NULL if no such user exists. Don't forget to unref user when you're done.
+ **/
+OobsUser *
+oobs_users_config_get_from_uid (OobsUsersConfig *config, uid_t uid)
+{
+  OobsUsersConfigPrivate *priv;
+  OobsUser *user;
+  OobsListIter iter;
+  gboolean valid;
+  uid_t user_uid;
+
+  g_return_val_if_fail (config != NULL, NULL);
+  g_return_val_if_fail (OOBS_IS_USERS_CONFIG (config), NULL);
+
+  priv = config->_priv;
+
+  valid = oobs_list_get_iter_first (priv->users_list, &iter);
+
+  while (valid) {
+    user = OOBS_USER (oobs_list_get (priv->users_list, &iter));
+    user_uid = oobs_user_get_uid (user);
+
+    if (user_uid == uid)
+      return user;
+
+    /* only the returned user is not unreferenced here */
+    g_object_unref (user);
+
+    valid = oobs_list_iter_next (priv->users_list, &iter);
+  }
+
+  return NULL;
+}
+
+/**
+ * oobs_users_config_is_login_used:
+ * @config: An #OobsUsersConfig.
+ * @login: the login name to check.
+ *
+ * Check whether @login is already used by an existing user or not. This is
+ * a convenience function to avoid walking manually over the users list.
+ *
+ * Return value: %TRUE if an user named @login already exists, %FALSE otherwise.
+ **/
+gboolean
+oobs_users_config_is_login_used (OobsUsersConfig *config, const gchar *login)
+{
+  OobsUser *user;
+  gboolean login_used;
+
+  user = oobs_users_config_get_from_login (config, login);
+  login_used = (user != NULL);
+
+  if (user)
+    g_object_unref (user);
+
+  return login_used;
+}
+
+/**
+ * oobs_users_config_is_uid_used:
+ * @config: An #OobsUsersConfig.
+ * @uid: the UID to check.
+ *
+ * Check whether @uid is already used by an existing user or not. This is
+ * a convenience function to avoid walking manually over the users list.
+ *
+ * Return value: %TRUE if an user with such an UID already exists, %FALSE otherwise.
+ **/
+gboolean
+oobs_users_config_is_uid_used (OobsUsersConfig *config, uid_t uid)
+{
+  OobsUser *user;
+  gboolean uid_used;
+
+  user = oobs_users_config_get_from_uid (config, uid);
+  uid_used = (user != NULL);
+
+  if (user)
+    g_object_unref (user);
+
+  return uid_used;
+}
+
+/**
+ * oobs_users_config_find_free_uid:
+ * @config: An #OobsUsersConfig.
+ * @uid_min: the minimum wanted UID.
+ * @uid_max: the maximum wanted UID.
+ *
+ * Finds an UID that is not used by any user in the list. The returned UID is
+ * the highest used UID in the range plus one if @uid_max is not used.
+ * Else, the first free UID in the range is returned.
+ *
+ * If both @uid_min and @uid_max are equal to 0, the default range is used.
+ *
+ * Return value: a free UID in the requested range,
+ * or @uid_max to indicate wrong use or failure to find a free UID.
+ **/
+uid_t
+oobs_users_config_find_free_uid (OobsUsersConfig *config, uid_t uid_min, uid_t uid_max)
+{
+  OobsUsersConfigPrivate *priv;
+  OobsList *list;
+  OobsListIter list_iter;
+  OobsUser *user;
+  gboolean valid;
+  uid_t new_uid, user_uid;
+
+  g_return_val_if_fail (config != NULL, uid_max);
+  g_return_val_if_fail (OOBS_IS_USERS_CONFIG (config), uid_max);
+  g_return_val_if_fail (uid_min <= uid_max, uid_max);
+
+  priv = config->_priv;
+
+  if (uid_min == 0 && uid_max == 0) {
+    uid_min = priv->minimum_uid;
+    uid_max = priv->maximum_uid;
+  }
+
+  new_uid = uid_min - 1;
+
+  list = oobs_users_config_get_users (config);
+  valid = oobs_list_get_iter_first (list, &list_iter);
+
+  /* Find the highest used UID in the range */
+  while (valid) {
+    user = OOBS_USER (oobs_list_get (list, &list_iter));
+    user_uid = oobs_user_get_uid (user);
+    g_object_unref (user);
+
+    if (user_uid < uid_max && user_uid >= uid_min && user_uid > new_uid)
+      new_uid = user_uid;
+
+    valid = oobs_list_iter_next (list, &list_iter);
+  }
+
+  new_uid++;
+
+  if (!oobs_users_config_is_uid_used (config, new_uid))
+    return new_uid;
+
+
+  /* If the fast method failed, iterate over the whole range */
+  new_uid = uid_min;
+  while (oobs_users_config_is_uid_used (config, new_uid) && new_uid < uid_max)
+    new_uid++;
+
+  /* In the extreme case where no UID is free in the range,
+   * we return the uid_max, which is the best we can do */
+  return new_uid;
+}
diff --git a/oobs/oobs-usersconfig.h b/oobs/oobs-usersconfig.h
index 39e4605..53dfdd4 100644
--- a/oobs/oobs-usersconfig.h
+++ b/oobs/oobs-usersconfig.h
@@ -77,6 +77,20 @@ void                  oobs_users_config_set_default_home_dir (OobsUsersConfig *c
 OobsGroup*  oobs_users_config_get_default_group    (OobsUsersConfig *config);
 GList*      oobs_users_config_get_available_shells (OobsUsersConfig *config);
 
+OobsUser*   oobs_users_config_get_from_login       (OobsUsersConfig *config,
+                                                    const gchar     *login);
+OobsUser*   oobs_users_config_get_from_uid         (OobsUsersConfig *config,
+                                                    uid_t            uid);
+
+gboolean    oobs_users_config_is_login_used        (OobsUsersConfig *config,
+                                                    const gchar     *login);
+gboolean    oobs_users_config_is_uid_used          (OobsUsersConfig *config,
+                                                    uid_t            uid);
+
+uid_t       oobs_users_config_find_free_uid        (OobsUsersConfig *config,
+                                                    uid_t            uid_min,
+                                                    uid_t            uid_max);
+
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]