← Commit list

9499d987b9

Patrick Monnerat
Patrick Monnerat
2026-08-28
SUCCESS Duration: 422s

Subject

os400: rewrite upper ebcdic wrappers using dynbuf

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

projects/OS400/ccsidcurl.c+339 -320
@@ -34,6 +34,7 @@
#pragma enum(int)
+#include "curl_setup.h"
#include "curl.h"
#include "mprintf.h"
#include "slist.h"
@@ -41,12 +42,13 @@
#include "url.h"
#include "setopt.h"
#include "getinfo.h"
+#include "curlx/dynbuf.h"
#include "ccsidcurl.h"
#include "os400sys.h"
#ifndef SIZE_MAX
-#define SIZE_MAX ((size_t)~0) /* Is unsigned on OS/400. */
+#define SIZE_MAX ((size_t) ~0)
#endif
#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */
@@ -56,15 +58,23 @@
#define ALLOC_GRANULE 8 /* Alloc. granule for curl_formadd_ccsid(). */
+
+/* A string terminator that works for all CCSIDs. */
+static const char universal_terminator[] = {0, 0, 0, 0};
+
+/* Freeing const pointers more easily. */
+#define untyped_free(p) curlx_free(CURL_UNCONST(p))
+
+
static void makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
{
- /**
- *** Convert a CCSID to the corresponding IBM iconv_open() character
- *** code identifier.
- *** This code is specific to the OS400 implementation of the iconv library.
- *** CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
- *** CCSID 0 is interpreted by the OS400 as the job's CCSID.
- **/
+ /*
+ * Convert a CCSID to the corresponding IBM iconv_open() character
+ * code identifier.
+ * This code is specific to the OS400 implementation of the iconv library.
+ * CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
+ * CCSID 0 is interpreted by the OS400 as the job's CCSID.
+ */
ccsid &= 0xFFFF;
@@ -81,12 +91,12 @@ static iconv_t iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin,
char fromcode[ICONV_ID_SIZE];
char tocode[ICONV_ID_SIZE];
- /**
- *** Like iconv_open(), but character codes are given as CCSIDs.
- *** If `cstr' is non-zero, conversion is set up to stop whenever a
- *** null character is encountered.
- *** See iconv_open() IBM description in "National Language Support API".
- **/
+ /*
+ * Like iconv_open(), but character codes are given as CCSIDs.
+ * If `cstr' is non-zero, conversion is set up to stop whenever a
+ * null character is encountered.
+ * See iconv_open() IBM description in "National Language Support API".
+ */
makeOS400IconvCode(fromcode, ccsidin);
makeOS400IconvCode(tocode, ccsidout);
@@ -98,44 +108,35 @@ static iconv_t iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin,
return iconv_open(tocode, fromcode);
}
-static int convert(char *d, size_t dlen, int dccsid, const char *s, int slen,
- int sccsid)
+static int convert(char *d, size_t dlen, const char *s, size_t slen,
+ unsigned int ccsidin, unsigned int ccsidout)
{
int i;
iconv_t cd;
size_t lslen;
- /**
- *** Convert `sccsid'-coded `slen'-data bytes at `s' into `dccsid'-coded
- *** data stored in the `dlen'-byte buffer at `d'.
- *** If `slen' < 0, source string is null-terminated.
- *** CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
- *** Return the converted destination byte count, or -1 if error.
- **/
+ /*
+ * Convert `ccsidin'-coded `slen'-data bytes at `s' into `ccsidout'-coded
+ * data stored in the `dlen'-byte buffer at `d'.
+ * If `slen' is CURL_ZERO_TERMINATED, let iconv() detect the end of
+ * input string.
+ * CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
+ * Return the converted destination byte count, or -1 if error.
+ */
- if(sccsid == 65535)
- sccsid = ASCII_CCSID;
+ if(ccsidin == 65535)
+ ccsidin = ASCII_CCSID;
- if(dccsid == 65535)
- dccsid = ASCII_CCSID;
-
- if(sccsid == dccsid) {
- lslen = slen >= 0 ? slen : strlen(s) + 1;
- i = lslen < dlen ? lslen : dlen;
-
- if(s != d && i > 0)
- memcpy(d, s, i);
-
- return i;
- }
+ if(ccsidout == 65535)
+ ccsidout = ASCII_CCSID;
- if(slen < 0) {
+ if(slen == CURL_ZERO_TERMINATED) {
lslen = 0;
- cd = iconv_open_CCSID(dccsid, sccsid, 1);
+ cd = iconv_open_CCSID(ccsidout, ccsidin, 1);
}
else {
lslen = (size_t)slen;
- cd = iconv_open_CCSID(dccsid, sccsid, 0);
+ cd = iconv_open_CCSID(ccsidout, ccsidin, 0);
}
if(ICONV_OPEN_ERROR(cd))
@@ -143,7 +144,7 @@ static int convert(char *d, size_t dlen, int dccsid, const char *s, int slen,
i = dlen;
- if((int)iconv(cd, (char **)&s, &lslen, &d, &dlen) < 0)
+ if((int)iconv(cd, (char **) &s, &lslen, &d, &dlen) < 0)
i = -1;
else
i -= dlen;
@@ -152,75 +153,116 @@ static int convert(char *d, size_t dlen, int dccsid, const char *s, int slen,
return i;
}
-static char *dynconvert(int dccsid, const char *s, int slen, int sccsid,
- int *olen)
+static CURLcode dyn_addn_CCSID(struct dynbuf *db,
+ const void *mem, size_t len,
+ unsigned int ccsidin, unsigned int ccsidout)
{
- char *d;
- char *cp;
+ iconv_t cd;
size_t dlen;
- int l;
- static const char nullbyte = 0;
+ CURLcode result = CURLE_OK;
+ char buffer[128];
- /* Like convert, but the destination is allocated and returned. */
+ if(ccsidin == 65535)
+ ccsidin = ASCII_CCSID;
- dlen = (size_t)(slen < 0 ? strlen(s) : slen) + 1;
- dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */
- d = malloc(dlen);
+ if(ccsidout == 65535)
+ ccsidout = ASCII_CCSID;
- if(!d)
- return (char *)NULL;
+ cd = iconv_open_CCSID(ccsidout, ccsidin, len == CURL_ZERO_TERMINATED);
- l = convert(d, dlen, dccsid, s, slen, sccsid);
-
- if(l < 0) {
- free(d);
- return (char *)NULL;
+ if(ICONV_OPEN_ERROR(cd)) {
+ curlx_dyn_free(db);
+ return CURLE_NOT_BUILT_IN;
}
- if(slen < 0) {
- /* Need to null-terminate even when source length is given.
- Since destination code size is unknown, use a conversion to generate
- terminator. */
-
- int l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID);
+ while(len) {
+ size_t dummylen = 0;
+ char *dptr = buffer;
+ int err = 0;
+
+ dlen = sizeof(buffer);
+ if((int)iconv(cd, (char **) &mem,
+ len == CURL_ZERO_TERMINATED ? &dummylen : &len,
+ &dptr, &dlen) < 0) {
+ /* !checksrc! disable ERRNOVAR 1 */
+ err = errno;
+ }
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ switch(err) {
+ case 0:
+ case E2BIG:
+ break;
+ case ENOMEM:
+ result = CURLE_OUT_OF_MEMORY;
+ FALLTHROUGH();
+ default:
+ curlx_dyn_free(db);
+ iconv_close(cd);
+ return result;
+ }
- if(l2 < 0) {
- free(d);
- return (char *)NULL;
+ result = curlx_dyn_addn(db, (const void *)buffer, dptr - buffer);
+ if(result) {
+ iconv_close(cd);
+ return result;
}
- l += l2;
+ if(!err)
+ break;
}
- if((size_t)l < dlen) {
- cp = realloc(d, l); /* Shorten to minimum needed. */
+ iconv_close(cd);
+ dlen = curlx_dyn_len(db);
+
+ if(len == CURL_ZERO_TERMINATED) {
+ /* The null terminator has been converted AND counted as a character.
+ * Measure it by an additional conversion and drop it. */
+ int tlen = convert(buffer, sizeof(buffer), universal_terminator, 1,
+ ASCII_CCSID, ccsidout);
- if(cp)
- d = cp;
+ if(tlen < 0 || tlen > dlen) {
+ curlx_dyn_free(db);
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ dlen -= tlen;
+ }
+ else {
+ /* Make sure the string is followed by an universal terminator. */
+ result = curlx_dyn_addn(db, universal_terminator,
+ sizeof(universal_terminator));
}
- if(olen)
- *olen = l;
- return d;
+ /* Restore the real string length. */
+ if(!result)
+ result = curlx_dyn_setlen(db, dlen);
+
+ return result;
}
-static struct curl_slist *slist_convert(int dccsid, struct curl_slist *from,
- int sccsid)
+static struct curl_slist *slist_convert(struct curl_slist *from,
+ unsigned int ccsidin,
+ unsigned int ccsidout)
{
struct curl_slist *to = (struct curl_slist *)NULL;
+ struct dynbuf db;
+ size_t plen;
+
+ curlx_dyn_init(&db, MAX_CONV_EXPANSION * CURL_MAX_HTTP_HEADER);
for(; from; from = from->next) {
struct curl_slist *nl;
- char *cp = dynconvert(dccsid, from->data, -1, sccsid, NULL);
+ char *s;
- if(!cp) {
+ if(dyn_addn_CCSID(&db, from->data, CURL_ZERO_TERMINATED,
+ ccsidin, ccsidout)) {
curl_slist_free_all(to);
- return (struct curl_slist *)NULL;
+ return NULL;
}
- nl = Curl_slist_append_nodup(to, cp);
+ s = curlx_dyn_take(&db, &plen);
+ nl = Curl_slist_append_nodup(to, s);
if(!nl) {
curl_slist_free_all(to);
- free(cp);
+ free(s);
return NULL;
}
to = nl;
@@ -231,35 +273,56 @@ static struct curl_slist *slist_convert(int dccsid, struct curl_slist *from,
static char *keyed_string(localkey_t key, const char *ascii,
unsigned int ccsid)
{
- int i;
+ size_t len;
char *ebcdic;
+ struct dynbuf db;
if(!ascii)
- return (char *)NULL;
-
- i = MAX_CONV_EXPANSION * (strlen(ascii) + 1);
+ return NULL;
- ebcdic = Curl_thread_buffer(key, i);
- if(!ebcdic)
- return ebcdic;
-
- if(convert(ebcdic, i, ccsid, ascii, -1, ASCII_CCSID) < 0)
- return (char *)NULL;
+ curlx_dyn_init(&db, MAX_CONV_EXPANSION * CURL_MAX_INPUT_LENGTH);
+ if(dyn_addn_CCSID(&db, ascii, CURL_ZERO_TERMINATED, ASCII_CCSID, ccsid))
+ return NULL;
+ len = curlx_dyn_len(&db);
+ ebcdic = Curl_thread_buffer(key, len + sizeof(universal_terminator));
+ if(ebcdic) {
+ memcpy(ebcdic, curlx_dyn_ptr(&db), len);
+ memcpy(ebcdic + len, universal_terminator, sizeof(universal_terminator));
+ }
+ curlx_dyn_free(&db);
return ebcdic;
}
-const char *curl_to_ccsid(const char *s, unsigned int ccsid)
+const char *curl_to_ccsid(const char *string, unsigned int ccsid)
{
- if(s)
- s = dynconvert(ccsid, s, -1, ASCII_CCSID, NULL);
+ char *s = NULL;
+
+ if(string) {
+ struct dynbuf db;
+ size_t len;
+
+ curlx_dyn_init(&db, MAX_CONV_EXPANSION * CURL_MAX_INPUT_LENGTH);
+ dyn_addn_CCSID(&db, string, CURL_ZERO_TERMINATED, ASCII_CCSID, ccsid);
+ s = curlx_dyn_take(&db, &len);
+ }
+
return s;
}
-const char *curl_from_ccsid(const char *s, unsigned int ccsid)
+const char *curl_from_ccsid(const char *string, unsigned int ccsid)
{
- if(s)
- s = dynconvert(ASCII_CCSID, s, -1, ccsid, NULL);
+ char *s = NULL;
+
+ if(string) {
+ struct dynbuf db;
+ size_t len;
+
+ curlx_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
+ dyn_addn_CCSID(&db, string, CURL_ZERO_TERMINATED, ccsid, ASCII_CCSID);
+ s = curlx_dyn_take(&db, &len);
+ }
+
return s;
}
@@ -269,103 +332,99 @@ char *curl_version_ccsid(unsigned int ccsid)
}
char *curl_easy_escape_ccsid(CURL *handle, const char *string, int length,
- unsigned int sccsid, unsigned int dccsid)
+ unsigned int ccsidin, unsigned int ccsidout)
{
- char *s;
+ struct dynbuf db;
char *d;
+ size_t len;
- if(!string) {
- /* !checksrc! disable ERRNOVAR 1 */
- errno = EINVAL;
- return (char *)NULL;
- }
+ if(!string)
+ return NULL;
- s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid, NULL);
+ curlx_dyn_init(&db, MAX_CONV_EXPANSION * CURL_MAX_INPUT_LENGTH);
- if(!s)
- return (char *)NULL;
+ if(dyn_addn_CCSID(&db, string, length ? length : CURL_ZERO_TERMINATED,
+ ccsidin, ASCII_CCSID))
+ return NULL;
- d = curl_easy_escape(handle, s, 0);
- free(s);
+ d = curl_easy_escape(handle, curlx_dyn_ptr(&db), curlx_dyn_len(&db));
+ curlx_dyn_free(&db);
if(!d)
- return (char *)NULL;
+ return NULL;
- s = dynconvert(dccsid, d, -1, ASCII_CCSID, NULL);
- free(d);
- return s;
+ dyn_addn_CCSID(&db, d, CURL_ZERO_TERMINATED, ASCII_CCSID, ccsidout);
+ untyped_free(d);
+ return curlx_dyn_take(&db, &len);
}
char *curl_easy_unescape_ccsid(CURL *handle, const char *string, int length,
- int *outlength, unsigned int sccsid,
- unsigned int dccsid)
+ int *outlength,
+ unsigned int ccsidin, unsigned int ccsidout)
{
- char *s;
+ struct dynbuf db;
char *d;
+ size_t len;
- if(!string) {
- /* !checksrc! disable ERRNOVAR 1 */
- errno = EINVAL;
- return (char *)NULL;
- }
+ if(!string)
+ return NULL;
- s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid, NULL);
+ curlx_dyn_init(&db, MAX_CONV_EXPANSION * CURL_MAX_INPUT_LENGTH);
- if(!s)
- return (char *)NULL;
+ if(dyn_addn_CCSID(&db, string, length ? length : CURL_ZERO_TERMINATED,
+ ccsidin, ASCII_CCSID))
+ return NULL;
- d = curl_easy_unescape(handle, s, 0, outlength);
- free(s);
+ d = curl_easy_unescape(handle,
+ curlx_dyn_ptr(&db), curlx_dyn_len(&db), outlength);
+ curlx_dyn_free(&db);
if(!d)
- return (char *)NULL;
+ return NULL;
- s = dynconvert(dccsid, d, -1, ASCII_CCSID, NULL);
- free(d);
-
- if(s && outlength)
- *outlength = strlen(s);
-
- return s;
+ if(!dyn_addn_CCSID(&db, d, CURL_ZERO_TERMINATED, ASCII_CCSID, ccsidout))
+ if(outlength)
+ *outlength = curlx_dyn_len(&db);
+ untyped_free(d);
+ return curlx_dyn_take(&db, &len);
}
struct curl_slist *curl_slist_append_ccsid(struct curl_slist *list,
const char *data,
unsigned int ccsid)
{
- char *s;
-
- s = (char *)NULL;
+ const char *s;
if(!data)
return curl_slist_append(list, data);
- s = dynconvert(ASCII_CCSID, data, -1, ccsid, NULL);
+ s = curl_from_ccsid(data, ccsid);
if(!s)
- return (struct curl_slist *)NULL;
+ return NULL;
- list = curl_slist_append(list, s);
- free(s);
+ list = Curl_slist_append_nodup(list, s);
+ if(!list)
+ untyped_free(s);
return list;
}
time_t curl_getdate_ccsid(const char *p, const time_t *unused,
unsigned int ccsid)
{
- char *s;
+ const char *s;
time_t t;
if(!p)
return curl_getdate(p, unused);
- s = dynconvert(ASCII_CCSID, p, -1, ccsid, NULL);
+ s = curl_from_ccsid(p, ccsid);
if(!s)
- return (time_t)-1;
+ return (time_t) -1;
t = curl_getdate(s, unused);
- free(s);
+ untyped_free(s);
return t;
}
@@ -378,7 +437,8 @@ static int convert_version_info_string(const char **stringp, char **bufp,
Return 0 if ok, else -1. */
if(*stringp) {
- int l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID);
+ int l = convert(*bufp, *left, *stringp, CURL_ZERO_TERMINATED,
+ ASCII_CCSID, ccsid);
if(l <= 0)
return -1;
@@ -432,7 +492,7 @@ curl_version_info_data *curl_version_info_ccsid(CURLversion stamp,
/* If caller has been compiled with a newer version, error. */
if(stamp > CURLVERSION_NOW)
- return (curl_version_info_data *)NULL;
+ return NULL;
p = curl_version_info(stamp);
@@ -469,11 +529,11 @@ curl_version_info_data *curl_version_info_ccsid(CURLversion stamp,
sizeof(*id));
if(!id || !cp)
- return (curl_version_info_data *)NULL;
+ return NULL;
/* Copy data and convert strings. */
- memcpy((char *)id, (char *)p, sizeof(*p));
+ memcpy(id, p, sizeof(*p));
if(id->protocols) {
i = nproto * sizeof(id->protocols[0]);
@@ -485,14 +545,14 @@ curl_version_info_data *curl_version_info_ccsid(CURLversion stamp,
for(i = 0; id->protocols[i]; i++)
if(convert_version_info_string(((const char **)id->protocols) + i,
- &cp, &n, ccsid))
- return (curl_version_info_data *)NULL;
+ &cp, &n, ccsid))
+ return NULL;
}
for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) {
cpp = (const char **)((char *)p + charfields[i]);
if(*cpp && convert_version_info_string(cpp, &cp, &n, ccsid))
- return (curl_version_info_data *)NULL;
+ return NULL;
}
return id;
@@ -527,9 +587,9 @@ void curl_certinfo_free_all(struct curl_certinfo *info)
for(i = 0; i < info->num_of_certs; i++)
curl_slist_free_all(info->certinfo[i]);
- free((char *)info->certinfo);
+ untyped_free(info->certinfo);
}
- free((char *)info);
+ untyped_free(info);
}
}
@@ -550,7 +610,7 @@ CURLcode curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
if(result == CURLE_OK) {
unsigned int ccsid;
- char **cpp;
+ const char **cpp;
struct curl_slist **slp;
struct curl_certinfo *cipf;
struct curl_certinfo *cipt;
@@ -559,13 +619,15 @@ CURLcode curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
case CURLINFO_STRING:
ccsid = va_arg(arg, unsigned int);
- cpp = (char **)paramp;
+ cpp = (const char **)paramp;
if(*cpp) {
- *cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID, NULL);
+ const char *s = curl_to_ccsid(*cpp, ccsid);
- if(!*cpp)
+ if(!s)
result = CURLE_OUT_OF_MEMORY;
+ else
+ *cpp = s;
}
break;
@@ -576,12 +638,12 @@ CURLcode curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
case CURLINFO_CERTINFO:
cipf = *(struct curl_certinfo **)paramp;
if(cipf) {
- cipt = malloc(sizeof(*cipt));
+ cipt = curlx_malloc(sizeof(*cipt));
if(!cipt)
result = CURLE_OUT_OF_MEMORY;
else {
- cipt->certinfo = calloc(cipf->num_of_certs + 1,
- sizeof(struct curl_slist *));
+ cipt->certinfo = curlx_calloc(cipf->num_of_certs + 1,
+ sizeof(struct curl_slist *));
if(!cipt->certinfo)
result = CURLE_OUT_OF_MEMORY;
else {
@@ -589,19 +651,20 @@ CURLcode curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
cipt->num_of_certs = cipf->num_of_certs;
for(i = 0; i < cipf->num_of_certs; i++)
- if(cipf->certinfo[i])
- if(!(cipt->certinfo[i] = slist_convert(ccsid,
- cipf->certinfo[i],
- ASCII_CCSID))) {
+ if(cipf->certinfo[i]) {
+ cipt->certinfo[i] = slist_convert(cipf->certinfo[i],
+ ASCII_CCSID, ccsid);
+ if(!cipt->certinfo[i]) {
result = CURLE_OUT_OF_MEMORY;
break;
}
+ }
}
}
if(result != CURLE_OK) {
curl_certinfo_free_all(cipt);
- cipt = (struct curl_certinfo *)NULL;
+ cipt = NULL;
}
*(struct curl_certinfo **)paramp = cipt;
@@ -617,7 +680,7 @@ CURLcode curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
default:
slp = (struct curl_slist **)paramp;
if(*slp) {
- *slp = slist_convert(ccsid, *slp, ASCII_CCSID);
+ *slp = slist_convert(*slp, ASCII_CCSID, ccsid);
if(!*slp)
result = CURLE_OUT_OF_MEMORY;
}
@@ -654,50 +717,36 @@ static void Curl_formadd_release_local(struct curl_forms *forms, int nargs,
if(nargs != skip)
if(Curl_is_formadd_string(forms[nargs].option))
if(forms[nargs].value)
- free((char *)forms[nargs].value);
+ untyped_free(forms[nargs].value);
- free((char *)forms);
+ untyped_free(forms);
}
static int Curl_formadd_convert(struct curl_forms *forms, int formx,
int lengthx, unsigned int ccsid)
{
- int l;
+ size_t len = CURL_ZERO_TERMINATED;
char *cp;
- char *cp2;
+ struct dynbuf db;
if(formx < 0 || !forms[formx].value)
return 0;
- if(lengthx >= 0)
- l = (int)forms[lengthx].value;
- else
- l = strlen(forms[formx].value) + 1;
-
- cp = malloc(MAX_CONV_EXPANSION * l);
-
- if(!cp)
- return -1;
+ curlx_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
- l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID, forms[formx].value, l,
- ccsid);
+ if(lengthx >= 0)
+ len = (size_t)forms[lengthx].value;
- if(l < 0) {
- free(cp);
+ if(dyn_addn_CCSID(&db, forms[formx].value, len, ccsid, ASCII_CCSID))
return -1;
- }
-
- cp2 = realloc(cp, l); /* Shorten buffer to the string size. */
-
- if(cp2)
- cp = cp2;
+ cp = curlx_dyn_take(&db, &len);
forms[formx].value = cp;
if(lengthx >= 0)
- forms[lengthx].value = (char *)l; /* Update length after conversion. */
+ forms[lengthx].value = (char *)len; /* Update length after conversion. */
- return l;
+ return len;
}
CURLFORMcode curl_formadd_ccsid(struct curl_httppost **httppost,
@@ -738,7 +787,7 @@ CURLFORMcode curl_formadd_ccsid(struct curl_httppost **httppost,
/* Allocate the local curl_forms array. */
lformlen = ALLOC_GRANULE;
- lforms = malloc(lformlen * sizeof(*lforms));
+ lforms = curlx_malloc(lformlen * sizeof(*lforms));
if(!lforms)
return CURL_FORMADD_MEMORY;
@@ -752,7 +801,7 @@ CURLFORMcode curl_formadd_ccsid(struct curl_httppost **httppost,
lengthx = -1;
namex = -1;
namelengthx = -1;
- forms = (struct curl_forms *)NULL;
+ forms = NULL;
va_start(arg, last_post);
for(;;) {
@@ -760,7 +809,7 @@ CURLFORMcode curl_formadd_ccsid(struct curl_httppost **httppost,
if(nargs >= lformlen) {
lformlen += ALLOC_GRANULE;
- tforms = realloc(lforms, lformlen * sizeof(*lforms));
+ tforms = curlx_realloc(lforms, lformlen * sizeof(*lforms));
if(!tforms) {
result = CURL_FORMADD_MEMORY;
@@ -793,7 +842,7 @@ CURLFORMcode curl_formadd_ccsid(struct curl_httppost **httppost,
switch(option) {
case CURLFORM_END:
- forms = (struct curl_forms *)NULL; /* Leave array mode. */
+ forms = NULL; /* Leave array mode. */
continue;
case CURLFORM_ARRAY:
@@ -977,34 +1026,27 @@ struct cfcdata {
unsigned int ccsid;
};
-static size_t Curl_formget_callback_ccsid(void *arg, const char *buf,
- size_t len)
+static size_t formget_callback_ccsid(void *arg, const char *buf, size_t len)
{
struct cfcdata *p;
- char *b;
- int l;
+ size_t olen;
size_t ret;
+ struct dynbuf db;
p = (struct cfcdata *)arg;
if((long)len <= 0)
- return (*p->append)(p->arg, buf, len);
-
- b = malloc(MAX_CONV_EXPANSION * len);
+ return p->append(p->arg, buf, len);
- if(!b)
- return (size_t)-1;
+ curlx_dyn_init(&db, MAX_CONV_EXPANSION * CURL_MAX_INPUT_LENGTH);
- l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID);
+ if(dyn_addn_CCSID(&db, buf, len, ASCII_CCSID, p->ccsid))
+ return (size_t) -1;
- if(l < 0) {
- free(b);
- return (size_t)-1;
- }
-
- ret = (*p->append)(p->arg, b, l);
- free(b);
- return ret == l ? len : -1;
+ olen = curlx_dyn_len(&db);
+ ret = p->append(p->arg, curlx_dyn_ptr(&db), olen);
+ curlx_dyn_free(&db);
+ return ret == olen ? len : -1;
}
int curl_formget_ccsid(struct curl_httppost *form, void *arg,
@@ -1015,19 +1057,21 @@ int curl_formget_ccsid(struct curl_httppost *form, void *arg,
lcfc.append = append;
lcfc.arg = arg;
lcfc.ccsid = ccsid;
- return curl_formget(form, (void *)&lcfc, Curl_formget_callback_ccsid);
+ return curl_formget(form, (void *) &lcfc, formget_callback_ccsid);
}
CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
{
CURLcode result;
va_list arg;
- char *s;
- char *cp = NULL;
+ const char *s;
unsigned int ccsid;
+ struct dynbuf db;
curl_off_t pfsize;
+ size_t len;
struct Curl_easy *data = curl;
+ curlx_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
va_start(arg, tag);
switch(tag) {
@@ -1131,11 +1175,11 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
case CURLOPT_USERPWD:
case CURLOPT_XOAUTH2_BEARER:
/* END TRANSLATABLE STRING OPTIONS */
- s = va_arg(arg, char *);
+ s = va_arg(arg, const char *);
ccsid = va_arg(arg, unsigned int);
if(s) {
- s = dynconvert(ASCII_CCSID, s, -1, ccsid, NULL);
+ s = curl_from_ccsid(s, ccsid);
if(!s) {
result = CURLE_OUT_OF_MEMORY;
@@ -1144,14 +1188,14 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
}
result = curl_easy_setopt(curl, tag, s);
- free(s);
+ untyped_free(s);
break;
case CURLOPT_COPYPOSTFIELDS:
/* Special case: byte count may have been given by CURLOPT_POSTFIELDSIZE
prior to this call. In this case, convert the given byte count and
replace the length according to the conversion result. */
- s = va_arg(arg, char *);
+ s = va_arg(arg, const char *);
ccsid = va_arg(arg, unsigned int);
pfsize = data->set.postfieldsize;
@@ -1161,51 +1205,33 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
break;
}
- if(pfsize == -1) {
- /* Data is null-terminated. */
- s = dynconvert(ASCII_CCSID, s, -1, ccsid, NULL);
-
- if(!s) {
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
- }
+ if(pfsize == -1)
+ result = dyn_addn_CCSID(&db, s, CURL_ZERO_TERMINATED,
+ ccsid, ASCII_CCSID);
else {
/* Data length specified. */
- size_t len;
-
- if(pfsize < 0 || pfsize > SIZE_MAX) {
+ if(pfsize < 0 || pfsize > SIZE_MAX)
result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- len = pfsize;
- pfsize = len * MAX_CONV_EXPANSION;
-
- if(pfsize > SIZE_MAX)
- pfsize = SIZE_MAX;
-
- cp = malloc(pfsize);
+ else
+ result = dyn_addn_CCSID(&db, s, (size_t)pfsize, ccsid, ASCII_CCSID);
+ }
- if(!cp) {
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
+ if(result)
+ break;
- pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
+ s = curlx_dyn_take(&db, &len);
- if(pfsize < 0) {
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- data->set.postfieldsize = pfsize; /* Replace data size. */
- s = cp;
- cp = NULL;
+ /* The following lines give data ownership to the library without
+ copying them. */
+ result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s);
+ if(!result) {
+ data->set.str_copypostfields = CURL_UNCONST(s); /* Adopt. */
+ if(pfsize != -1)
+ data->set.postfieldsize = len;
}
+ else
+ untyped_free(s);
- result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s);
- data->set.str_copypostfields = s; /* Give to library. */
break;
default:
@@ -1217,27 +1243,12 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
if(bp && bp->data && bp->len &&
ccsid != NOCONV_CCSID && ccsid != ASCII_CCSID) {
- pfsize = (curl_off_t)bp->len * MAX_CONV_EXPANSION;
-
- if(pfsize > SIZE_MAX)
- pfsize = SIZE_MAX;
-
- cp = malloc(pfsize);
-
- if(!cp) {
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- pfsize = convert(cp, pfsize, ASCII_CCSID, bp->data, bp->len, ccsid);
-
- if(pfsize < 0) {
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
+ result = dyn_addn_CCSID(&db, bp->data, bp->len, ccsid, ASCII_CCSID);
+ if(result)
+ break;
- blob.data = cp;
- blob.len = pfsize;
+ blob.data = curlx_dyn_ptr(&db);
+ blob.len = curlx_dyn_len(&db);
blob.flags = bp->flags | CURL_BLOB_COPY;
bp = &blob;
}
@@ -1251,7 +1262,7 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
}
va_end(arg);
- free(cp);
+ curlx_dyn_free(&db);
return result;
}
@@ -1259,7 +1270,10 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
char *curl_form_long_value(long value)
{
- /* ILE/RPG cannot cast an integer to a pointer. This procedure does it. */
+ /* ILE/RPG cannot cast an integer to a pointer. This procedure does it.
+ As OS/400 is unable to dereference a pointer built from an integer only,
+ the goal here is only to keep the integer value as a (invalid) pointer
+ for a later reverse conversion. */
return (char *)value;
}
@@ -1287,51 +1301,46 @@ CURLcode curl_multi_setopt_RPGnum_(CURLM *multi, CURLMoption tag,
char *curl_pushheader_bynum_cssid(struct curl_pushheaders *h, size_t num,
unsigned int ccsid)
{
- char *d = (char *)NULL;
- char *s = curl_pushheader_bynum(h, num);
-
- if(s)
- d = dynconvert(ccsid, s, -1, ASCII_CCSID, NULL);
-
- return d;
+ return CURL_UNCONST(curl_to_ccsid(curl_pushheader_bynum(h, num), ccsid));
}
char *curl_pushheader_byname_ccsid(struct curl_pushheaders *h,
const char *header, unsigned int ccsidin,
unsigned int ccsidout)
{
- char *d = (char *)NULL;
+ const char *d = NULL;
if(header) {
- header = dynconvert(ASCII_CCSID, header, -1, ccsidin, NULL);
+ const char *hdr = curl_from_ccsid(header, ccsidin);
+
+ if(hdr) {
+ char *s = curl_pushheader_byname(h, hdr);
- if(header) {
- char *s = curl_pushheader_byname(h, header);
- free((char *)header);
+ untyped_free(hdr);
if(s)
- d = dynconvert(ccsidout, s, -1, ASCII_CCSID, NULL);
+ d = curl_to_ccsid(s, ccsidout);
}
}
- return d;
+ return CURL_UNCONST(d);
}
static CURLcode
mime_string_call(curl_mimepart *part, const char *string, unsigned int ccsid,
CURLcode (*mimefunc)(curl_mimepart *part, const char *string))
{
- char *s = (char *)NULL;
+ const char *s;
CURLcode result;
if(!string)
return mimefunc(part, string);
- s = dynconvert(ASCII_CCSID, string, -1, ccsid, NULL);
+ s = curl_from_ccsid(string, ccsid);
if(!s)
return CURLE_OUT_OF_MEMORY;
result = mimefunc(part, s);
- free(s);
+ untyped_free(s);
return result;
}
@@ -1368,58 +1377,68 @@ CURLcode curl_mime_filedata_ccsid(curl_mimepart *part, const char *filename,
CURLcode curl_mime_data_ccsid(curl_mimepart *part, const char *data,
size_t datasize, unsigned int ccsid)
{
- char *s = (char *)NULL;
+ struct dynbuf db;
CURLcode result;
- int osize;
if(!data)
return curl_mime_data(part, data, datasize);
- s = dynconvert(ASCII_CCSID, data, datasize, ccsid, &osize);
- if(!s)
- return CURLE_OUT_OF_MEMORY;
- result = curl_mime_data(part, s, osize);
- free(s);
+ curlx_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
+
+ result = dyn_addn_CCSID(&db, data, datasize, ccsid, ASCII_CCSID);
+
+ if(!result) {
+ size_t osize;
+ char *newdata = curlx_dyn_take(&db, &osize);
+
+ result = curl_mime_data(part, newdata, datasize == CURL_ZERO_TERMINATED ?
+ datasize : osize);
+ untyped_free(newdata);
+ }
+
return result;
}
CURLUcode curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part,
unsigned int flags, unsigned int ccsid)
{
- char *s = (char *)NULL;
+ char *s = NULL;
CURLUcode result;
if(!part)
return CURLUE_BAD_PARTPOINTER;
- *part = (char *)NULL;
+ *part = NULL;
result = curl_url_get(handle, what, &s, flags);
if(result == CURLUE_OK) {
if(s) {
- *part = dynconvert(ccsid, s, -1, ASCII_CCSID, NULL);
- if(!*part)
+ const char *d = curl_to_ccsid(s, ccsid);
+
+ if(d)
+ *part = CURL_UNCONST(d);
+ else
result = CURLUE_OUT_OF_MEMORY;
}
}
if(s)
- free(s);
+ untyped_free(s);
return result;
}
CURLUcode curl_url_set_ccsid(CURLU *handle, CURLUPart what, const char *part,
unsigned int flags, unsigned int ccsid)
{
- char *s = (char *)NULL;
+ const char *s = NULL;
CURLUcode result;
if(part) {
- s = dynconvert(ASCII_CCSID, part, -1, ccsid, NULL);
+ s = curl_from_ccsid(part, ccsid);
if(!s)
return CURLUE_OUT_OF_MEMORY;
}
result = curl_url_set(handle, what, s, flags);
if(s)
- free(s);
+ untyped_free(s);
return result;
}
@@ -1429,11 +1448,11 @@ curl_easy_option_by_name_ccsid(const char *name, unsigned int ccsid)
const struct curl_easyoption *option = NULL;
if(name) {
- char *s = dynconvert(ASCII_CCSID, name, -1, ccsid, NULL);
+ const char *s = curl_from_ccsid(name, ccsid);
if(s) {
option = curl_easy_option_by_name(s);
- free(s);
+ untyped_free(s);
}
}
@@ -1445,12 +1464,12 @@ const char *
curl_easy_option_get_name_ccsid(const struct curl_easyoption *option,
unsigned int ccsid)
{
- char *name = NULL;
+ const char *name = NULL;
if(option && option->name)
- name = dynconvert(ccsid, option->name, -1, ASCII_CCSID, NULL);
+ name = curl_to_ccsid(option->name, ccsid);
- return (const char *)name;
+ return name;
}
/* Header API CCSID support. */
@@ -1461,12 +1480,12 @@ CURLHcode curl_easy_header_ccsid(CURL *easy, const char *name, size_t index,
CURLHcode result = CURLHE_BAD_ARGUMENT;
if(name) {
- char *s = dynconvert(ASCII_CCSID, name, -1, ccsid, NULL);
+ const char *s = curl_from_ccsid(name, ccsid);
result = CURLHE_OUT_OF_MEMORY;
if(s) {
result = curl_easy_header(easy, s, index, origin, request, hout);
- free(s);
+ untyped_free(s);
}
}