/*- * Compact mkstemp(3)-only implementation, for klibc * * Copyright (c) 2009 * Thorsten Glaser * * This file is available under the same terms ("historic * permission clause") as klibc itself or under the terms * of The MirOS Licence (dual licenced). */ #include #include #include #include #include #include #include #include int mkstemp(char *template) { unsigned int i; char *cp, *sp; struct stat sbuf; cp = template; while (*cp) ++cp; --cp; if (cp < template) { errno = EINVAL; return (-1); } /* generate random suffix */ while (cp > template && *cp == 'X') { i = arc4random(); i = i % (26 + 26); *cp-- = i < 26 ? 'A' + i : 'a' + i - 26; } sp = cp + 1; /* check the target directory */ while (cp > template && *cp != '/') --cp; if (cp > template) { *cp = '\0'; i = stat(template, &sbuf); *cp = '/'; if (i != 0) /* stat failed, pass errno */ return (-1); if (!S_ISDIR(sbuf.st_mode)) { errno = ENOTDIR; return (-1); } } cp = sp; for (;;) { if ((i = open(template, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0 || errno != EEXIST) break; while (*cp == 'Z') if (!*++cp) return (-1); if (*cp == 'z') *cp = 'A'; else ++*cp; } return (i); }