Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
a9cbd67f90 |
2
local.mk
2
local.mk
|
@ -7,7 +7,7 @@ dist-files += configure config.h.in nix.spec perl/configure
|
||||||
|
|
||||||
clean-files += Makefile.config
|
clean-files += Makefile.config
|
||||||
|
|
||||||
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr
|
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr -D_FILE_OFFSET_BITS=64
|
||||||
|
|
||||||
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh), \
|
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh), \
|
||||||
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
||||||
|
|
|
@ -79,7 +79,7 @@ let
|
||||||
git
|
git
|
||||||
mercurial
|
mercurial
|
||||||
]
|
]
|
||||||
++ lib.optional stdenv.isLinux libseccomp
|
++ lib.optionals stdenv.isLinux [ libseccomp fuse ]
|
||||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
||||||
(aws-sdk-cpp.override {
|
(aws-sdk-cpp.override {
|
||||||
|
|
|
@ -27,7 +27,7 @@ with import ./release-common.nix { inherit pkgs; };
|
||||||
git
|
git
|
||||||
mercurial
|
mercurial
|
||||||
]
|
]
|
||||||
++ lib.optional stdenv.isLinux libseccomp;
|
++ lib.optionals stdenv.isLinux [ libseccomp fuse ];
|
||||||
|
|
||||||
inherit configureFlags;
|
inherit configureFlags;
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,6 @@ nix_SOURCES := $(wildcard $(d)/*.cc) $(wildcard src/linenoise/*.cpp)
|
||||||
|
|
||||||
nix_LIBS = libexpr libmain libstore libutil libformat
|
nix_LIBS = libexpr libmain libstore libutil libformat
|
||||||
|
|
||||||
|
nix_LDFLAGS = -lfuse
|
||||||
|
|
||||||
$(eval $(call install-symlink, nix, $(bindir)/nix-hash))
|
$(eval $(call install-symlink, nix, $(bindir)/nix-hash))
|
||||||
|
|
207
src/nix/mount.cc
Normal file
207
src/nix/mount.cc
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
#include "command.hh"
|
||||||
|
#include "store-api.hh"
|
||||||
|
#include "fs-accessor.hh"
|
||||||
|
#include "nar-accessor.hh"
|
||||||
|
|
||||||
|
#define FUSE_USE_VERSION 30
|
||||||
|
#include <fuse.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace nix;
|
||||||
|
|
||||||
|
std::shared_ptr<Store> store;
|
||||||
|
std::shared_ptr<FSAccessor> accessor;
|
||||||
|
|
||||||
|
static int op_getattr(const char * path_, struct stat * stbuf)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
Path path(path_);
|
||||||
|
|
||||||
|
memset(stbuf, 0, sizeof(struct stat));
|
||||||
|
stbuf->st_uid = 0;
|
||||||
|
stbuf->st_gid = 0;
|
||||||
|
stbuf->st_nlink = 1;
|
||||||
|
|
||||||
|
if (path == "/") {
|
||||||
|
stbuf->st_mode = S_IFDIR | 0111;
|
||||||
|
} else {
|
||||||
|
auto st = accessor->stat(store->storeDir + path);
|
||||||
|
|
||||||
|
switch (st.type) {
|
||||||
|
case FSAccessor::tRegular:
|
||||||
|
stbuf->st_mode = S_IFREG | (st.isExecutable ? 0555 : 0444);
|
||||||
|
stbuf->st_size = st.fileSize;
|
||||||
|
break;
|
||||||
|
case FSAccessor::tSymlink:
|
||||||
|
stbuf->st_mode = S_IFLNK | 0777;
|
||||||
|
break;
|
||||||
|
case FSAccessor::tDirectory:
|
||||||
|
stbuf->st_mode = S_IFDIR | 0555;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int op_readdir(const char * path_, void * buf, fuse_fill_dir_t filler,
|
||||||
|
off_t offset, struct fuse_file_info * fi)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
Path path(path_);
|
||||||
|
|
||||||
|
if (path == "/")
|
||||||
|
/* FIXME: could use queryAllValidPaths(), but it will be
|
||||||
|
superslow for binary caches, and won't include name
|
||||||
|
parts. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto st = accessor->stat(store->storeDir + path);
|
||||||
|
if (st.type == FSAccessor::tMissing) return -ENOENT;
|
||||||
|
if (st.type != FSAccessor::tDirectory) return -ENOTDIR;
|
||||||
|
|
||||||
|
for (auto & entry : accessor->readDirectory(store->storeDir + path))
|
||||||
|
filler(buf, entry.c_str(), nullptr, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int op_open(const char * path_, struct fuse_file_info * fi)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
Path path(path_);
|
||||||
|
|
||||||
|
auto st = accessor->stat(store->storeDir + path);
|
||||||
|
if (st.type == FSAccessor::tMissing) return -ENOENT;
|
||||||
|
if (st.type == FSAccessor::tDirectory) return -EISDIR;
|
||||||
|
if (st.type != FSAccessor::tRegular) return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int op_read(const char * path_, char * buf, size_t size, off_t offset,
|
||||||
|
struct fuse_file_info * fi)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
Path path(path_);
|
||||||
|
|
||||||
|
// FIXME: absolutely need to cache this and/or provide random
|
||||||
|
// access.
|
||||||
|
|
||||||
|
auto s = accessor->readFile(store->storeDir + path);
|
||||||
|
|
||||||
|
if (offset >= (off_t) s.size()) return 0;
|
||||||
|
|
||||||
|
if (offset + size > s.size())
|
||||||
|
size = s.size() - offset;
|
||||||
|
|
||||||
|
memcpy(buf, s.data() + offset, size);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int op_readlink(const char * path_, char * buf, size_t size)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
Path path(path_);
|
||||||
|
|
||||||
|
auto st = accessor->stat(store->storeDir + path);
|
||||||
|
if (st.type == FSAccessor::tMissing) return -ENOENT;
|
||||||
|
if (st.type != FSAccessor::tSymlink) return -EINVAL;
|
||||||
|
|
||||||
|
auto s = accessor->readLink(store->storeDir + path);
|
||||||
|
|
||||||
|
if (s.size() >= size) return ENAMETOOLONG; // FIXME
|
||||||
|
|
||||||
|
strncpy(buf, s.c_str(), size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CmdMountStore : StoreCommand
|
||||||
|
{
|
||||||
|
Path mountPoint;
|
||||||
|
|
||||||
|
CmdMountStore()
|
||||||
|
{
|
||||||
|
expectArg("mount-point", &mountPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() override
|
||||||
|
{
|
||||||
|
return "mount-store";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "mount a Nix store as a FUSE file system";
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(ref<Store> store) override
|
||||||
|
{
|
||||||
|
::store = store;
|
||||||
|
accessor = store->getFSAccessor();
|
||||||
|
|
||||||
|
Strings fuseArgs = { "nix", mountPoint, "-o", "debug" };
|
||||||
|
auto fuseArgs2 = stringsToCharPtrs(fuseArgs);
|
||||||
|
|
||||||
|
struct fuse * fuse;
|
||||||
|
char * mountpoint;
|
||||||
|
int multithreaded;
|
||||||
|
|
||||||
|
fuse_operations oper;
|
||||||
|
memset(&oper, 0, sizeof(oper));
|
||||||
|
oper.getattr = op_getattr;
|
||||||
|
oper.readdir = op_readdir;
|
||||||
|
oper.open = op_open;
|
||||||
|
oper.read = op_read;
|
||||||
|
oper.readlink = op_readlink;
|
||||||
|
|
||||||
|
fuse = fuse_setup(fuseArgs2.size() - 1, fuseArgs2.data(),
|
||||||
|
&oper, sizeof(oper),
|
||||||
|
&mountpoint, &multithreaded, nullptr);
|
||||||
|
if (!fuse) throw Error("FUSE setup failed");
|
||||||
|
|
||||||
|
if (multithreaded)
|
||||||
|
fuse_loop_mt(fuse);
|
||||||
|
else
|
||||||
|
fuse_loop(fuse);
|
||||||
|
|
||||||
|
fuse_teardown(fuse, mountpoint);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static RegisterCommand r(make_ref<CmdMountStore>());
|
Loading…
Reference in a new issue