1 /* 2 * Automated Testing Framework (atf) 3 * 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <errno.h> 31 #include <stdarg.h> 32 #include <stdint.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "atf-c/error.h" 38 39 #include "dynstr.h" 40 #include "sanity.h" 41 #include "text.h" 42 43 /* --------------------------------------------------------------------- 44 * Auxiliary functions. 45 * --------------------------------------------------------------------- */ 46 47 static 48 atf_error_t 49 resize(atf_dynstr_t *ad, size_t newsize) 50 { 51 char *newdata; 52 atf_error_t err; 53 54 PRE(newsize > ad->m_datasize); 55 56 newdata = (char *)malloc(newsize); 57 if (newdata == NULL) { 58 err = atf_no_memory_error(); 59 } else { 60 strcpy(newdata, ad->m_data); 61 free(ad->m_data); 62 ad->m_data = newdata; 63 ad->m_datasize = newsize; 64 err = atf_no_error(); 65 } 66 67 return err; 68 } 69 70 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0) 71 static 72 atf_error_t 73 prepend_or_append(atf_dynstr_t *ad, const char *fmt, va_list ap, 74 bool prepend) 75 { 76 char *aux; 77 atf_error_t err; 78 size_t newlen; 79 va_list ap2; 80 81 va_copy(ap2, ap); 82 err = atf_text_format_ap(&aux, fmt, ap2); 83 va_end(ap2); 84 if (atf_is_error(err)) 85 goto out; 86 newlen = ad->m_length + strlen(aux); 87 88 if (newlen + sizeof(char) > ad->m_datasize) { 89 err = resize(ad, newlen + sizeof(char)); 90 if (atf_is_error(err)) 91 goto out_free; 92 } 93 94 if (prepend) { 95 memmove(ad->m_data + strlen(aux), ad->m_data, ad->m_length + 1); 96 memcpy(ad->m_data, aux, strlen(aux)); 97 } else 98 strcpy(ad->m_data + ad->m_length, aux); 99 ad->m_length = newlen; 100 err = atf_no_error(); 101 102 out_free: 103 free(aux); 104 out: 105 return err; 106 } 107 108 /* --------------------------------------------------------------------- 109 * The "atf_dynstr" type. 110 * --------------------------------------------------------------------- */ 111 112 /* 113 * Constants. 114 */ 115 116 const size_t atf_dynstr_npos = SIZE_MAX; 117 118 /* 119 * Constructors and destructors. 120 */ 121 122 atf_error_t 123 atf_dynstr_init(atf_dynstr_t *ad) 124 { 125 atf_error_t err; 126 127 ad->m_data = (char *)malloc(sizeof(char)); 128 if (ad->m_data == NULL) { 129 err = atf_no_memory_error(); 130 goto out; 131 } 132 133 ad->m_data[0] = '\0'; 134 ad->m_datasize = 1; 135 ad->m_length = 0; 136 err = atf_no_error(); 137 138 out: 139 return err; 140 } 141 142 atf_error_t 143 atf_dynstr_init_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) 144 { 145 atf_error_t err; 146 147 ad->m_datasize = strlen(fmt) + 1; 148 ad->m_length = 0; 149 150 do { 151 va_list ap2; 152 int ret; 153 154 ad->m_datasize *= 2; 155 ad->m_data = (char *)malloc(ad->m_datasize); 156 if (ad->m_data == NULL) { 157 err = atf_no_memory_error(); 158 goto out; 159 } 160 161 va_copy(ap2, ap); 162 ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2); 163 va_end(ap2); 164 if (ret < 0) { 165 free(ad->m_data); 166 err = atf_libc_error(errno, "Cannot format string"); 167 goto out; 168 } 169 170 INV(ret >= 0); 171 if ((size_t)ret >= ad->m_datasize) { 172 free(ad->m_data); 173 ad->m_data = NULL; 174 } 175 ad->m_length = ret; 176 } while (ad->m_length >= ad->m_datasize); 177 178 err = atf_no_error(); 179 out: 180 POST(atf_is_error(err) || ad->m_data != NULL); 181 return err; 182 } 183 184 atf_error_t 185 atf_dynstr_init_fmt(atf_dynstr_t *ad, const char *fmt, ...) 186 { 187 va_list ap; 188 atf_error_t err; 189 190 va_start(ap, fmt); 191 err = atf_dynstr_init_ap(ad, fmt, ap); 192 va_end(ap); 193 194 return err; 195 } 196 197 atf_error_t 198 atf_dynstr_init_raw(atf_dynstr_t *ad, const void *mem, size_t memlen) 199 { 200 atf_error_t err; 201 202 if (memlen >= SIZE_MAX - 1) { 203 err = atf_no_memory_error(); 204 goto out; 205 } 206 207 ad->m_data = (char *)malloc(memlen + 1); 208 if (ad->m_data == NULL) { 209 err = atf_no_memory_error(); 210 goto out; 211 } 212 213 ad->m_datasize = memlen + 1; 214 memcpy(ad->m_data, mem, memlen); 215 ad->m_data[memlen] = '\0'; 216 ad->m_length = strlen(ad->m_data); 217 INV(ad->m_length <= memlen); 218 err = atf_no_error(); 219 220 out: 221 return err; 222 } 223 224 atf_error_t 225 atf_dynstr_init_rep(atf_dynstr_t *ad, size_t len, char ch) 226 { 227 atf_error_t err; 228 229 if (len == SIZE_MAX) { 230 err = atf_no_memory_error(); 231 goto out; 232 } 233 234 ad->m_datasize = (len + 1) * sizeof(char); 235 ad->m_data = (char *)malloc(ad->m_datasize); 236 if (ad->m_data == NULL) { 237 err = atf_no_memory_error(); 238 goto out; 239 } 240 241 memset(ad->m_data, ch, len); 242 ad->m_data[len] = '\0'; 243 ad->m_length = len; 244 err = atf_no_error(); 245 246 out: 247 return err; 248 } 249 250 atf_error_t 251 atf_dynstr_init_substr(atf_dynstr_t *ad, const atf_dynstr_t *src, 252 size_t beg, size_t end) 253 { 254 if (beg > src->m_length) 255 beg = src->m_length; 256 257 if (end == atf_dynstr_npos || end > src->m_length) 258 end = src->m_length; 259 260 return atf_dynstr_init_raw(ad, src->m_data + beg, end - beg); 261 } 262 263 atf_error_t 264 atf_dynstr_copy(atf_dynstr_t *dest, const atf_dynstr_t *src) 265 { 266 atf_error_t err; 267 268 dest->m_data = (char *)malloc(src->m_datasize); 269 if (dest->m_data == NULL) 270 err = atf_no_memory_error(); 271 else { 272 memcpy(dest->m_data, src->m_data, src->m_datasize); 273 dest->m_datasize = src->m_datasize; 274 dest->m_length = src->m_length; 275 err = atf_no_error(); 276 } 277 278 return err; 279 } 280 281 void 282 atf_dynstr_fini(atf_dynstr_t *ad) 283 { 284 INV(ad->m_data != NULL); 285 free(ad->m_data); 286 } 287 288 char * 289 atf_dynstr_fini_disown(atf_dynstr_t *ad) 290 { 291 INV(ad->m_data != NULL); 292 return ad->m_data; 293 } 294 295 /* 296 * Getters. 297 */ 298 299 const char * 300 atf_dynstr_cstring(const atf_dynstr_t *ad) 301 { 302 return ad->m_data; 303 } 304 305 size_t 306 atf_dynstr_length(const atf_dynstr_t *ad) 307 { 308 return ad->m_length; 309 } 310 311 size_t 312 atf_dynstr_rfind_ch(const atf_dynstr_t *ad, char ch) 313 { 314 size_t pos; 315 316 for (pos = ad->m_length; pos > 0 && ad->m_data[pos - 1] != ch; pos--) 317 ; 318 319 return pos == 0 ? atf_dynstr_npos : pos - 1; 320 } 321 322 /* 323 * Modifiers. 324 */ 325 326 atf_error_t 327 atf_dynstr_append_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) 328 { 329 atf_error_t err; 330 va_list ap2; 331 332 va_copy(ap2, ap); 333 err = prepend_or_append(ad, fmt, ap2, false); 334 va_end(ap2); 335 336 return err; 337 } 338 339 atf_error_t 340 atf_dynstr_append_fmt(atf_dynstr_t *ad, const char *fmt, ...) 341 { 342 va_list ap; 343 atf_error_t err; 344 345 va_start(ap, fmt); 346 err = prepend_or_append(ad, fmt, ap, false); 347 va_end(ap); 348 349 return err; 350 } 351 352 void 353 atf_dynstr_clear(atf_dynstr_t *ad) 354 { 355 ad->m_data[0] = '\0'; 356 ad->m_length = 0; 357 } 358 359 atf_error_t 360 atf_dynstr_prepend_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) 361 { 362 atf_error_t err; 363 va_list ap2; 364 365 va_copy(ap2, ap); 366 err = prepend_or_append(ad, fmt, ap2, true); 367 va_end(ap2); 368 369 return err; 370 } 371 372 atf_error_t 373 atf_dynstr_prepend_fmt(atf_dynstr_t *ad, const char *fmt, ...) 374 { 375 va_list ap; 376 atf_error_t err; 377 378 va_start(ap, fmt); 379 err = prepend_or_append(ad, fmt, ap, true); 380 va_end(ap); 381 382 return err; 383 } 384 385 /* 386 * Operators. 387 */ 388 389 bool 390 atf_equal_dynstr_cstring(const atf_dynstr_t *ad, const char *str) 391 { 392 return strcmp(ad->m_data, str) == 0; 393 } 394 395 bool 396 atf_equal_dynstr_dynstr(const atf_dynstr_t *s1, const atf_dynstr_t *s2) 397 { 398 return strcmp(s1->m_data, s2->m_data) == 0; 399 } 400