Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 28 Jan 2013 11:33:00 -0500
From: Rich Felker <dalias@...ifal.cx>
To: musl@...ts.openwall.com
Subject: Re: [PATCH] Add support for mkostemp, mkstemps and mkostemps

On Mon, Jan 28, 2013 at 12:06:23AM -0500, Anthony G. Basile wrote:
> From: "Anthony G. Basile" <basile@...nsource.dyc.edu>
> 
> Signed-off-by: Anthony G. Basile <blueness@...too.org>
> ---
>  include/stdlib.h     |  6 ++++++
>  src/temp/mkostemp.c  | 18 ++++++++++++++++++
>  src/temp/mkostemps.c | 18 ++++++++++++++++++
>  src/temp/mkstemp.c   | 15 ++-------------
>  src/temp/mkstemps.c  | 18 ++++++++++++++++++
>  src/temp/mktemp.c    |  7 +++----
>  src/temp/randname.c  | 22 ++++++++++++++++++++++
>  src/temp/tempfile.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
>  8 files changed, 129 insertions(+), 17 deletions(-)
>  create mode 100644 src/temp/mkostemp.c
>  create mode 100644 src/temp/mkostemps.c
>  create mode 100644 src/temp/mkstemps.c
>  create mode 100644 src/temp/randname.c
>  create mode 100644 src/temp/tempfile.c
> 
> diff --git a/include/stdlib.h b/include/stdlib.h
> index 671d188..4210f40 100644
> --- a/include/stdlib.h
> +++ b/include/stdlib.h
> @@ -95,6 +95,9 @@ int posix_memalign (void **, size_t, size_t);
>  int setenv (const char *, const char *, int);
>  int unsetenv (const char *);
>  int mkstemp (char *);
> +int mkostemp (char *, int);
> +int mkstemps (char *, int);
> +int mkostemps (char *, int, int);
>  char *mkdtemp (char *);
>  int getsubopt (char **, char *const *, char **);
>  int rand_r (unsigned *);
> @@ -150,6 +153,9 @@ char *gcvt(double, int, char *);
>  
>  #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
>  #define mkstemp64 mkstemp
> +#define mkostemp64 mkostemp
> +#define mkstemps64 mkstemps
> +#define mkostemps64 mkostemps
>  #endif
>  
>  #ifdef __cplusplus
> diff --git a/src/temp/mkostemp.c b/src/temp/mkostemp.c
> new file mode 100644
> index 0000000..750d880
> --- /dev/null
> +++ b/src/temp/mkostemp.c
> @@ -0,0 +1,18 @@
> +#define _GNU_SOURCE
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <limits.h>
> +#include <errno.h>
> +#include "libc.h"
> +
> +int __open_tempfile (char *, int, int);
> +
> +int __mkostemp(char *template, int flags)
> +{
> +	return __open_tempfile (template, 0, flags);
> +}
> +
> +weak_alias(__mkostemp, mkostemp);
> diff --git a/src/temp/mkostemps.c b/src/temp/mkostemps.c
> new file mode 100644
> index 0000000..8c810ce
> --- /dev/null
> +++ b/src/temp/mkostemps.c
> @@ -0,0 +1,18 @@
> +#define _GNU_SOURCE
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <limits.h>
> +#include <errno.h>
> +#include "libc.h"
> +
> +int __open_tempfile (char *, int, int);
> +
> +int __mkostemps(char *template, int len, int flags)
> +{
> +	return __open_tempfile (template, len, flags);
> +}
> +
> +weak_alias(__mkostemps, mkostemps);

Sorry, I think I wasn't clear about my comments on the alias. I was
just saying the actual function can be named __mkostemps (rather than
__open_tempfile or whatever) with weak_alias(__mkostemps, mkostemps);
so that it also provides the publicly visible mkostemps. That avoids
having an extra wrapper layer.

> diff --git a/src/temp/mkstemps.c b/src/temp/mkstemps.c
> new file mode 100644
> index 0000000..53fea07
> --- /dev/null
> +++ b/src/temp/mkstemps.c
> @@ -0,0 +1,18 @@
> +#define _GNU_SOURCE
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <limits.h>
> +#include <errno.h>
> +#include "libc.h"

I don't think all these headers are needed for just a one-line wrapper
function. :)

> +
> +int __open_tempfile (char *, int, int);
> +
> +int __mkstemps(char *template, int len)
> +{
> +	return __open_tempfile (template, len, O_RDWR);
> +}
> +
> +weak_alias(__mkstemps, mkstemps);

These aliases aren't needed since mkstemps, et.c aren't used
internally. The __-prefixed version of a function, with the "real"
name being a weak alias for it, is needed only when you want to be
able to call a nonstandard function from within the standard library,
or if it's being defined in the same source file as a standard
function.

> diff --git a/src/temp/mktemp.c b/src/temp/mktemp.c
> index c0e06f5..de1afb4 100644
> --- a/src/temp/mktemp.c
> +++ b/src/temp/mktemp.c
> @@ -8,6 +8,8 @@
>  #include <stdint.h>
>  #include "libc.h"
>  
> +char *__randname(char *);
> +
>  char *__mktemp(char *template)
>  {
>  	struct timespec ts;
> @@ -21,10 +23,7 @@ char *__mktemp(char *template)
>  		return template;
>  	}
>  	while (retries--) {
> -		clock_gettime(CLOCK_REALTIME, &ts);
> -		r = ts.tv_nsec + (uintptr_t)&ts / 16 + (uintptr_t)template;
> -		for (i=1; i<=6; i++, r>>=4)
> -			template[l-i] = 'A'+(r&15);
> +		__randname(template);
>  		if (access(template, F_OK) < 0) return template;
>  	}
>  	*template = 0;
> diff --git a/src/temp/randname.c b/src/temp/randname.c
> new file mode 100644
> index 0000000..4d3476f
> --- /dev/null
> +++ b/src/temp/randname.c
> @@ -0,0 +1,22 @@
> +#include <string.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <time.h>
> +#include <stdint.h>
> +#include "libc.h"
> +
> +char *__randname(char *template)
> +{
> +	struct timespec ts;
> +	size_t i, l = strlen(template);
> +	unsigned long r;
> +
> +	/* This assumes that a check for the template
> +	   size has alrady been made */
> +	clock_gettime(CLOCK_REALTIME, &ts);
> +	r = ts.tv_nsec + (uintptr_t)&ts / 16 + (uintptr_t)template;
> +	for (i=1; i<=6; i++, r>>=4)
> +		template[l-i] = 'A'+(r&15);
> +
> +	return template;
> +}
> diff --git a/src/temp/tempfile.c b/src/temp/tempfile.c
> new file mode 100644
> index 0000000..93808a6
> --- /dev/null
> +++ b/src/temp/tempfile.c
> @@ -0,0 +1,42 @@
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <limits.h>
> +#include <errno.h>
> +#include "libc.h"
> +
> +char *__randname(char *);
> +
> +int __open_tempfile (char *template, int len, int flags)
> +{
> +	if (len < 0) return EINVAL;
> +
> +	int l = strlen(template)-len;
> +	if (l < 6 || strncmp(template+l-6, "XXXXXX",6)) {
> +		errno = EINVAL;
> +		*template = 0;
> +		return -1;
> +	}
> +
> +	/* Null terminate the template before the suffix,
> +	   and save the char for adding back the suffix */
> +	char suffix = template[l];
> +	template[l] = '\0';
> +
> +	int fd, retries = 100, t0 = *template;
> +	while (retries--) {
> +		if (!*__randname(template)) return -1;
> +		/* Add back the suffix */
> +		template[l] = suffix;
> +		if ((fd = open(template, flags | O_CREAT | O_EXCL, 0600))>=0)
> +			return fd;
> +		if (errno != EEXIST) return -1;
> +		/* this is safe because mktemp verified
> +		 * that we have a valid template string */
> +		template[0] = t0;
> +		strcpy(template+l-6, "XXXXXX");

Since your __randname is not checking for XXXXXX like __mktemp was
doing, this strcpy is probably not needed. I'm not sure whether it
would be cleaner to keep this strcpy and put the template check back
in __randname (so that mktemp and __mkostemps don't duplicate the
check) or just get rid of the strcpy here. What do you think?

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.