Implemented symlinks

This commit is contained in:
Sebastian Messmer 2015-04-22 16:00:14 +02:00
parent f41939f443
commit 446c07deff
6 changed files with 73 additions and 17 deletions

View File

@ -16,7 +16,8 @@ public:
enum class EntryType {
DIR = 0,
FILE = 1
FILE = 1,
SYMLINK = 2
};
struct Entry {
@ -27,6 +28,7 @@ public:
virtual std::unique_ptr<OpenFile> createAndOpenFile(const std::string &name, mode_t mode, uid_t uid, gid_t gid) = 0;
virtual void createDir(const std::string &name, mode_t mode, uid_t uid, gid_t gid) = 0;
virtual void createSymlink(const std::string &name, const boost::filesystem::path &target) = 0;
//TODO Allow alternative implementation returning only children names without more information
//virtual std::unique_ptr<std::vector<std::string>> children() const = 0;

21
fs_interface/Symlink.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#ifndef FSPP_SYMLINK_H_
#define FSPP_SYMLINK_H_
#include "Node.h"
#include <memory>
#include <string>
namespace fspp {
class Device;
class Symlink: public virtual Node {
public:
virtual ~Symlink() {}
virtual boost::filesystem::path target() = 0;
};
}
#endif

View File

@ -37,6 +37,8 @@ public:
virtual void statfs(const boost::filesystem::path &path, struct statvfs *fsstat) = 0;
//TODO We shouldn't use Dir::Entry here, that's in another layer
virtual std::unique_ptr<std::vector<Dir::Entry>> readDir(const boost::filesystem::path &path) = 0;
virtual void createSymlink(const boost::filesystem::path &to, const boost::filesystem::path &from) = 0;
virtual void readSymlink(const boost::filesystem::path &path, char *buf, size_t size) = 0;
};
}

View File

@ -45,8 +45,8 @@ int fusepp_rmdir(const char *path) {
return FUSE_OBJ->rmdir(bf::path(path));
}
int fusepp_symlink(const char *from, const char *to) {
return FUSE_OBJ->symlink(bf::path(from), bf::path(to));
int fusepp_symlink(const char *to, const char *from) {
return FUSE_OBJ->symlink(bf::path(to), bf::path(from));
}
int fusepp_rename(const char *from, const char *to) {
@ -248,13 +248,14 @@ int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fil
}
}
//TODO
int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
UNUSED(path);
UNUSED(buf);
UNUSED(size);
printf("Called non-implemented readlink(%s, _, %zu)\n", path.c_str(), size);
return ENOSYS;
//printf("readlink(%s, _, %zu)\n", path.c_str(), size);
try {
_fs->readSymlink(path, buf, size);
return 0;
} catch (fspp::fuse::FuseErrnoException &e) {
return -e.getErrno();
}
}
int Fuse::mknod(const bf::path &path, mode_t mode, dev_t rdev) {
@ -295,14 +296,14 @@ int Fuse::rmdir(const bf::path &path) {
}
}
//TODO
int Fuse::symlink(const bf::path &from, const bf::path &to) {
printf("NOT IMPLEMENTED: symlink(%s, %s)\n", from.c_str(), to.c_str());
//auto real_from = _impl->RootDir() / from;
//auto real_to = _impl->RootDir() / to;
//int retstat = ::symlink(real_from.c_str(), real_to.c_str());
//return errcode_map(retstat);
return ENOSYS;
//printf("symlink(%s, %s)\n", from.c_str(), to.c_str());
try {
_fs->createSymlink(from, to);
return 0;
} catch(fspp::fuse::FuseErrnoException &e) {
return -e.getErrno();
}
}
int Fuse::rename(const bf::path &from, const bf::path &to) {
@ -477,8 +478,13 @@ int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t
//It does getattr() calls on all entries nevertheless.
if (entry.type == Dir::EntryType::DIR) {
stbuf.st_mode = S_IFDIR;
} else {
} else if (entry.type == Dir::EntryType::FILE) {
stbuf.st_mode = S_IFREG;
} else if (entry.type == Dir::EntryType::SYMLINK) {
printf("readdir:symlink\n");
stbuf.st_mode = S_IFLNK;
} else {
assert(false);
}
if (filler(buf, entry.name.c_str(), &stbuf, 0) != 0) {
return -ENOMEM;

View File

@ -4,6 +4,7 @@
#include <fcntl.h>
#include "../fs_interface/Device.h"
#include "../fs_interface/Dir.h"
#include "../fs_interface/Symlink.h"
#include "../fuse/FuseErrnoException.h"
#include "../fs_interface/File.h"
@ -46,6 +47,15 @@ unique_ptr<Dir> FilesystemImpl::LoadDir(const bf::path &path) {
return dir;
}
unique_ptr<Symlink> FilesystemImpl::LoadSymlink(const bf::path &path) {
auto node = _device->Load(path);
auto dir = dynamic_pointer_move<Symlink>(node);
if (!dir) {
throw fuse::FuseErrnoException(ENOTDIR);
}
return dir;
}
int FilesystemImpl::openFile(const bf::path &path, int flags) {
auto file = LoadFile(path);
return openFile(*file, flags);
@ -148,3 +158,14 @@ void FilesystemImpl::utimens(const bf::path &path, const timespec times[2]) {
void FilesystemImpl::statfs(const bf::path &path, struct statvfs *fsstat) {
_device->statfs(path, fsstat);
}
void FilesystemImpl::createSymlink(const bf::path &to, const bf::path &from) {
auto parent = LoadDir(from.parent_path());
parent->createSymlink(from.filename().native(), to);
}
void FilesystemImpl::readSymlink(const bf::path &path, char *buf, size_t size) {
string target = LoadSymlink(path)->target().native();
std::memcpy(buf, target.c_str(), std::min(target.size()+1, size));
buf[size-1] = '\0';
}

View File

@ -10,6 +10,7 @@
namespace fspp {
class Node;
class File;
class Symlink;
class OpenFile;
class FilesystemImpl: public fuse::Filesystem {
@ -39,10 +40,13 @@ public:
std::unique_ptr<std::vector<Dir::Entry>> readDir(const boost::filesystem::path &path) override;
void utimens(const boost::filesystem::path &path, const timespec times[2]) override;
void statfs(const boost::filesystem::path &path, struct statvfs *fsstat) override;
void createSymlink(const boost::filesystem::path &to, const boost::filesystem::path &from) override;
void readSymlink(const boost::filesystem::path &path, char *buf, size_t size) override;
private:
std::unique_ptr<File> LoadFile(const boost::filesystem::path &path);
std::unique_ptr<Dir> LoadDir(const boost::filesystem::path &path);
std::unique_ptr<Symlink> LoadSymlink(const boost::filesystem::path &path);
int openFile(const File &file, int flags);
Device *_device;