/* * find_free_range: find an unused consecutive sequence of ids to allocate * to a user. * @db: database to search * @min: the first uid in the range to find * @max: the highest uid to find * @count: the number of uids needed * * Return the lowest new uid, or ULONG_MAX on failure. */ static unsigned long find_free_range(struct commonio_db *db, unsigned long min, unsigned long max, unsigned long count) { const struct subordinate_range *range; unsigned long low, high; /* When given invalid parameters fail */ if ((count == 0) || (max < min)) goto fail; /* Sort by range then by owner */ commonio_sort (db, subordinate_range_cmp); commonio_rewind(db); low = min; while ((range = commonio_next(db)) != NULL) { unsigned long first = range->start; unsigned long last = first + range->count - 1; /* Find the top end of the hole before this range */ high = first; /* Don't allocate IDs after max (included) */ if (high > max + 1) { high = max + 1; } /* Is the hole before this range large enough? */ if ((high > low) && ((high - low) >= count)) return low; /* Compute the low end of the next hole */ if (low < (last + 1)) low = last + 1; if (low > max) goto fail; } /* Is the remaining unclaimed area large enough? */ if (((max - low) + 1) >= count) return low; fail: return ULONG_MAX; }
/* Sort entries by GID */ int gr_sort () { return commonio_sort (&group_db, gr_cmp); }
/* Sort entries by UID */ int pw_sort () { return commonio_sort (&passwd_db, pw_cmp); }