1 /**
2 * \file rpmio/rpmstring.c
3 */
4
5 #include "system.h"
6
7 #include <stdarg.h>
8 #include <stdio.h>
9
10 #include <rpm/rpmstring.h>
11 #include "debug.h"
12
13
rstrcasecmp(const char * s1,const char * s2)14 int rstrcasecmp(const char * s1, const char * s2)
15 {
16 const char * p1 = s1;
17 const char * p2 = s2;
18 char c1, c2;
19
20 if (p1 == p2)
21 return 0;
22
23 do
24 {
25 c1 = rtolower (*p1++);
26 c2 = rtolower (*p2++);
27 if (c1 == '\0')
28 break;
29 }
30 while (c1 == c2);
31
32 return (int)(c1 - c2);
33 }
34
rstrncasecmp(const char * s1,const char * s2,size_t n)35 int rstrncasecmp(const char *s1, const char *s2, size_t n)
36 {
37 const char * p1 = s1;
38 const char * p2 = s2;
39 char c1, c2;
40
41 if (p1 == p2 || n == 0)
42 return 0;
43
44 do
45 {
46 c1 = rtolower (*p1++);
47 c2 = rtolower (*p2++);
48 if (c1 == '\0' || c1 != c2)
49 break;
50 } while (--n > 0);
51
52 return (int)(c1 - c2);
53 }
54
rvasprintf(char ** strp,const char * fmt,va_list ap)55 int rvasprintf(char **strp, const char *fmt, va_list ap)
56 {
57 int n;
58 char * p = NULL;
59 va_list aq;
60
61 if (strp == NULL)
62 return -1;
63
64 va_copy(aq, ap);
65 n = vsnprintf(NULL, 0, fmt, aq);
66 va_end(aq);
67
68 if (n >= -1) {
69 size_t nb = n + 1;
70 p = xmalloc(nb);
71 va_copy(aq, ap);
72 n = vsnprintf(p, nb, fmt, aq);
73 va_end(aq);
74 }
75 *strp = p;
76 return n;
77 }
78
rasprintf(char ** strp,const char * fmt,...)79 int rasprintf(char **strp, const char *fmt, ...)
80 {
81 int n;
82 va_list ap;
83
84 va_start(ap, fmt);
85 n = rvasprintf(strp, fmt, ap);
86 va_end(ap);
87
88 return n;
89 }
90
91 /*
92 * Concatenate two strings with dynamically (re)allocated
93 * memory what prevents static buffer overflows by design.
94 * *dest is reallocated to the size of strings to concatenate.
95 *
96 * Note:
97 * 1) char *buf = rstrcat(NULL,"string"); is the same like rstrcat(&buf,"string");
98 * 2) rstrcat(&buf,NULL) returns buf
99 * 3) rstrcat(NULL,NULL) returns NULL
100 * 4) *dest and src can overlap
101 */
rstrcat(char ** dest,const char * src)102 char *rstrcat(char **dest, const char *src)
103 {
104 if ( src == NULL ) {
105 return dest != NULL ? *dest : NULL;
106 }
107
108 if ( dest == NULL ) {
109 return xstrdup(src);
110 }
111
112 {
113 size_t dest_size = *dest != NULL ? strlen(*dest) : 0;
114 size_t src_size = strlen(src);
115
116 *dest = xrealloc(*dest, dest_size+src_size+1); /* include '\0' */
117 memmove(&(*dest)[dest_size], src, src_size+1);
118 }
119
120 return *dest;
121 }
122
123 /*
124 * Concatenate strings with dynamically (re)allocated
125 * memory what prevents static buffer overflows by design.
126 * *dest is reallocated to the size of strings to concatenate.
127 * List of strings has to be NULL terminated.
128 *
129 * Note:
130 * 1) char *buf = rstrscat(NULL,"string",NULL); is the same like rstrscat(&buf,"string",NULL);
131 * 2) rstrscat(&buf,NULL) returns buf
132 * 3) rstrscat(NULL,NULL) returns NULL
133 * 4) *dest and argument strings can overlap
134 */
rstrscat(char ** dest,const char * arg,...)135 char *rstrscat(char **dest, const char *arg, ...)
136 {
137 va_list ap;
138 size_t arg_size, dst_size;
139 const char *s;
140 char *dst, *p;
141
142 dst = dest ? *dest : NULL;
143
144 if ( arg == NULL ) {
145 return dst;
146 }
147
148 va_start(ap, arg);
149 for (arg_size=0, s=arg; s; s = va_arg(ap, const char *))
150 arg_size += strlen(s);
151 va_end(ap);
152
153 dst_size = dst ? strlen(dst) : 0;
154 dst = xrealloc(dst, dst_size+arg_size+1); /* include '\0' */
155 p = &dst[dst_size];
156
157 va_start(ap, arg);
158 for (s = arg; s; s = va_arg(ap, const char *)) {
159 size_t size = strlen(s);
160 memmove(p, s, size);
161 p += size;
162 }
163 va_end(ap);
164 *p = '\0';
165
166 if ( dest ) {
167 *dest = dst;
168 }
169
170 return dst;
171 }
172
173 /*
174 * Adapted from OpenBSD, strlcpy() originally developed by
175 * Todd C. Miller <Todd.Miller@courtesan.com>
176 */
rstrlcpy(char * dest,const char * src,size_t n)177 size_t rstrlcpy(char *dest, const char *src, size_t n)
178 {
179 char *d = dest;
180 const char *s = src;
181 size_t len = n;
182
183 /* Copy as many bytes as will fit */
184 if (len != 0) {
185 while (--len != 0) {
186 if ((*d++ = *s++) == '\0')
187 break;
188 }
189 }
190
191 /* Not enough room in dst, add NUL and traverse rest of src */
192 if (len == 0) {
193 if (n != 0)
194 *d = '\0'; /* NUL-terminate dst */
195 while (*s++)
196 ;
197 }
198
199 return s - src - 1; /* count does not include NUL */
200 }
201