mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-22 22:16:16 +02:00
Merge pull request #10556 from nix-windows/uds-remote-on-windows
Enable the `unix://` store on Windows
This commit is contained in:
commit
1948ec390c
11 changed files with 166 additions and 88 deletions
|
@ -173,12 +173,13 @@ void initNix(bool loadConfig)
|
||||||
everybody. */
|
everybody. */
|
||||||
umask(0022);
|
umask(0022);
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
/* Initialise the PRNG. */
|
/* Initialise the PRNG. */
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
|
#ifndef _WIN32
|
||||||
srandom(tv.tv_usec);
|
srandom(tv.tv_usec);
|
||||||
#endif
|
#endif
|
||||||
|
srand(tv.tv_usec);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
44
src/libstore/indirect-root-store.cc
Normal file
44
src/libstore/indirect-root-store.cc
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "indirect-root-store.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
void IndirectRootStore::makeSymlink(const Path & link, const Path & target)
|
||||||
|
{
|
||||||
|
/* Create directories up to `gcRoot'. */
|
||||||
|
createDirs(dirOf(link));
|
||||||
|
|
||||||
|
/* Create the new symlink. */
|
||||||
|
Path tempLink = fmt("%1%.tmp-%2%-%3%", link, getpid(), rand());
|
||||||
|
createSymlink(target, tempLink);
|
||||||
|
|
||||||
|
/* Atomically replace the old one. */
|
||||||
|
renameFile(tempLink, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Path IndirectRootStore::addPermRoot(const StorePath & storePath, const Path & _gcRoot)
|
||||||
|
{
|
||||||
|
Path gcRoot(canonPath(_gcRoot));
|
||||||
|
|
||||||
|
if (isInStore(gcRoot))
|
||||||
|
throw Error(
|
||||||
|
"creating a garbage collector root (%1%) in the Nix store is forbidden "
|
||||||
|
"(are you running nix-build inside the store?)", gcRoot);
|
||||||
|
|
||||||
|
/* Register this root with the garbage collector, if it's
|
||||||
|
running. This should be superfluous since the caller should
|
||||||
|
have registered this root yet, but let's be on the safe
|
||||||
|
side. */
|
||||||
|
addTempRoot(storePath);
|
||||||
|
|
||||||
|
/* Don't clobber the link if it already exists and doesn't
|
||||||
|
point to the Nix store. */
|
||||||
|
if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
|
||||||
|
throw Error("cannot create symlink '%1%'; already exists", gcRoot);
|
||||||
|
makeSymlink(gcRoot, printStorePath(storePath));
|
||||||
|
addIndirectRoot(gcRoot);
|
||||||
|
|
||||||
|
return gcRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -67,6 +67,9 @@ struct IndirectRootStore : public virtual LocalFSStore
|
||||||
* The form this weak-reference takes is implementation-specific.
|
* The form this weak-reference takes is implementation-specific.
|
||||||
*/
|
*/
|
||||||
virtual void addIndirectRoot(const Path & path) = 0;
|
virtual void addIndirectRoot(const Path & path) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void makeSymlink(const Path & link, const Path & target);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(THREAD_LDFLAGS)
|
||||||
ifdef HOST_LINUX
|
ifdef HOST_LINUX
|
||||||
libstore_LDFLAGS += -ldl
|
libstore_LDFLAGS += -ldl
|
||||||
endif
|
endif
|
||||||
|
ifdef HOST_WINDOWS
|
||||||
|
libstore_LDFLAGS += -lws2_32
|
||||||
|
endif
|
||||||
|
|
||||||
$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox)))
|
$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox)))
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,20 @@
|
||||||
#include "unix-domain-socket.hh"
|
#include "unix-domain-socket.hh"
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <cstring>
|
#ifdef _WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
# include <afunix.h>
|
||||||
|
#else
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <sys/un.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -57,7 +61,7 @@ std::string UDSRemoteStore::getUri()
|
||||||
|
|
||||||
void UDSRemoteStore::Connection::closeWrite()
|
void UDSRemoteStore::Connection::closeWrite()
|
||||||
{
|
{
|
||||||
shutdown(fd.get(), SHUT_WR);
|
shutdown(toSocket(fd.get()), SHUT_WR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,7 +72,7 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
||||||
/* Connect to a daemon that does the privileged work for us. */
|
/* Connect to a daemon that does the privileged work for us. */
|
||||||
conn->fd = createUnixDomainSocket();
|
conn->fd = createUnixDomainSocket();
|
||||||
|
|
||||||
nix::connect(conn->fd.get(), path ? *path : settings.nixDaemonSocketFile);
|
nix::connect(toSocket(conn->fd.get()), path ? *path : settings.nixDaemonSocketFile);
|
||||||
|
|
||||||
conn->from.fd = conn->fd.get();
|
conn->from.fd = conn->fd.get();
|
||||||
conn->to.fd = conn->fd.get();
|
conn->to.fd = conn->fd.get();
|
|
@ -35,20 +35,6 @@ static std::string gcSocketPath = "/gc-socket/socket";
|
||||||
static std::string gcRootsDir = "gcroots";
|
static std::string gcRootsDir = "gcroots";
|
||||||
|
|
||||||
|
|
||||||
static void makeSymlink(const Path & link, const Path & target)
|
|
||||||
{
|
|
||||||
/* Create directories up to `gcRoot'. */
|
|
||||||
createDirs(dirOf(link));
|
|
||||||
|
|
||||||
/* Create the new symlink. */
|
|
||||||
Path tempLink = fmt("%1%.tmp-%2%-%3%", link, getpid(), random());
|
|
||||||
createSymlink(target, tempLink);
|
|
||||||
|
|
||||||
/* Atomically replace the old one. */
|
|
||||||
renameFile(tempLink, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::addIndirectRoot(const Path & path)
|
void LocalStore::addIndirectRoot(const Path & path)
|
||||||
{
|
{
|
||||||
std::string hash = hashString(HashAlgorithm::SHA1, path).to_string(HashFormat::Nix32, false);
|
std::string hash = hashString(HashAlgorithm::SHA1, path).to_string(HashFormat::Nix32, false);
|
||||||
|
@ -57,32 +43,6 @@ void LocalStore::addIndirectRoot(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path IndirectRootStore::addPermRoot(const StorePath & storePath, const Path & _gcRoot)
|
|
||||||
{
|
|
||||||
Path gcRoot(canonPath(_gcRoot));
|
|
||||||
|
|
||||||
if (isInStore(gcRoot))
|
|
||||||
throw Error(
|
|
||||||
"creating a garbage collector root (%1%) in the Nix store is forbidden "
|
|
||||||
"(are you running nix-build inside the store?)", gcRoot);
|
|
||||||
|
|
||||||
/* Register this root with the garbage collector, if it's
|
|
||||||
running. This should be superfluous since the caller should
|
|
||||||
have registered this root yet, but let's be on the safe
|
|
||||||
side. */
|
|
||||||
addTempRoot(storePath);
|
|
||||||
|
|
||||||
/* Don't clobber the link if it already exists and doesn't
|
|
||||||
point to the Nix store. */
|
|
||||||
if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
|
|
||||||
throw Error("cannot create symlink '%1%'; already exists", gcRoot);
|
|
||||||
makeSymlink(gcRoot, printStorePath(storePath));
|
|
||||||
addIndirectRoot(gcRoot);
|
|
||||||
|
|
||||||
return gcRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::createTempRootsFile()
|
void LocalStore::createTempRootsFile()
|
||||||
{
|
{
|
||||||
auto fdTempRoots(_fdTempRoots.lock());
|
auto fdTempRoots(_fdTempRoots.lock());
|
||||||
|
|
|
@ -1,24 +1,31 @@
|
||||||
#include "file-system.hh"
|
#include "file-system.hh"
|
||||||
#include "processes.hh"
|
|
||||||
#include "unix-domain-socket.hh"
|
#include "unix-domain-socket.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#ifdef _WIN32
|
||||||
#include <sys/un.h>
|
# include <winsock2.h>
|
||||||
|
# include <afunix.h>
|
||||||
|
#else
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <sys/un.h>
|
||||||
|
# include "processes.hh"
|
||||||
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
AutoCloseFD createUnixDomainSocket()
|
AutoCloseFD createUnixDomainSocket()
|
||||||
{
|
{
|
||||||
AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM
|
AutoCloseFD fdSocket = toDescriptor(socket(PF_UNIX, SOCK_STREAM
|
||||||
#ifdef SOCK_CLOEXEC
|
#ifdef SOCK_CLOEXEC
|
||||||
| SOCK_CLOEXEC
|
| SOCK_CLOEXEC
|
||||||
#endif
|
#endif
|
||||||
, 0);
|
, 0));
|
||||||
if (!fdSocket)
|
if (!fdSocket)
|
||||||
throw SysError("cannot create Unix domain socket");
|
throw SysError("cannot create Unix domain socket");
|
||||||
|
#ifndef _WIN32
|
||||||
closeOnExec(fdSocket.get());
|
closeOnExec(fdSocket.get());
|
||||||
|
#endif
|
||||||
return fdSocket;
|
return fdSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,16 +39,15 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
||||||
if (chmod(path.c_str(), mode) == -1)
|
if (chmod(path.c_str(), mode) == -1)
|
||||||
throw SysError("changing permissions on '%1%'", path);
|
throw SysError("changing permissions on '%1%'", path);
|
||||||
|
|
||||||
if (listen(fdSocket.get(), 100) == -1)
|
if (listen(toSocket(fdSocket.get()), 100) == -1)
|
||||||
throw SysError("cannot listen on socket '%1%'", path);
|
throw SysError("cannot listen on socket '%1%'", path);
|
||||||
|
|
||||||
return fdSocket;
|
return fdSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void bindConnectProcHelper(
|
static void bindConnectProcHelper(
|
||||||
std::string_view operationName, auto && operation,
|
std::string_view operationName, auto && operation,
|
||||||
int fd, const std::string & path)
|
Socket fd, const std::string & path)
|
||||||
{
|
{
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
|
@ -54,6 +60,9 @@ static void bindConnectProcHelper(
|
||||||
auto * psaddr = reinterpret_cast<struct sockaddr *>(&addr);
|
auto * psaddr = reinterpret_cast<struct sockaddr *>(&addr);
|
||||||
|
|
||||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
throw Error("cannot %s to socket at '%s': path is too long", operationName, path);
|
||||||
|
#else
|
||||||
Pipe pipe;
|
Pipe pipe;
|
||||||
pipe.create();
|
pipe.create();
|
||||||
Pid pid = startProcess([&] {
|
Pid pid = startProcess([&] {
|
||||||
|
@ -83,6 +92,7 @@ static void bindConnectProcHelper(
|
||||||
errno = *errNo;
|
errno = *errNo;
|
||||||
throw SysError("cannot %s to socket at '%s'", operationName, path);
|
throw SysError("cannot %s to socket at '%s'", operationName, path);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
|
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
|
||||||
if (operation(fd, psaddr, sizeof(addr)) == -1)
|
if (operation(fd, psaddr, sizeof(addr)) == -1)
|
||||||
|
@ -91,7 +101,7 @@ static void bindConnectProcHelper(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bind(int fd, const std::string & path)
|
void bind(Socket fd, const std::string & path)
|
||||||
{
|
{
|
||||||
unlink(path.c_str());
|
unlink(path.c_str());
|
||||||
|
|
||||||
|
@ -99,7 +109,7 @@ void bind(int fd, const std::string & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void connect(int fd, const std::string & path)
|
void connect(Socket fd, const std::string & path)
|
||||||
{
|
{
|
||||||
bindConnectProcHelper("connect", ::connect, fd, path);
|
bindConnectProcHelper("connect", ::connect, fd, path);
|
||||||
}
|
}
|
84
src/libutil/unix-domain-socket.hh
Normal file
84
src/libutil/unix-domain-socket.hh
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#pragma once
|
||||||
|
///@file
|
||||||
|
|
||||||
|
#include "types.hh"
|
||||||
|
#include "file-descriptor.hh"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Unix domain socket.
|
||||||
|
*/
|
||||||
|
AutoCloseFD createUnixDomainSocket();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Unix domain socket in listen mode.
|
||||||
|
*/
|
||||||
|
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Often we want to use `Descriptor`, but Windows makes a slightly
|
||||||
|
* stronger file descriptor vs socket distinction, at least at the level
|
||||||
|
* of C types.
|
||||||
|
*/
|
||||||
|
using Socket =
|
||||||
|
#ifdef _WIN32
|
||||||
|
SOCKET
|
||||||
|
#else
|
||||||
|
int
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/**
|
||||||
|
* Windows gives this a different name
|
||||||
|
*/
|
||||||
|
# define SHUT_WR SD_SEND
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a `Socket` to a `Descriptor`
|
||||||
|
*
|
||||||
|
* This is a no-op except on Windows.
|
||||||
|
*/
|
||||||
|
static inline Socket toSocket(Descriptor fd)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return reinterpret_cast<Socket>(fd);
|
||||||
|
#else
|
||||||
|
return fd;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a `Socket` to a `Descriptor`
|
||||||
|
*
|
||||||
|
* This is a no-op except on Windows.
|
||||||
|
*/
|
||||||
|
static inline Descriptor fromSocket(Socket fd)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return reinterpret_cast<Descriptor>(fd);
|
||||||
|
#else
|
||||||
|
return fd;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind a Unix domain socket to a path.
|
||||||
|
*/
|
||||||
|
void bind(Socket fd, const std::string & path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to a Unix domain socket.
|
||||||
|
*/
|
||||||
|
void connect(Socket fd, const std::string & path);
|
||||||
|
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
#pragma once
|
|
||||||
///@file
|
|
||||||
|
|
||||||
#include "types.hh"
|
|
||||||
#include "file-descriptor.hh"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace nix {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a Unix domain socket.
|
|
||||||
*/
|
|
||||||
AutoCloseFD createUnixDomainSocket();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a Unix domain socket in listen mode.
|
|
||||||
*/
|
|
||||||
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind a Unix domain socket to a path.
|
|
||||||
*/
|
|
||||||
void bind(int fd, const std::string & path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to a Unix domain socket.
|
|
||||||
*/
|
|
||||||
void connect(int fd, const std::string & path);
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue