Various useful helpers (#41684)

Split out of #41543.

These don't make too much sense on their own, but they also don't really
hurt. They are preparation for #41543, but in order to make things
either to review I split these four commits out, since they are not
directly part of what the PR shall achieve
This commit is contained in:
Lennart Poettering
2026-04-18 09:50:19 +02:00
committed by GitHub
7 changed files with 71 additions and 5 deletions
+5
View File
@@ -83,6 +83,11 @@ static inline int safe_atou64(const char *s, uint64_t *ret_u) {
return safe_atollu(s, (unsigned long long*) ret_u);
}
static inline int safe_atou64_full(const char *s, unsigned base, uint64_t *ret_u) {
assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
return safe_atollu_full(s, base, (unsigned long long*) ret_u);
}
static inline int safe_atoi64(const char *s, int64_t *ret_i) {
assert_cc(sizeof(int64_t) == sizeof(long long));
return safe_atolli(s, (long long*) ret_i);
+17
View File
@@ -898,3 +898,20 @@ mode_t inode_type_from_string(const char *s) {
return MODE_INVALID;
}
int vfs_free_bytes(int fd, uint64_t *ret) {
assert(fd >= 0);
assert(ret);
/* Safely returns the current available disk space (for root, i.e. including any space reserved for
* root) of the disk referenced by the fd, converted to bytes. */
struct statvfs sv;
if (fstatvfs(fd, &sv) < 0)
return -errno;
if (!MUL_SAFE(ret, (uint64_t) sv.f_frsize, (uint64_t) sv.f_bfree))
return -ERANGE;
return 0;
}
+2
View File
@@ -161,3 +161,5 @@ static inline bool inode_type_can_hardlink(mode_t m) {
* type). */
return IN_SET(m & S_IFMT, S_IFSOCK, S_IFLNK, S_IFREG, S_IFBLK, S_IFCHR, S_IFIFO);
}
int vfs_free_bytes(int fd, uint64_t *ret);
+17 -2
View File
@@ -1519,17 +1519,32 @@ char* strrstr_internal(const char *haystack, const char *needle) {
/* Special case: for the empty string we return the very last possible occurrence, i.e. *after* the
* last char, not before. */
if (*needle == 0)
if (needle[0] == 0)
return (char*) strchr(haystack, 0);
/* Special case: for single character strings, just use optimized strrchr() */
if (needle[1] == 0)
return (char*) strrchr(haystack, needle[0]);
for (const char *p = strstr(haystack, needle), *q; p; p = q) {
q = strstr(p + 1, needle);
if (!q)
return (char *) p;
return (char*) p;
}
return NULL;
}
char* strrstr_no_case_internal(const char *haystack, const char *needle) {
if (!haystack || !needle)
return NULL;
for (const char *p = strchr(haystack, 0); p > haystack; p--)
if (startswith_no_case(p, needle))
return (char*) p;
return startswith_no_case(haystack, needle) ? (char*) haystack : NULL;
}
size_t str_common_prefix(const char *a, const char *b) {
assert(a);
assert(b);
+4
View File
@@ -312,4 +312,8 @@ char* strrstr_internal(const char *haystack, const char *needle) _pure_;
#define strrstr(haystack, needle) \
const_generic(haystack, strrstr_internal(haystack, needle))
char* strrstr_no_case_internal(const char *haystack, const char *needle) _pure_;
#define strrstr_no_case(haystack, needle) \
const_generic(haystack, strrstr_no_case_internal(haystack, needle))
size_t str_common_prefix(const char *a, const char *b) _pure_;