LWN.net Logo

strcpy() / strlcpy() / asprintf()

strcpy() / strlcpy() / asprintf()

Posted Mar 30, 2012 15:56 UTC (Fri) by nybble41 (subscriber, #55106)
In reply to: strcpy() / strlcpy() / asprintf() by nix
Parent article: A turning point for GNU libc

It seems to me like asprintf() should be easy to implement in terms of two calls to vsnprintf():

int vasprintf(char **strp, const char *fmt, va_list ap)
{
  va_list ap_copy;
  char *str;
  int bytes;
  char nul;

  /* Determine the amount of memory required to format the string */
  /* vsnprintf() returns the space required, but only stores the NUL. */
  va_copy(ap_copy, ap);
  bytes = vsnprintf(&nul, 1, fmt, ap_copy);
  va_end(ap_copy);

  if (bytes <= 0)
    return bytes;

  str = (char*)malloc(bytes);

  if (!str)
    return -1;

  /* Format the string into the destination buffer */
  bytes = vsnprintf(str, bytes, fmt, ap);

  if (bytes <= 0)
  {
    free(str);
    return bytes;
  }

  /* No errors; store pointer to destination buffer and return its size. */
  *strp = str;
  return bytes;
}

int asprintf(char **strp, const char *fmt, ...)
{
  int bytes;
  va_list ap;

  va_start(ap, fmt);
  bytes = vasprintf(strp, fmt, ap);
  va_end(ap);

  return bytes;
}

Is there any reason this implementation wouldn't work? (Ignoring minor issues/typos; I'm making this up as I go.)


(Log in to post comments)

strcpy() / strlcpy() / asprintf()

Posted Mar 30, 2012 17:50 UTC (Fri) by nix (subscriber, #2304) [Link]

Ah yes, of course if you had a vsnprintf() you can do it. I forgot about that. (I spent way too long on deprived platforms with either no snprintf() or none that worked.)

strcpy() / strlcpy() / asprintf()

Posted Mar 31, 2012 21:10 UTC (Sat) by lacos (subscriber, #70616) [Link]

You can still implement it easily (but perhaps not too elegantly): vfprintf() the stuff to "/dev/null", and use the return value for allocation. Both the vfprintf() function and the /dev/null special file are mandated by SUSv1 (UNIX(R) 95) and possibly by earlier standards.

(SUSv1 doesn't have snprintf(). Once I needed to compile a glibc-oriented program on OSF/1 4.0E, which one might have consider a reference implementation of SUSv1, even though it wasn't formally certified. The program needed snprintf() and there was none, so I printed the string first to /dev/null (for the size), then fully to a malloc()'d area, then copied the bytes that had room, then free()'d the area. ... Sorry if this sounds trivial and/or retarded :))

strcpy() / strlcpy() / asprintf()

Posted Apr 5, 2012 8:36 UTC (Thu) by nix (subscriber, #2304) [Link]

Never thought of using vfprintf(). That's a good idea. Ah well. It would surely be more elegant than the longjmp() thing.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds