]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/basic/strxcpyx.c
NEWS: fix typo
[thirdparty/systemd.git] / src / basic / strxcpyx.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3/*
4 * Concatenates/copies strings. In any case, terminates in all cases
5 * with '\0' and moves the @dest pointer forward to the added '\0'.
6 * Returns the remaining size, and 0 if the string was truncated.
7 *
8 * Due to the intended usage, these helpers silently noop invocations
9 * having zero size. This is technically an exception to the above
10 * statement "terminates in all cases". It's unexpected for such calls to
11 * occur outside of a loop where this is the preferred behavior.
12 */
13
14#include <stdio.h>
15#include <string.h>
16
17#include "strxcpyx.h"
18
19size_t strnpcpy_full(char **dest, size_t size, const char *src, size_t len, bool *ret_truncated) {
20 bool truncated = false;
21
22 assert(dest);
23 assert(src);
24
25 if (size == 0) {
26 if (ret_truncated)
27 *ret_truncated = len > 0;
28 return 0;
29 }
30
31 if (len >= size) {
32 if (size > 1)
33 *dest = mempcpy(*dest, src, size-1);
34 size = 0;
35 truncated = true;
36 } else if (len > 0) {
37 *dest = mempcpy(*dest, src, len);
38 size -= len;
39 }
40
41 if (ret_truncated)
42 *ret_truncated = truncated;
43
44 *dest[0] = '\0';
45 return size;
46}
47
48size_t strpcpy_full(char **dest, size_t size, const char *src, bool *ret_truncated) {
49 assert(dest);
50 assert(src);
51
52 return strnpcpy_full(dest, size, src, strlen(src), ret_truncated);
53}
54
55size_t strpcpyf_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) {
56 bool truncated = false;
57 va_list va;
58 int i;
59
60 assert(dest);
61 assert(src);
62
63 va_start(va, src);
64 i = vsnprintf(*dest, size, src, va);
65 va_end(va);
66
67 if (i < (int) size) {
68 *dest += i;
69 size -= i;
70 } else {
71 size = 0;
72 truncated = i > 0;
73 }
74
75 if (ret_truncated)
76 *ret_truncated = truncated;
77
78 return size;
79}
80
81size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) {
82 bool truncated = false;
83 va_list va;
84
85 assert(dest);
86 assert(src);
87
88 va_start(va, src);
89 do {
90 bool t;
91
92 size = strpcpy_full(dest, size, src, &t);
93 truncated = truncated || t;
94 src = va_arg(va, char *);
95 } while (src);
96 va_end(va);
97
98 if (ret_truncated)
99 *ret_truncated = truncated;
100 return size;
101}
102
103size_t strnscpy_full(char *dest, size_t size, const char *src, size_t len, bool *ret_truncated) {
104 char *s;
105
106 assert(dest);
107 assert(src);
108
109 s = dest;
110 return strnpcpy_full(&s, size, src, len, ret_truncated);
111}
112
113size_t strscpy_full(char *dest, size_t size, const char *src, bool *ret_truncated) {
114 assert(dest);
115 assert(src);
116
117 return strnscpy_full(dest, size, src, strlen(src), ret_truncated);
118}
119
120size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *src, ...) {
121 bool truncated = false;
122 va_list va;
123 char *s;
124
125 assert(dest);
126 assert(src);
127
128 va_start(va, src);
129 s = dest;
130 do {
131 bool t;
132
133 size = strpcpy_full(&s, size, src, &t);
134 truncated = truncated || t;
135 src = va_arg(va, char *);
136 } while (src);
137 va_end(va);
138
139 if (ret_truncated)
140 *ret_truncated = truncated;
141
142 return size;
143}