0c69794138
These lines are generally out-of-date, incomplete and unnecessary. With SPDX and git repository much more accurate and fine grained information about licensing and authorship is available, hence let's drop the per-file copyright notice. Of course, removing copyright lines of others is problematic, hence this commit only removes my own lines and leaves all others untouched. It might be nicer if sooner or later those could go away too, making git the only and accurate source of authorship information.
192 lines
4.5 KiB
C
192 lines
4.5 KiB
C
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "alloc-util.h"
|
|
#include "macro.h"
|
|
#include "uid-range.h"
|
|
#include "user-util.h"
|
|
|
|
static bool uid_range_intersect(UidRange *range, uid_t start, uid_t nr) {
|
|
assert(range);
|
|
|
|
return range->start <= start + nr &&
|
|
range->start + range->nr >= start;
|
|
}
|
|
|
|
static void uid_range_coalesce(UidRange **p, unsigned *n) {
|
|
unsigned i, j;
|
|
|
|
assert(p);
|
|
assert(n);
|
|
|
|
for (i = 0; i < *n; i++) {
|
|
for (j = i + 1; j < *n; j++) {
|
|
UidRange *x = (*p)+i, *y = (*p)+j;
|
|
|
|
if (uid_range_intersect(x, y->start, y->nr)) {
|
|
uid_t begin, end;
|
|
|
|
begin = MIN(x->start, y->start);
|
|
end = MAX(x->start + x->nr, y->start + y->nr);
|
|
|
|
x->start = begin;
|
|
x->nr = end - begin;
|
|
|
|
if (*n > j+1)
|
|
memmove(y, y+1, sizeof(UidRange) * (*n - j -1));
|
|
|
|
(*n)--;
|
|
j--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int uid_range_compare(const void *a, const void *b) {
|
|
const UidRange *x = a, *y = b;
|
|
|
|
if (x->start < y->start)
|
|
return -1;
|
|
if (x->start > y->start)
|
|
return 1;
|
|
|
|
if (x->nr < y->nr)
|
|
return -1;
|
|
if (x->nr > y->nr)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr) {
|
|
bool found = false;
|
|
UidRange *x;
|
|
unsigned i;
|
|
|
|
assert(p);
|
|
assert(n);
|
|
|
|
if (nr <= 0)
|
|
return 0;
|
|
|
|
for (i = 0; i < *n; i++) {
|
|
x = (*p) + i;
|
|
if (uid_range_intersect(x, start, nr)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
uid_t begin, end;
|
|
|
|
begin = MIN(x->start, start);
|
|
end = MAX(x->start + x->nr, start + nr);
|
|
|
|
x->start = begin;
|
|
x->nr = end - begin;
|
|
} else {
|
|
UidRange *t;
|
|
|
|
t = reallocarray(*p, *n + 1, sizeof(UidRange));
|
|
if (!t)
|
|
return -ENOMEM;
|
|
|
|
*p = t;
|
|
x = t + ((*n) ++);
|
|
|
|
x->start = start;
|
|
x->nr = nr;
|
|
}
|
|
|
|
qsort(*p, *n, sizeof(UidRange), uid_range_compare);
|
|
uid_range_coalesce(p, n);
|
|
|
|
return *n;
|
|
}
|
|
|
|
int uid_range_add_str(UidRange **p, unsigned *n, const char *s) {
|
|
uid_t start, nr;
|
|
const char *t;
|
|
int r;
|
|
|
|
assert(p);
|
|
assert(n);
|
|
assert(s);
|
|
|
|
t = strchr(s, '-');
|
|
if (t) {
|
|
char *b;
|
|
uid_t end;
|
|
|
|
b = strndupa(s, t - s);
|
|
r = parse_uid(b, &start);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
r = parse_uid(t+1, &end);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
if (end < start)
|
|
return -EINVAL;
|
|
|
|
nr = end - start + 1;
|
|
} else {
|
|
r = parse_uid(s, &start);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
nr = 1;
|
|
}
|
|
|
|
return uid_range_add(p, n, start, nr);
|
|
}
|
|
|
|
int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid) {
|
|
uid_t closest = UID_INVALID, candidate;
|
|
unsigned i;
|
|
|
|
assert(p);
|
|
assert(uid);
|
|
|
|
candidate = *uid - 1;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
uid_t begin, end;
|
|
|
|
begin = p[i].start;
|
|
end = p[i].start + p[i].nr - 1;
|
|
|
|
if (candidate >= begin && candidate <= end) {
|
|
*uid = candidate;
|
|
return 1;
|
|
}
|
|
|
|
if (end < candidate)
|
|
closest = end;
|
|
}
|
|
|
|
if (closest == UID_INVALID)
|
|
return -EBUSY;
|
|
|
|
*uid = closest;
|
|
return 1;
|
|
}
|
|
|
|
bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid) {
|
|
unsigned i;
|
|
|
|
assert(p);
|
|
assert(uid);
|
|
|
|
for (i = 0; i < n; i++)
|
|
if (uid >= p[i].start && uid < p[i].start + p[i].nr)
|
|
return true;
|
|
|
|
return false;
|
|
}
|