blob: 5f0de0532f3db365e1193ab9935ff7a35dc360c5 (
plain) (
tree)
|
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifndef TEST
/**
* Fill a buffer with random alphanumerical symbols, and '_' and '-'
*
* @param buf The buffer to fill
* @param n The size of the buffer
*/
static void
random_alnum(char *buf, size_t n)
{
size_t i;
int rnd;
double drnd;
#if defined(__linux__) && defined(GRND_NONBLOCK)
ssize_t r = getrandom(buf, n, GRND_NONBLOCK);
i = r < 0 ? 0 : (size_t)r;
#else
i = 0;
#endif
for (; i < n; i++) {
rnd = rand();
drnd = (double)rnd / (double)RAND_MAX;
drnd *= 63;
rnd = (int)drnd;
buf[i] = (char)rnd;
}
for (i = 0; i < n; i++)
buf[i] = "0123456789_abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ"[buf[i] & 63];
}
int
libsimple_bindtemp_un(int fd, int dir_fd, struct sockaddr_un *addr, socklen_t *addrlen)
{
int len, saved_errno = errno;
size_t rem, try_limit = 1000;
struct sockaddr_un addr_;
if (!addr)
addr = &addr_;
if (addrlen)
*addrlen = sizeof(*addr);
memset(addr, 0, sizeof(*addr));
addr->sun_family = AF_UNIX;
if (dir_fd == AT_FDCWD)
len = snprintf(addr->sun_path, sizeof(addr->sun_path), "tmp");
else
len = snprintf(addr->sun_path, sizeof(addr->sun_path), "/dev/fd/%i/tmp", dir_fd);
if (len < 0 || (size_t)len >= sizeof(addr->sun_path) || sizeof(addr->sun_path) - (size_t)len < 6)
abort();
rem = sizeof(addr->sun_path) - 1U - (size_t)len;
addr->sun_path[sizeof(addr->sun_path) - 1U] = 0;
while (try_limit--) {
again:
random_alnum(&addr->sun_path[len], rem);
if (!bind(fd, (void *)&addr, (socklen_t)sizeof(*addr))) {
errno = saved_errno;
return 0;
} else if (errno == ENAMETOOLONG && rem > 5) {
addr->sun_path[(size_t)len + --rem] = 0;
goto again;
} else if (errno != EEXIST && errno != EADDRINUSE) {
return -1;
}
}
return -1;
}
#else
#include "test.h"
int
main(void) /* TODO add test */
{
return 0;
}
#endif
|