diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2009-01-02 16:43:50 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2009-01-02 16:43:50 (GMT) |
commit | 4123c4bbf735f1e0910f1ae529ee6a5fa4a841a4 (patch) | |
tree | e72f06db7689cdca26c0e91537e5a0eecf4e2d9a /compat | |
parent | 337a6648fee48d63d97c16579b72703b39647564 (diff) | |
download | tcl-4123c4bbf735f1e0910f1ae529ee6a5fa4a841a4.zip tcl-4123c4bbf735f1e0910f1ae529ee6a5fa4a841a4.tar.gz tcl-4123c4bbf735f1e0910f1ae529ee6a5fa4a841a4.tar.bz2 |
Fix various mkstemp()-related issues. [Bugs 741967,878333]
Diffstat (limited to 'compat')
-rw-r--r-- | compat/mkstemp.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/compat/mkstemp.c b/compat/mkstemp.c new file mode 100644 index 0000000..8adc11b --- /dev/null +++ b/compat/mkstemp.c @@ -0,0 +1,78 @@ +/* + * mkstemp.c -- + * + * Source code for the "mkstemp" library routine. + * + * Copyright (c) 2009 Donal K. Fellows + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: mkstemp.c,v 1.1 2009/01/02 16:43:50 dkf Exp $ + */ + +#include <stdlib.h> +#include <unistd.h> + +/* + *---------------------------------------------------------------------- + * + * mkstemp -- + * + * Create an open temporary file from a template. + * + * Results: + * A file descriptor, or -1 (with errno set) in the case of an error. + * + * Side effects: + * The template is updated to contain the real filename. + * + *---------------------------------------------------------------------- + */ + +int +mkstemp( + char *template) /* Template for filename. */ +{ + static const char alphanumerics[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + register char *a, *b; + int fd, count, alphanumericsLen = strlen(alphanumerics); /* == 62 */ + + a = template + strlen(template); + while (a > template && *(a-1) == 'X') { + a--; + } + + if (a == template) { + errno = ENOENT; + return -1; + } + + /* + * We'll only try up to 10 times; after that, we're suffering from enemy + * action and should let the caller know. + */ + + count = 10; + do { + /* + * Replace the X's in the original template with random alphanumeric + * digits. + */ + + for (b=a ; *b ; b++) { + float r = random() / ((float) RAND_MAX); + + *b = alphanumerics[(int)(r * alphanumericsLen)]; + } + + /* + * Template is now realized; try to open (with correct options). + */ + + fd = open(template, O_RDWR|O_CREAT|O_EXCL, 0600); + } while (fd == -1 && errno == EEXIST && --count > 0); + + return fd; +} |