version 1.6, 2019/02/18 21:55:27 |
version 1.7, 2019/02/18 22:47:34 |
|
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/un.h> |
#include <sys/un.h> |
|
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <limits.h> |
#include <limits.h> |
#include <stdio.h> |
#include <stdio.h> |
|
#include <stdint.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
#define MKTEMP_NAME 0 |
#include "extern.h" |
#define MKTEMP_FILE 1 |
|
#define MKTEMP_DIR 2 |
|
#define MKTEMP_LINK 3 |
|
#define MKTEMP_FIFO 4 |
|
#define MKTEMP_NOD 5 |
|
#define MKTEMP_SOCK 6 |
|
|
|
|
/* |
|
* The type of temporary files we can create. |
|
*/ |
|
enum tmpmode { |
|
MKTEMP_NAME, |
|
MKTEMP_FILE, |
|
MKTEMP_DIR, |
|
MKTEMP_LINK, |
|
MKTEMP_FIFO, |
|
MKTEMP_NOD, |
|
MKTEMP_SOCK |
|
}; |
|
|
|
/* |
|
* Characters we'll use for replacement in the template string. |
|
*/ |
#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" |
#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" |
#define NUM_CHARS (sizeof(TEMPCHARS) - 1) |
#define NUM_CHARS (sizeof(TEMPCHARS) - 1) |
|
|
|
/* |
|
* The number of template replacement values (foo.XXXXXX = 6) that we |
|
* require as a minimum for the filename. |
|
*/ |
#define MIN_X 6 |
#define MIN_X 6 |
|
|
|
/* |
|
* The only flags we'll accept for creation of the temporary file. |
|
*/ |
#define MKOTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_DSYNC | O_RSYNC | O_SYNC) |
#define MKOTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_DSYNC | O_RSYNC | O_SYNC) |
|
|
#ifndef nitems |
#ifndef nitems |
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) |
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) |
#endif |
#endif |
|
|
/* adapted from libc/stdio/mktemp.c */ |
/* |
|
* Adapted from libc/stdio/mktemp.c. |
|
*/ |
static int |
static int |
mktemp_internalat(int pfd, char *path, int slen, int mode, int flags, |
mktemp_internalat(int pfd, char *path, int slen, enum tmpmode mode, |
const char *link, mode_t dev_type, dev_t dev) |
int flags, const char *link, mode_t dev_type, dev_t dev) |
{ |
{ |
char *start, *cp, *ep; |
char *start, *cp, *ep; |
const char tempchars[] = TEMPCHARS; |
const char tempchars[] = TEMPCHARS; |
unsigned int tries; |
unsigned int tries; |
struct stat sb; |
struct stat sb; |
struct sockaddr_un sun; |
struct sockaddr_un sun; |
size_t len; |
size_t len; |
int fd, saved_errno; |
int fd, saved_errno; |
|
|
len = strlen(path); |
len = strlen(path); |
if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) { |
if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) { |
|
|
ep = path + len - slen; |
ep = path + len - slen; |
|
|
for (start = ep; start > path && start[-1] == 'X'; start--) |
for (start = ep; start > path && start[-1] == 'X'; start--) |
; |
/* continue */ ; |
|
|
if (ep - start < MIN_X) { |
if (ep - start < MIN_X) { |
errno = EINVAL; |
errno = EINVAL; |
return(-1); |
return(-1); |
|
|
* A combination of mkstemp(3) and openat(2). |
* A combination of mkstemp(3) and openat(2). |
* On success returns a file descriptor and trailing Xs are overwritten in |
* On success returns a file descriptor and trailing Xs are overwritten in |
* path to create a unique file name. |
* path to create a unique file name. |
* Returns -1 on failure. |
* Returns -1 on failure and sets errno. |
*/ |
*/ |
int |
int |
mkstempat(int fd, char *path) |
mkstempat(int fd, char *path) |
{ |
{ |
return(mktemp_internalat(fd, path, 0, MKTEMP_FILE, 0, NULL, 0, 0)); |
return mktemp_internalat(fd, path, 0, MKTEMP_FILE, 0, NULL, 0, 0); |
} |
} |
|
|
/* |
/* |
* A combination of mkstemp(3) and symlinkat(2). |
* A combination of mkstemp(3) and symlinkat(2). |
* On success returns path with trailing Xs overwritten to create a unique |
* On success returns path with trailing Xs overwritten to create a unique |
* file name. |
* file name. |
* Returns NULL on failure. |
* Returns NULL on failure and sets errno. |
*/ |
*/ |
char* |
char * |
mkstemplinkat(char *link, int fd, char *path) |
mkstemplinkat(char *link, int fd, char *path) |
{ |
{ |
|
|
if (mktemp_internalat(fd, path, 0, MKTEMP_LINK, 0, link, 0, 0) == -1) |
if (mktemp_internalat(fd, path, 0, MKTEMP_LINK, 0, link, 0, 0) == -1) |
return(NULL); |
return NULL; |
return(path); |
return path; |
} |
} |
|
|
/* |
/* |
* A combination of mkstemp(3) and mkfifoat(2). |
* A combination of mkstemp(3) and mkfifoat(2). |
* On success returns path with trailing Xs overwritten to create a unique |
* On success returns path with trailing Xs overwritten to create a unique |
* file name. |
* file name. |
* Returns NULL on failure. |
* Returns NULL on failure and sets errno. |
*/ |
*/ |
char* |
char * |
mkstempfifoat(int fd, char *path) |
mkstempfifoat(int fd, char *path) |
{ |
{ |
|
|
if (mktemp_internalat(fd, path, 0, MKTEMP_FIFO, 0, NULL, 0, 0) == -1) |
if (mktemp_internalat(fd, path, 0, MKTEMP_FIFO, 0, NULL, 0, 0) == -1) |
return(NULL); |
return NULL; |
return(path); |
return path; |
} |
} |
|
|
/* |
/* |
* A combination of mkstemp(3) and mknodat(2). |
* A combination of mkstemp(3) and mknodat(2). |
* On success returns path with trailing Xs overwritten to create a unique |
* On success returns path with trailing Xs overwritten to create a unique |
* file name. |
* file name. |
* Returns NULL on failure. |
* Returns NULL on failure and sets errno. |
*/ |
*/ |
char* |
char * |
mkstempnodat(int fd, char *path, mode_t mode, dev_t dev) |
mkstempnodat(int fd, char *path, mode_t mode, dev_t dev) |
{ |
{ |
if (mktemp_internalat(fd, path, 0, MKTEMP_NOD, 0, NULL, mode, dev) == |
|
-1) |
if (mktemp_internalat(fd, path, 0, |
return(NULL); |
MKTEMP_NOD, 0, NULL, mode, dev) == -1) |
return(path); |
return NULL; |
|
return path; |
} |
} |
|
|
/* |
/* |
* A combination of mkstemp(3) and bind(2) on a unix domain socket. |
* A combination of mkstemp(3) and bind(2) on a unix domain socket. |
* On success returns path with trailing Xs overwritten to create a unique |
* On success returns path with trailing Xs overwritten to create a unique |
* file name. |
* file name. |
* Returns NULL on failure. |
* Returns NULL on failure and sets errno. |
*/ |
*/ |
char* |
char * |
mkstempsock(const char *root, char *path) |
mkstempsock(const char *root, char *path) |
{ |
{ |
|
|
if (mktemp_internalat(0, path, 0, MKTEMP_SOCK, 0, root, 0, 0) == -1) |
if (mktemp_internalat(0, path, 0, MKTEMP_SOCK, 0, root, 0, 0) == -1) |
return(NULL); |
return NULL; |
return(path); |
return path; |
} |
} |
|
|
/* |
/* |
|
|
* (excluding the final '\0'). |
* (excluding the final '\0'). |
*/ |
*/ |
int |
int |
mktemplate(char **ret, const char *path, int recursive) |
mktemplate(struct sess *sess, char **ret, const char *path, int recursive) |
{ |
{ |
int n, dirlen; |
int n, dirlen; |
const char *cp; |
const char *cp; |
|
|
if (recursive && (cp = strrchr(path, '/')) != NULL) { |
if (recursive && (cp = strrchr(path, '/')) != NULL) { |
dirlen = cp - path; |
dirlen = cp - path; |
if ((n = asprintf(ret, "%.*s/.%s.XXXXXXXXXX", dirlen, path, |
n = asprintf(ret, "%.*s/.%s.XXXXXXXXXX", |
path + dirlen + 1)) == -1) |
dirlen, path, path + dirlen + 1); |
|
if (n < 0) { |
|
ERR(sess, "asprintf"); |
*ret = NULL; |
*ret = NULL; |
} else { |
} |
if ((n = asprintf(ret, ".%s.XXXXXXXXXX", path)) == -1) |
} else if ((n = asprintf(ret, ".%s.XXXXXXXXXX", path)) < 0) { |
*ret = NULL; |
ERR(sess, "asprintf"); |
|
*ret = NULL; |
} |
} |
return(n); |
|
|
return n; |
} |
} |