Mercurial > libpst
comparison src/vbuf.c @ 73:3cb02cb1e6cd stable-0-6-10
Patch from Robert Simpson to fix doubly-linked list in the cache_ptr code, and allow arrays of unicode strings (without converting them).
More changes for Fedora packaging (#434727)
Fixes for const correctness.
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 29 May 2008 18:51:02 -0700 |
parents | b12f4e50e2e8 |
children | cb14583c119a |
comparison
equal
deleted
inserted
replaced
72:c21e9c001256 | 73:3cb02cb1e6cd |
---|---|
7 #include <signal.h> | 7 #include <signal.h> |
8 #include <stdarg.h> | 8 #include <stdarg.h> |
9 #include <stdio.h> | 9 #include <stdio.h> |
10 #include <stdlib.h> | 10 #include <stdlib.h> |
11 #include <string.h> | 11 #include <string.h> |
12 | |
13 #include "define.h" | |
12 #include "vbuf.h" | 14 #include "vbuf.h" |
13 #include "generic.h" | |
14 | 15 |
15 #ifdef WITH_DMALLOC | 16 #ifdef WITH_DMALLOC |
16 #include <dmalloc.h> | 17 #include <dmalloc.h> |
17 #endif | 18 #endif |
19 | |
20 #define STUPID_CR "\r\n" | |
21 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); } | |
18 | 22 |
19 | 23 |
20 int skip_nl(char *s) | 24 int skip_nl(char *s) |
21 { | 25 { |
22 if (s[0] == '\n') | 26 if (s[0] == '\n') |
102 iconv_close(i8859_1to8); | 106 iconv_close(i8859_1to8); |
103 iconv_close(i8toi8859_1); | 107 iconv_close(i8toi8859_1); |
104 } | 108 } |
105 | 109 |
106 | 110 |
107 //int utf16_write( FILE* stream, const void *buf, size_t count ) // write utf-8 or iso_8869-1 to stream after converting it to utf-16 | |
108 //{ | |
109 // | |
110 // //TODO: if anything big comes through here we are sunk, should do it | |
111 // //bit-by-bit, not one-big-gulp | |
112 // | |
113 // size_t inbytesleft, outbytesleft; | |
114 // char *inbuf, *outbuf; | |
115 // size_t icresult; | |
116 // size_t rl; | |
117 // | |
118 // //do we have enough buffer space? | |
119 // if( !wwbuf || nwwbuf < (count * 2 + 2) ) { | |
120 // wwbuf = F_REALLOC( wwbuf, count * 2 +2 ); | |
121 // | |
122 // nwwbuf = count * 2 + 2; | |
123 // } | |
124 // | |
125 // inbytesleft = count; outbytesleft = nwwbuf; | |
126 // inbuf = (char*)buf; outbuf = wwbuf; | |
127 // | |
128 //// fprintf(stderr, "X%s, %dX", (char*)buf, strlen( buf )); | |
129 //// fflush(stderr); | |
130 // | |
131 // if( (rl = strlen( buf ) + 1) != count ) { | |
132 // fprintf(stderr, "utf16_write(): reported buffer size (%d) does not match string length (%d)\n", | |
133 // count, | |
134 // rl); | |
135 // | |
136 // //hexdump( (char*)buf, 0, count, 1 ); | |
137 // | |
138 // raise( SIGSEGV ); | |
139 // inbytesleft = rl; | |
140 // } | |
141 // | |
142 //// fprintf(stderr, " attempting to convert:\n"); | |
143 //// hexdump( (char*)inbuf, 0, count, 1 ); | |
144 // | |
145 // icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); | |
146 // | |
147 //// fprintf(stderr, " converted:\n"); | |
148 //// hexdump( (char*)buf, 0, count, 1 ); | |
149 // | |
150 //// fprintf(stderr, " to:\n"); | |
151 //// hexdump( (char*)wwbuf, 0, nwwbuf, 1 ); | |
152 // | |
153 // if( (size_t)-1 == icresult ) { | |
154 // fprintf(stderr, "utf16_write(): iconv failure(%d): %s\n", errno, strerror( errno ) ); | |
155 // fprintf(stderr, " attempted to convert:\n"); | |
156 // hexdump( (char*)inbuf, 0, count, 1 ); | |
157 // | |
158 // fprintf(stderr, " result:\n"); | |
159 // hexdump( (char*)outbuf, 0, count, 1 ); | |
160 // | |
161 // fprintf(stderr, "I'm going to segfault now.\n"); | |
162 // raise( SIGSEGV ); | |
163 // exit(1); | |
164 // } | |
165 // | |
166 // if( inbytesleft > 0 ) { | |
167 // fprintf(stderr, "utf16_write(): iconv returned a short count.\n"); | |
168 // exit(1); | |
169 // } | |
170 // | |
171 // return fwrite( wwbuf, nwwbuf - outbytesleft - 2, 1, stream ); | |
172 //} | |
173 | |
174 //char *utf16buf = NULL; | |
175 //int utf16buf_len = 0; | |
176 // | |
177 //int utf16_fprintf( FILE* stream, const char *fmt, ... ) | |
178 //{ | |
179 // int result=0; | |
180 // va_list ap; | |
181 // | |
182 // if( utf16buf == NULL ) { | |
183 // utf16buf = (char*)F_MALLOC( SZ_MAX + 1 ); | |
184 // | |
185 // utf16buf_len = SZ_MAX + 1; | |
186 // } | |
187 // | |
188 // va_start( ap, fmt ); | |
189 // | |
190 // result = vsnprintf( utf16buf, utf16buf_len, fmt, ap ); | |
191 // | |
192 // if( result + 1 > utf16buf_len ) { //didn't have space, realloc() and try again | |
193 // fprintf(stderr, "utf16_fprintf(): buffer too small (%d), F_MALLOC(%d)\n", utf16buf_len, result); | |
194 // free( utf16buf ); | |
195 // utf16buf_len = result + 1; | |
196 // utf16buf = (char*)F_MALLOC( utf16buf_len ); | |
197 // | |
198 // result = vsnprintf( utf16buf, utf16buf_len, fmt, ap ); | |
199 // } | |
200 // | |
201 // | |
202 // //didn't have space...again...something weird is going on... | |
203 // ASSERT( result + 1 <= utf16buf_len, "utf16_fprintf(): Unpossible error!\n"); | |
204 // | |
205 // if( 1 != utf16_write( stream, utf16buf, result + 1 ) ) | |
206 // DIE( "Write error? -> %s or %s\n", strerror( errno ), uerr_str( uerr_get() ) ); | |
207 // | |
208 // return result; | |
209 //} | |
210 // | |
211 //int utf16to8( char *inbuf_o, char *outbuf_o, int length ) | |
212 //{ | |
213 // int inbytesleft = length; | |
214 // int outbytesleft = length; | |
215 // char *inbuf = inbuf_o; | |
216 // char *outbuf = outbuf_o; | |
217 // int rlen = -1, tlen; | |
218 // int icresult = -1; | |
219 // | |
220 // int i, strlen=-1; | |
221 // | |
222 // DEBUG( | |
223 // fprintf(stderr, " utf16to8(): attempting to convert:\n"); | |
224 // //hexdump( (char*)inbuf_o, 0, length, 1 ); | |
225 // fflush(stderr); | |
226 // ); | |
227 // | |
228 // for( i=0; i<length ; i+=2 ) { | |
229 // if( inbuf_o[i] == 0 && inbuf_o[i + 1] == 0 ) { | |
230 // //fprintf(stderr, "End of string found at: %d\n", i ); | |
231 // strlen = i; | |
232 // } | |
233 // } | |
234 // | |
235 // //hexdump( (char*)inbuf_o, 0, strlen, 1 ); | |
236 // | |
237 // if( -1 == strlen ) WARN("String is not zero-terminated."); | |
238 // | |
239 // //iconv does not like it when the inbytesleft > actual string length | |
240 // //enum: zero terminated, length valid | |
241 // // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case | |
242 // // zero terminated, length long | |
243 // // not zero terminated | |
244 // // TODO: MEMORY BUG HERE! | |
245 // for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) { | |
246 // if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){ | |
247 // rlen = tlen + 2; | |
248 // tlen = rlen; | |
249 // break; | |
250 // } | |
251 // if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n"); | |
252 // } | |
253 // | |
254 // if( rlen >= 0 ) | |
255 // icresult = iconv( i16to8, &inbuf, &rlen, &outbuf, &outbytesleft ); | |
256 // | |
257 // if( icresult == (size_t)-1 ) { | |
258 // fprintf(stderr, "utf16to8(): iconv failure(%d): %s\n", errno, strerror( errno ) ); | |
259 // fprintf(stderr, " attempted to convert:\n"); | |
260 // hexdump( (char*)inbuf_o, 0, length, 1 ); | |
261 // fprintf(stderr, " result:\n"); | |
262 // hexdump( (char*)outbuf_o, 0, length, 1 ); | |
263 // fprintf(stderr, " MyDirtyOut:\n"); | |
264 // for( i=0; i<length; i++) { | |
265 // if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] ); | |
266 // } | |
267 // | |
268 // fprintf( stderr, "\n" ); | |
269 // raise( SIGSEGV ); | |
270 // exit(1); | |
271 // } | |
272 // | |
273 // DEBUG( | |
274 // fprintf(stderr, " result:\n"); | |
275 // hexdump( (char*)outbuf_o, 0, length, 1 ); | |
276 // ) | |
277 // | |
278 // //fprintf(stderr, "utf16to8() returning %s\n", outbuf ); | |
279 // | |
280 // return icresult; | |
281 //} | |
282 // | |
283 | |
284 | |
285 int utf16_is_terminated(char *str, int length) | 111 int utf16_is_terminated(char *str, int length) |
286 { | 112 { |
287 VSTR_STATIC(errbuf, 100); | 113 VSTR_STATIC(errbuf, 100); |
288 int len = -1; | 114 int len = -1; |
289 int i; | 115 int i; |
293 } | 119 } |
294 } | 120 } |
295 | 121 |
296 if (-1 == len) { | 122 if (-1 == len) { |
297 vshexdump(errbuf, str, 0, length, 1); | 123 vshexdump(errbuf, str, 0, length, 1); |
298 WARN("String is not zero terminated (probably broken data from registry) %s.", errbuf->b); | 124 WARN(("String is not zero terminated (probably broken data from registry) %s.", errbuf->b)); |
299 } | 125 } |
300 | 126 |
301 return (-1 == len) ? 0 : 1; | 127 return (-1 == len) ? 0 : 1; |
302 } | 128 } |
303 | 129 |
329 dest->dlen = outbuf - dest->b; | 155 dest->dlen = outbuf - dest->b; |
330 vbgrow(dest, inbytesleft); | 156 vbgrow(dest, inbytesleft); |
331 } while ((size_t)-1 == icresult && E2BIG == errno); | 157 } while ((size_t)-1 == icresult && E2BIG == errno); |
332 | 158 |
333 if (0 != vb_utf8to16T(dumpster, dest->b, dest->dlen)) | 159 if (0 != vb_utf8to16T(dumpster, dest->b, dest->dlen)) |
334 DIE("Reverse conversion failed."); | 160 DIE(("Reverse conversion failed.")); |
335 | 161 |
336 if (icresult == (size_t)-1) { | 162 if (icresult == (size_t)-1) { |
337 //TODO: error | 163 //TODO: error |
338 //ERR_UNIX( errno, "vb_utf16to8():iconv failure: %s", strerror( errno ) ); | 164 //ERR_UNIX( errno, "vb_utf16to8():iconv failure: %s", strerror( errno ) ); |
339 unicode_init(); | 165 unicode_init(); |
371 char *inbuf = inbuf_o; | 197 char *inbuf = inbuf_o; |
372 char *outbuf = outbuf_o; | 198 char *outbuf = outbuf_o; |
373 size_t icresult = (size_t)-1; | 199 size_t icresult = (size_t)-1; |
374 char *stend; | 200 char *stend; |
375 | 201 |
376 DEBUG(fprintf(stderr, " utf8to16(): attempting to convert:\n"); | |
377 //hexdump( (char*)inbuf_o, 0, length, 1 ); | |
378 fflush(stderr);); | |
379 | |
380 stend = memchr(inbuf_o, '\0', iblen); | 202 stend = memchr(inbuf_o, '\0', iblen); |
381 ASSERT(NULL != stend, "utf8to16(): in string not zero terminated."); | 203 ASSERT(NULL != stend, "utf8to16(): in string not zero terminated."); |
382 | |
383 inbytesleft = (stend - inbuf_o + 1 < iblen) ? stend - inbuf_o + 1 : iblen; | 204 inbytesleft = (stend - inbuf_o + 1 < iblen) ? stend - inbuf_o + 1 : iblen; |
384 | |
385 //iconv does not like it when the inbytesleft > actual string length | |
386 //enum: zero terminated, length valid | |
387 // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case | |
388 // zero terminated, length long | |
389 // not zero terminated | |
390 // TODO: MEMORY BUG HERE! | |
391 // | |
392 /* | |
393 for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) { | |
394 if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){ | |
395 rlen = tlen + 2; | |
396 tlen = rlen; | |
397 break; | |
398 } | |
399 if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n"); | |
400 } | |
401 */ | |
402 | |
403 //if( rlen >= 0 ) | |
404 icresult = iconv(i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft); | 205 icresult = iconv(i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft); |
405 | 206 |
406 if (icresult == (size_t)-1) { | 207 if (icresult == (size_t)-1) { |
407 DIE("iconv failure(%d): %s\n", errno, strerror(errno)); | 208 DIE(("iconv failure(%d): %s\n", errno, strerror(errno))); |
408 //fprintf(stderr, " attempted to convert:\n"); | 209 } |
409 //hexdump( (char*)inbuf_o, 0, iblen, 1 ); | |
410 //fprintf(stderr, " result:\n"); | |
411 //hexdump( (char*)outbuf_o, 0, oblen, 1 ); | |
412 //fprintf(stderr, " MyDirtyOut:\n"); | |
413 // for( i=0; i<iblen; i++) { | |
414 // if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] ); | |
415 // } | |
416 // | |
417 // fprintf( stderr, "\n" ); | |
418 // raise( SIGSEGV ); | |
419 // exit(1); | |
420 } | |
421 // DEBUG( | |
422 // fprintf(stderr, " result:\n"); | |
423 // hexdump( (char*)outbuf_o, 0, oblen, 1 ); | |
424 // ) | |
425 | |
426 //fprintf(stderr, "utf8to16() returning %s\n", outbuf ); | |
427 | |
428 //TODO: error | |
429 DEBUG( | |
430 if (icresult) | |
431 printf("Uhhhh...utf8to16() returning icresult == %d\n", icresult); | |
432 ); | |
433 | |
434 if (icresult > (size_t)INT_MAX) { | 210 if (icresult > (size_t)INT_MAX) { |
435 return (-1); | 211 return (-1); |
436 } | 212 } |
437 return (int) icresult; | 213 return (int) icresult; |
438 } | 214 } |
459 bout->dlen = outbuf - bout->b; | 235 bout->dlen = outbuf - bout->b; |
460 vbgrow(bout, 20); | 236 vbgrow(bout, 20); |
461 } while ((size_t)-1 == icresult && E2BIG == errno); | 237 } while ((size_t)-1 == icresult && E2BIG == errno); |
462 | 238 |
463 if (icresult == (size_t)-1) { | 239 if (icresult == (size_t)-1) { |
464 WARN("iconv failure: %s", strerror(errno)); | 240 WARN(("iconv failure: %s", strerror(errno))); |
465 //ERR_UNIX( errno, "vb_utf8to16():iconv failure: %s", strerror( errno ) ); | |
466 unicode_init(); | 241 unicode_init(); |
467 return -1; | 242 return -1; |
468 /* | 243 } |
469 fprintf(stderr, "vb_utf8to16(): iconv failure(%d == %d?): %s\n", errno, E2BIG, strerror( errno ) ); | |
470 fprintf(stderr, " attempted to convert:\n"); | |
471 hexdump( (char*)cin, 0, inlen, 1 ); | |
472 fprintf(stderr, " result:\n"); | |
473 hexdump( (char*)bout->b, 0, bout->dlen, 1 ); | |
474 fprintf(stderr, " MyDirtyOut:\n"); | |
475 for( i=0; i<inlen; i++) { | |
476 if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] ); | |
477 } | |
478 | |
479 fprintf( stderr, "\n" ); | |
480 raise( SIGSEGV ); | |
481 exit(1); | |
482 */ | |
483 } | |
484 DEBUG( | |
485 if (icresult) | |
486 printf("Uhhhh...vb_utf8to16() returning icresult == %d\n", icresult); | |
487 ); | |
488 | |
489 if (icresult > (size_t) INT_MAX) { | 244 if (icresult > (size_t) INT_MAX) { |
490 return (-1); | 245 return (-1); |
491 } | 246 } |
492 return icresult; | 247 return icresult; |
493 } | 248 } |
517 } | 272 } |
518 | 273 |
519 | 274 |
520 vbuf *vballoc(size_t len) | 275 vbuf *vballoc(size_t len) |
521 { | 276 { |
522 struct varbuf *result; | 277 struct varbuf *result = malloc(sizeof(struct varbuf)); |
523 | 278 if (result) { |
524 result = F_MALLOC(sizeof(struct varbuf)); | 279 result->dlen = 0; |
525 | 280 result->blen = 0; |
526 result->dlen = 0; | 281 result->buf = NULL; |
527 result->blen = 0; | 282 vbresize(result, len); |
528 result->buf = NULL; | 283 } |
529 | 284 else DIE(("malloc() failure")); |
530 vbresize(result, len); | |
531 | |
532 return result; | 285 return result; |
533 | |
534 } | 286 } |
535 | 287 |
536 | 288 |
537 void vbcheck(vbuf * vb) | 289 void vbcheck(vbuf * vb) |
538 { | 290 { |
563 if (vb->blen >= len) { | 315 if (vb->blen >= len) { |
564 vb->b = vb->buf; | 316 vb->b = vb->buf; |
565 return; | 317 return; |
566 } | 318 } |
567 | 319 |
568 vb->buf = F_REALLOC(vb->buf, len); | 320 vb->buf = realloc(vb->buf, len); |
569 vb->b = vb->buf; | 321 vb->b = vb->buf; |
570 vb->blen = len; | 322 vb->blen = len; |
571 } | 323 } |
572 | 324 |
573 | 325 |
574 size_t vbavail(vbuf * vb) | 326 size_t vbavail(vbuf * vb) |
602 } | 354 } |
603 | 355 |
604 if (vb->dlen + len > vb->blen) { | 356 if (vb->dlen + len > vb->blen) { |
605 if (vb->dlen + len < vb->blen * 1.5) | 357 if (vb->dlen + len < vb->blen * 1.5) |
606 len = vb->blen * 1.5; | 358 len = vb->blen * 1.5; |
607 char *nb = F_MALLOC(vb->blen + len); | 359 char *nb = malloc(vb->blen + len); |
608 //printf("vbgrow() got %p back from malloc(%d)\n", nb, vb->blen + len); | 360 if (!nb) DIE(("malloc() failure")); |
609 vb->blen = vb->blen + len; | 361 vb->blen = vb->blen + len; |
610 memcpy(nb, vb->b, vb->dlen); | 362 memcpy(nb, vb->b, vb->dlen); |
611 | 363 |
612 //printf("vbgrow() I am going to free %p\n", vb->buf ); | |
613 free(vb->buf); | 364 free(vb->buf); |
614 vb->buf = nb; | 365 vb->buf = nb; |
615 vb->b = vb->buf; | 366 vb->b = vb->buf; |
616 } else { | 367 } else { |
617 if (vb->b != vb->buf) | 368 if (vb->b != vb->buf) |
960 v->b[off] = '\0'; | 711 v->b[off] = '\0'; |
961 v->dlen = off + 1; | 712 v->dlen = off + 1; |
962 } | 713 } |
963 | 714 |
964 | 715 |
965 // TODO: not sure how useful this stuff is here | |
966 int fmyinput(char *prmpt, char *ibuf, int maxlen) | |
967 { /* get user input */ | |
968 printf("%s", prmpt); | |
969 | |
970 fgets(ibuf, maxlen + 1, stdin); | |
971 | |
972 ibuf[strlen(ibuf) - 1] = 0; | |
973 | |
974 return (strlen(ibuf)); | |
975 } | |
976 | |
977 | |
978 // String formatting and output to FILE *stream or just stdout, etc | |
979 // TODO: a lot of old, unused stuff in here | |
980 void vswinhex8(vstr * vs, unsigned char *hbuf, int start, int stop, int loff) // Produce regedit-style hex output */ | |
981 { | |
982 int i; | |
983 int lineflag = 0; | |
984 | |
985 for (i = start; i < stop; i++) { | |
986 loff += vscatprintf(vs, "%02x", hbuf[i]); | |
987 if (i < stop - 1) { | |
988 loff += vscatprintf(vs, ","); | |
989 switch (lineflag) { | |
990 case 0: | |
991 if (loff >= 77) { | |
992 lineflag = 1; | |
993 loff = 0; | |
994 vscatprintf(vs, "\\%s ", STUPID_CR); | |
995 } | |
996 break; | |
997 case 1: | |
998 if (loff >= 75) { | |
999 loff = 0; | |
1000 vscatprintf(vs, "\\%s ", STUPID_CR); | |
1001 } | |
1002 break; | |
1003 } | |
1004 } | |
1005 } | |
1006 } |