Coverage Report

Created: 2026-02-26 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/freeradius-devel/util/misc.h
Line
Count
Source
1
#pragma once
2
/*
3
 *   This library is free software; you can redistribute it and/or
4
 *   modify it under the terms of the GNU Lesser General Public
5
 *   License as published by the Free Software Foundation; either
6
 *   version 2.1 of the License, or (at your option) any later version.
7
 *
8
 *   This library is distributed in the hope that it will be useful,
9
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
 *   Lesser General Public License for more details.
12
 *
13
 *   You should have received a copy of the GNU Lesser General Public
14
 *   License along with this library; if not, write to the Free Software
15
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
 */
17
18
/** Various miscellaneous utility functions
19
 *
20
 * @file src/lib/util/misc.h
21
 *
22
 * @copyright 2000,2006 The FreeRADIUS server project
23
 */
24
RCSIDH(misc_h, "$Id: 70ba928bd872c6c72042eb9c596495c615076504 $")
25
26
#ifdef __cplusplus
27
extern "C" {
28
#endif
29
30
#include <freeradius-devel/build.h>
31
#include <freeradius-devel/missing.h>
32
#include <freeradius-devel/util/print.h>
33
#include <freeradius-devel/util/talloc.h>
34
#include <freeradius-devel/util/time.h>
35
36
#include <signal.h>
37
38
typedef   int8_t (*fr_cmp_t)(void const *a, void const *b);
39
typedef   void (*fr_free_t)(void *);
40
41
/*
42
 *  Define TALLOC_DEBUG to check overflows with talloc.
43
 *  we can't use valgrind, because the memory used by
44
 *  talloc is valid memory... just not for us.
45
 */
46
#ifdef TALLOC_DEBUG
47
void    fr_talloc_verify_cb(const void *ptr, int depth,
48
            int max_depth, int is_ref,
49
            void *private_data);
50
#  define VERIFY_ALL_TALLOC talloc_report_depth_cb(NULL, 0, -1, fr_talloc_verify_cb, NULL)
51
#else
52
#  define VERIFY_ALL_TALLOC
53
#endif
54
55
/** Zero out any whitespace with nul bytes
56
 *
57
 * @param[in,out] _p  string to process
58
 */
59
#define fr_zero_whitespace(_p)  while (isspace((uint8_t) *_p)) *(_p++) = '\0'
60
61
/** Check whether the string is all whitespace
62
 *
63
 * @return
64
 *  - true if the entirety of the string is whitespace.
65
 *  - false if the string contains non whitespace.
66
 */
67
static inline bool is_whitespace(char const *value)
68
0
{
69
0
#ifdef STATIC_ANALYZER
70
0
  if (*value == '\0') return false; /* clang analyzer doesn't seem to know what isspace does */
71
0
#endif
72
0
  do {
73
0
    if (!isspace((uint8_t) *value)) return false;
74
0
  } while (*++value);
75
0
76
0
  return true;
77
0
}
Unexecuted instantiation: fuzzer_dhcpv6.c:is_whitespace
Unexecuted instantiation: fuzzer_util.c:is_whitespace
Unexecuted instantiation: fuzzer_dhcpv4.c:is_whitespace
Unexecuted instantiation: fuzzer_cbor.c:is_whitespace
Unexecuted instantiation: fuzzer_der.c:is_whitespace
Unexecuted instantiation: fuzzer_dns.c:is_whitespace
Unexecuted instantiation: fuzzer_tacacs.c:is_whitespace
Unexecuted instantiation: fuzzer_bfd.c:is_whitespace
Unexecuted instantiation: fuzzer_radius.c:is_whitespace
Unexecuted instantiation: fuzzer_tftp.c:is_whitespace
Unexecuted instantiation: fuzzer_vmps.c:is_whitespace
Unexecuted instantiation: atexit.c:is_whitespace
Unexecuted instantiation: backtrace.c:is_whitespace
Unexecuted instantiation: base16.c:is_whitespace
Unexecuted instantiation: base32.c:is_whitespace
Unexecuted instantiation: base64.c:is_whitespace
Unexecuted instantiation: calc.c:is_whitespace
Unexecuted instantiation: cbor.c:is_whitespace
Unexecuted instantiation: dbuff.c:is_whitespace
Unexecuted instantiation: debug.c:is_whitespace
Unexecuted instantiation: decode.c:is_whitespace
Unexecuted instantiation: dict_ext.c:is_whitespace
Unexecuted instantiation: dict_fixup.c:is_whitespace
Unexecuted instantiation: dict_print.c:is_whitespace
Unexecuted instantiation: dict_test.c:is_whitespace
Unexecuted instantiation: dict_tokenize.c:is_whitespace
Unexecuted instantiation: dict_unknown.c:is_whitespace
Unexecuted instantiation: dict_util.c:is_whitespace
Unexecuted instantiation: dict_validate.c:is_whitespace
Unexecuted instantiation: dl.c:is_whitespace
Unexecuted instantiation: dns.c:is_whitespace
Unexecuted instantiation: edit.c:is_whitespace
Unexecuted instantiation: encode.c:is_whitespace
Unexecuted instantiation: event.c:is_whitespace
Unexecuted instantiation: timer.c:is_whitespace
Unexecuted instantiation: ext.c:is_whitespace
Unexecuted instantiation: file.c:is_whitespace
Unexecuted instantiation: hash.c:is_whitespace
Unexecuted instantiation: heap.c:is_whitespace
Unexecuted instantiation: htrie.c:is_whitespace
Unexecuted instantiation: inet.c:is_whitespace
Unexecuted instantiation: iovec.c:is_whitespace
Unexecuted instantiation: log.c:is_whitespace
Unexecuted instantiation: lst.c:is_whitespace
Unexecuted instantiation: machine.c:is_whitespace
Unexecuted instantiation: minmax_heap.c:is_whitespace
Unexecuted instantiation: misc.c:is_whitespace
Unexecuted instantiation: net.c:is_whitespace
Unexecuted instantiation: packet.c:is_whitespace
Unexecuted instantiation: pair.c:is_whitespace
Unexecuted instantiation: pair_inline.c:is_whitespace
Unexecuted instantiation: pair_legacy.c:is_whitespace
Unexecuted instantiation: pair_print.c:is_whitespace
Unexecuted instantiation: pair_tokenize.c:is_whitespace
Unexecuted instantiation: print.c:is_whitespace
Unexecuted instantiation: proto.c:is_whitespace
Unexecuted instantiation: rand.c:is_whitespace
Unexecuted instantiation: rb.c:is_whitespace
Unexecuted instantiation: rb_expire.c:is_whitespace
Unexecuted instantiation: regex.c:is_whitespace
Unexecuted instantiation: sbuff.c:is_whitespace
Unexecuted instantiation: skip.c:is_whitespace
Unexecuted instantiation: socket.c:is_whitespace
Unexecuted instantiation: stats.c:is_whitespace
Unexecuted instantiation: strerror.c:is_whitespace
Unexecuted instantiation: struct.c:is_whitespace
Unexecuted instantiation: syserror.c:is_whitespace
Unexecuted instantiation: table.c:is_whitespace
Unexecuted instantiation: talloc.c:is_whitespace
Unexecuted instantiation: trie.c:is_whitespace
Unexecuted instantiation: types.c:is_whitespace
Unexecuted instantiation: udp.c:is_whitespace
Unexecuted instantiation: udp_queue.c:is_whitespace
Unexecuted instantiation: uri.c:is_whitespace
Unexecuted instantiation: value.c:is_whitespace
Unexecuted instantiation: fuzzer.c:is_whitespace
Unexecuted instantiation: base.c:is_whitespace
Unexecuted instantiation: raw.c:is_whitespace
Unexecuted instantiation: list.c:is_whitespace
Unexecuted instantiation: tcp.c:is_whitespace
Unexecuted instantiation: abinary.c:is_whitespace
Unexecuted instantiation: vmps.c:is_whitespace
78
79
/** Check whether the string is made up of printable UTF8 chars
80
 *
81
 * @param value to check.
82
 * @param len of value.
83
 *
84
 * @return
85
 *  - true if the string is printable.
86
 *  - false if the string contains non printable chars
87
 */
88
 static inline bool is_printable(void const *value, size_t len)
89
0
 {
90
0
  uint8_t const *p = value;
91
0
  size_t  clen;
92
0
  size_t  i;
93
0
94
0
  for (i = 0; i < len; i++) {
95
0
    clen = fr_utf8_char(p, len - i);
96
0
    if (clen == 0) return false;
97
0
    i += (size_t)clen;
98
0
    p += clen;
99
0
  }
100
0
  return true;
101
0
 }
Unexecuted instantiation: fuzzer_dhcpv6.c:is_printable
Unexecuted instantiation: fuzzer_util.c:is_printable
Unexecuted instantiation: fuzzer_dhcpv4.c:is_printable
Unexecuted instantiation: fuzzer_cbor.c:is_printable
Unexecuted instantiation: fuzzer_der.c:is_printable
Unexecuted instantiation: fuzzer_dns.c:is_printable
Unexecuted instantiation: fuzzer_tacacs.c:is_printable
Unexecuted instantiation: fuzzer_bfd.c:is_printable
Unexecuted instantiation: fuzzer_radius.c:is_printable
Unexecuted instantiation: fuzzer_tftp.c:is_printable
Unexecuted instantiation: fuzzer_vmps.c:is_printable
Unexecuted instantiation: atexit.c:is_printable
Unexecuted instantiation: backtrace.c:is_printable
Unexecuted instantiation: base16.c:is_printable
Unexecuted instantiation: base32.c:is_printable
Unexecuted instantiation: base64.c:is_printable
Unexecuted instantiation: calc.c:is_printable
Unexecuted instantiation: cbor.c:is_printable
Unexecuted instantiation: dbuff.c:is_printable
Unexecuted instantiation: debug.c:is_printable
Unexecuted instantiation: decode.c:is_printable
Unexecuted instantiation: dict_ext.c:is_printable
Unexecuted instantiation: dict_fixup.c:is_printable
Unexecuted instantiation: dict_print.c:is_printable
Unexecuted instantiation: dict_test.c:is_printable
Unexecuted instantiation: dict_tokenize.c:is_printable
Unexecuted instantiation: dict_unknown.c:is_printable
Unexecuted instantiation: dict_util.c:is_printable
Unexecuted instantiation: dict_validate.c:is_printable
Unexecuted instantiation: dl.c:is_printable
Unexecuted instantiation: dns.c:is_printable
Unexecuted instantiation: edit.c:is_printable
Unexecuted instantiation: encode.c:is_printable
Unexecuted instantiation: event.c:is_printable
Unexecuted instantiation: timer.c:is_printable
Unexecuted instantiation: ext.c:is_printable
Unexecuted instantiation: file.c:is_printable
Unexecuted instantiation: hash.c:is_printable
Unexecuted instantiation: heap.c:is_printable
Unexecuted instantiation: htrie.c:is_printable
Unexecuted instantiation: inet.c:is_printable
Unexecuted instantiation: iovec.c:is_printable
Unexecuted instantiation: log.c:is_printable
Unexecuted instantiation: lst.c:is_printable
Unexecuted instantiation: machine.c:is_printable
Unexecuted instantiation: minmax_heap.c:is_printable
Unexecuted instantiation: misc.c:is_printable
Unexecuted instantiation: net.c:is_printable
Unexecuted instantiation: packet.c:is_printable
Unexecuted instantiation: pair.c:is_printable
Unexecuted instantiation: pair_inline.c:is_printable
Unexecuted instantiation: pair_legacy.c:is_printable
Unexecuted instantiation: pair_print.c:is_printable
Unexecuted instantiation: pair_tokenize.c:is_printable
Unexecuted instantiation: print.c:is_printable
Unexecuted instantiation: proto.c:is_printable
Unexecuted instantiation: rand.c:is_printable
Unexecuted instantiation: rb.c:is_printable
Unexecuted instantiation: rb_expire.c:is_printable
Unexecuted instantiation: regex.c:is_printable
Unexecuted instantiation: sbuff.c:is_printable
Unexecuted instantiation: skip.c:is_printable
Unexecuted instantiation: socket.c:is_printable
Unexecuted instantiation: stats.c:is_printable
Unexecuted instantiation: strerror.c:is_printable
Unexecuted instantiation: struct.c:is_printable
Unexecuted instantiation: syserror.c:is_printable
Unexecuted instantiation: table.c:is_printable
Unexecuted instantiation: talloc.c:is_printable
Unexecuted instantiation: trie.c:is_printable
Unexecuted instantiation: types.c:is_printable
Unexecuted instantiation: udp.c:is_printable
Unexecuted instantiation: udp_queue.c:is_printable
Unexecuted instantiation: uri.c:is_printable
Unexecuted instantiation: value.c:is_printable
Unexecuted instantiation: fuzzer.c:is_printable
Unexecuted instantiation: base.c:is_printable
Unexecuted instantiation: raw.c:is_printable
Unexecuted instantiation: list.c:is_printable
Unexecuted instantiation: tcp.c:is_printable
Unexecuted instantiation: abinary.c:is_printable
Unexecuted instantiation: vmps.c:is_printable
102
103
/** Check whether the string is all numbers
104
 *
105
 * @return
106
 *  - true if the entirety of the string is number chars.
107
 *  - false if string contains non-numeric chars or is empty.
108
 */
109
static inline bool is_integer(char const *value)
110
2.49k
{
111
#ifdef STATIC_ANALYZER
112
  if (*value == '\0') return false; /* clang analyzer doesn't seem to know what isdigit does */
113
#endif
114
4.90k
  do {
115
4.90k
    if (!isdigit((uint8_t) *value)) return false;
116
4.90k
  } while (*++value);
117
118
579
  return true;
119
2.49k
}
Unexecuted instantiation: fuzzer_dhcpv6.c:is_integer
Unexecuted instantiation: fuzzer_util.c:is_integer
Unexecuted instantiation: fuzzer_dhcpv4.c:is_integer
Unexecuted instantiation: fuzzer_cbor.c:is_integer
Unexecuted instantiation: fuzzer_der.c:is_integer
Unexecuted instantiation: fuzzer_dns.c:is_integer
Unexecuted instantiation: fuzzer_tacacs.c:is_integer
Unexecuted instantiation: fuzzer_bfd.c:is_integer
Unexecuted instantiation: fuzzer_radius.c:is_integer
Unexecuted instantiation: fuzzer_tftp.c:is_integer
Unexecuted instantiation: fuzzer_vmps.c:is_integer
Unexecuted instantiation: atexit.c:is_integer
Unexecuted instantiation: backtrace.c:is_integer
Unexecuted instantiation: base16.c:is_integer
Unexecuted instantiation: base32.c:is_integer
Unexecuted instantiation: base64.c:is_integer
Unexecuted instantiation: calc.c:is_integer
Unexecuted instantiation: cbor.c:is_integer
Unexecuted instantiation: dbuff.c:is_integer
Unexecuted instantiation: debug.c:is_integer
Unexecuted instantiation: decode.c:is_integer
Unexecuted instantiation: dict_ext.c:is_integer
Unexecuted instantiation: dict_fixup.c:is_integer
Unexecuted instantiation: dict_print.c:is_integer
Unexecuted instantiation: dict_test.c:is_integer
Unexecuted instantiation: dict_tokenize.c:is_integer
Unexecuted instantiation: dict_unknown.c:is_integer
Unexecuted instantiation: dict_util.c:is_integer
Unexecuted instantiation: dict_validate.c:is_integer
Unexecuted instantiation: dl.c:is_integer
Unexecuted instantiation: dns.c:is_integer
Unexecuted instantiation: edit.c:is_integer
Unexecuted instantiation: encode.c:is_integer
Unexecuted instantiation: event.c:is_integer
Unexecuted instantiation: timer.c:is_integer
Unexecuted instantiation: ext.c:is_integer
Unexecuted instantiation: file.c:is_integer
Unexecuted instantiation: hash.c:is_integer
Unexecuted instantiation: heap.c:is_integer
Unexecuted instantiation: htrie.c:is_integer
inet.c:is_integer
Line
Count
Source
110
2.49k
{
111
#ifdef STATIC_ANALYZER
112
  if (*value == '\0') return false; /* clang analyzer doesn't seem to know what isdigit does */
113
#endif
114
4.90k
  do {
115
4.90k
    if (!isdigit((uint8_t) *value)) return false;
116
4.90k
  } while (*++value);
117
118
579
  return true;
119
2.49k
}
Unexecuted instantiation: iovec.c:is_integer
Unexecuted instantiation: log.c:is_integer
Unexecuted instantiation: lst.c:is_integer
Unexecuted instantiation: machine.c:is_integer
Unexecuted instantiation: minmax_heap.c:is_integer
Unexecuted instantiation: misc.c:is_integer
Unexecuted instantiation: net.c:is_integer
Unexecuted instantiation: packet.c:is_integer
Unexecuted instantiation: pair.c:is_integer
Unexecuted instantiation: pair_inline.c:is_integer
Unexecuted instantiation: pair_legacy.c:is_integer
Unexecuted instantiation: pair_print.c:is_integer
Unexecuted instantiation: pair_tokenize.c:is_integer
Unexecuted instantiation: print.c:is_integer
Unexecuted instantiation: proto.c:is_integer
Unexecuted instantiation: rand.c:is_integer
Unexecuted instantiation: rb.c:is_integer
Unexecuted instantiation: rb_expire.c:is_integer
Unexecuted instantiation: regex.c:is_integer
Unexecuted instantiation: sbuff.c:is_integer
Unexecuted instantiation: skip.c:is_integer
Unexecuted instantiation: socket.c:is_integer
Unexecuted instantiation: stats.c:is_integer
Unexecuted instantiation: strerror.c:is_integer
Unexecuted instantiation: struct.c:is_integer
Unexecuted instantiation: syserror.c:is_integer
Unexecuted instantiation: table.c:is_integer
Unexecuted instantiation: talloc.c:is_integer
Unexecuted instantiation: trie.c:is_integer
Unexecuted instantiation: types.c:is_integer
Unexecuted instantiation: udp.c:is_integer
Unexecuted instantiation: udp_queue.c:is_integer
Unexecuted instantiation: uri.c:is_integer
Unexecuted instantiation: value.c:is_integer
Unexecuted instantiation: fuzzer.c:is_integer
Unexecuted instantiation: base.c:is_integer
Unexecuted instantiation: raw.c:is_integer
Unexecuted instantiation: list.c:is_integer
Unexecuted instantiation: tcp.c:is_integer
Unexecuted instantiation: abinary.c:is_integer
Unexecuted instantiation: vmps.c:is_integer
120
121
/** Check whether the string is all zeros
122
 *
123
 * @return
124
 *  - true if the entirety of the string is all zeros.
125
 *  - false if string contains non-zero chars or is empty.
126
 */
127
static inline bool is_zero(char const *value)
128
0
{
129
0
  do {
130
0
    if (*value != '0') return false;
131
0
  } while (*++value);
132
0
133
0
  return true;
134
0
}
Unexecuted instantiation: fuzzer_dhcpv6.c:is_zero
Unexecuted instantiation: fuzzer_util.c:is_zero
Unexecuted instantiation: fuzzer_dhcpv4.c:is_zero
Unexecuted instantiation: fuzzer_cbor.c:is_zero
Unexecuted instantiation: fuzzer_der.c:is_zero
Unexecuted instantiation: fuzzer_dns.c:is_zero
Unexecuted instantiation: fuzzer_tacacs.c:is_zero
Unexecuted instantiation: fuzzer_bfd.c:is_zero
Unexecuted instantiation: fuzzer_radius.c:is_zero
Unexecuted instantiation: fuzzer_tftp.c:is_zero
Unexecuted instantiation: fuzzer_vmps.c:is_zero
Unexecuted instantiation: atexit.c:is_zero
Unexecuted instantiation: backtrace.c:is_zero
Unexecuted instantiation: base16.c:is_zero
Unexecuted instantiation: base32.c:is_zero
Unexecuted instantiation: base64.c:is_zero
Unexecuted instantiation: calc.c:is_zero
Unexecuted instantiation: cbor.c:is_zero
Unexecuted instantiation: dbuff.c:is_zero
Unexecuted instantiation: debug.c:is_zero
Unexecuted instantiation: decode.c:is_zero
Unexecuted instantiation: dict_ext.c:is_zero
Unexecuted instantiation: dict_fixup.c:is_zero
Unexecuted instantiation: dict_print.c:is_zero
Unexecuted instantiation: dict_test.c:is_zero
Unexecuted instantiation: dict_tokenize.c:is_zero
Unexecuted instantiation: dict_unknown.c:is_zero
Unexecuted instantiation: dict_util.c:is_zero
Unexecuted instantiation: dict_validate.c:is_zero
Unexecuted instantiation: dl.c:is_zero
Unexecuted instantiation: dns.c:is_zero
Unexecuted instantiation: edit.c:is_zero
Unexecuted instantiation: encode.c:is_zero
Unexecuted instantiation: event.c:is_zero
Unexecuted instantiation: timer.c:is_zero
Unexecuted instantiation: ext.c:is_zero
Unexecuted instantiation: file.c:is_zero
Unexecuted instantiation: hash.c:is_zero
Unexecuted instantiation: heap.c:is_zero
Unexecuted instantiation: htrie.c:is_zero
Unexecuted instantiation: inet.c:is_zero
Unexecuted instantiation: iovec.c:is_zero
Unexecuted instantiation: log.c:is_zero
Unexecuted instantiation: lst.c:is_zero
Unexecuted instantiation: machine.c:is_zero
Unexecuted instantiation: minmax_heap.c:is_zero
Unexecuted instantiation: misc.c:is_zero
Unexecuted instantiation: net.c:is_zero
Unexecuted instantiation: packet.c:is_zero
Unexecuted instantiation: pair.c:is_zero
Unexecuted instantiation: pair_inline.c:is_zero
Unexecuted instantiation: pair_legacy.c:is_zero
Unexecuted instantiation: pair_print.c:is_zero
Unexecuted instantiation: pair_tokenize.c:is_zero
Unexecuted instantiation: print.c:is_zero
Unexecuted instantiation: proto.c:is_zero
Unexecuted instantiation: rand.c:is_zero
Unexecuted instantiation: rb.c:is_zero
Unexecuted instantiation: rb_expire.c:is_zero
Unexecuted instantiation: regex.c:is_zero
Unexecuted instantiation: sbuff.c:is_zero
Unexecuted instantiation: skip.c:is_zero
Unexecuted instantiation: socket.c:is_zero
Unexecuted instantiation: stats.c:is_zero
Unexecuted instantiation: strerror.c:is_zero
Unexecuted instantiation: struct.c:is_zero
Unexecuted instantiation: syserror.c:is_zero
Unexecuted instantiation: table.c:is_zero
Unexecuted instantiation: talloc.c:is_zero
Unexecuted instantiation: trie.c:is_zero
Unexecuted instantiation: types.c:is_zero
Unexecuted instantiation: udp.c:is_zero
Unexecuted instantiation: udp_queue.c:is_zero
Unexecuted instantiation: uri.c:is_zero
Unexecuted instantiation: value.c:is_zero
Unexecuted instantiation: fuzzer.c:is_zero
Unexecuted instantiation: base.c:is_zero
Unexecuted instantiation: raw.c:is_zero
Unexecuted instantiation: list.c:is_zero
Unexecuted instantiation: tcp.c:is_zero
Unexecuted instantiation: abinary.c:is_zero
Unexecuted instantiation: vmps.c:is_zero
135
136
int   fr_set_signal(int sig, sig_t func);
137
int   fr_unset_signal(int sig);
138
int   rad_lockfd(int fd, int lock_len);
139
int   rad_lockfd_nonblock(int fd, int lock_len);
140
int   rad_unlockfd(int fd, int lock_len);
141
int   fr_strtoull(uint64_t *out, char **end, char const *value);
142
int   fr_strtoll(int64_t *out, char **end, char const *value);
143
char    *fr_trim(char const *str, size_t size);
144
char    *fr_tolower(char *str);
145
146
int   fr_nonblock(int fd);
147
int   fr_blocking(int fd);
148
int   fr_cloexec(int fd);
149
150
ssize_t   fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen);
151
size_t    fr_snprint_uint128(char *out, size_t outlen, uint128_t const num);
152
153
int8_t    fr_pointer_cmp(void const *a, void const *b);
154
void    fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp);
155
int   fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length) CC_HINT(nonnull);
156
157
char const  *fr_filename(char const *path);
158
char const  *fr_filename_common_trim(char const *path, char const *common);
159
160
/*
161
 *  Some libraries need to call suid up/down, except that those are functions in the server, and we don't
162
 *  want to link everything to the server library.  As a result, we include trampoline functions which do
163
 *  nothing, but which can be over-written by the server when is starts.
164
 */
165
typedef void (*fr_suid_t)(void);
166
167
void    fr_suid_noop(void);
168
extern    fr_suid_t fr_suid_up;
169
extern    fr_suid_t fr_suid_down;
170
171
#ifdef __cplusplus
172
}
173
#endif