Offer pnstrdup to frontend code

We already had it on the backend.  Frontend can also use it now.

Discussion: https://postgr.es/m/20191204144021.GA17976@alvherre.pgsql
This commit is contained in:
Alvaro Herrera 2019-12-04 19:36:06 -03:00
parent b1abfec825
commit 0b9466fce2
6 changed files with 36 additions and 35 deletions

View File

@ -114,8 +114,7 @@ split_path(const char *path, char **dir, char **fname)
/* directory path */
if (sep != NULL)
{
*dir = pg_strdup(path);
(*dir)[(sep - path) + 1] = '\0'; /* no strndup */
*dir = pnstrdup(path, sep - path);
*fname = pg_strdup(sep + 1);
}
/* local directory */

View File

@ -270,13 +270,10 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
/* execute command */
case '`':
{
FILE *fd;
char *file = pg_strdup(p + 1);
int cmdend;
int cmdend = strcspn(p + 1, "`");
char *file = pnstrdup(p + 1, cmdend);
FILE *fd = popen(file, "r");
cmdend = strcspn(file, "`");
file[cmdend] = '\0';
fd = popen(file, "r");
if (fd)
{
if (fgets(buf, sizeof(buf), fd) == NULL)
@ -295,13 +292,10 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
/* interpolate variable */
case ':':
{
char *name;
int nameend = strcspn(p + 1, ":");
char *name = pnstrdup(p + 1, nameend);
const char *val;
int nameend;
name = pg_strdup(p + 1);
nameend = strcspn(name, ":");
name[nameend] = '\0';
val = GetVariable(pset.vars, name);
if (val)
strlcpy(buf, val, sizeof(buf));

View File

@ -353,8 +353,7 @@ splitTableColumnsSpec(const char *spec, int encoding,
else
cp += PQmblen(cp, encoding);
}
*table = pg_strdup(spec);
(*table)[cp - spec] = '\0'; /* no strndup */
*table = pnstrdup(spec, cp - spec);
*columns = cp;
}

View File

@ -142,6 +142,33 @@ pstrdup(const char *in)
return pg_strdup(in);
}
char *
pnstrdup(const char *in, Size size)
{
char *tmp;
int len;
if (!in)
{
fprintf(stderr,
_("cannot duplicate null pointer (internal error)\n"));
exit(EXIT_FAILURE);
}
len = strnlen(in, size);
tmp = malloc(len + 1);
if (tmp == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
memcpy(tmp, in, len);
tmp[len] = '\0';
return tmp;
}
void *
repalloc(void *pointer, Size size)
{

View File

@ -31,6 +31,7 @@ extern void pg_free(void *pointer);
/* Equivalent functions, deliberately named the same as backend functions */
extern char *pstrdup(const char *in);
extern char *pnstrdup(const char *in, Size size);
extern void *palloc(Size size);
extern void *palloc0(Size size);
extern void *palloc_extended(Size size, int flags);

View File

@ -175,25 +175,6 @@ deccopy(decimal *src, decimal *target)
memcpy(target, src, sizeof(decimal));
}
static char *
ecpg_strndup(const char *str, size_t len)
{
size_t real_len = strlen(str);
int use_len = (int) ((real_len > len) ? len : real_len);
char *new = malloc(use_len + 1);
if (new)
{
memcpy(new, str, use_len);
new[use_len] = '\0';
}
else
errno = ENOMEM;
return new;
}
int
deccvasc(const char *cp, int len, decimal *np)
{
@ -205,7 +186,7 @@ deccvasc(const char *cp, int len, decimal *np)
if (risnull(CSTRINGTYPE, cp))
return 0;
str = ecpg_strndup(cp, len); /* decimal_in always converts the complete
str = pnstrdup(cp, len); /* decimal_in always converts the complete
* string */
if (!str)
ret = ECPG_INFORMIX_NUM_UNDERFLOW;