genode/repos/libports/src/server/fuse_fs/symlink.h
Emery Hemingway 2f1db06deb rump_fs/fuse_fs/lx_fs/ram_fs: symlink fixup
Allow symlinks to be passed to the read and write file system utilities.

Disallow writes to symlinks with offsets in file system servers, this is
to ensure that writing the target of a symlink is an atomic operation.

Fixes #1604
2015-07-21 09:40:19 +02:00

87 lines
1.5 KiB
C++

/*
* \brief Symlink file-system node
* \author Norman Feske
* \author Christian Helmuth
* \author Josef Soentgen
* \date 2013-11-26
*/
#ifndef _SYMLINK_H_
#define _SYMLINK_H_
/* local includes */
#include <node.h>
namespace File_system {
class Symlink;
}
class File_system::Symlink : public Node
{
private:
Node *_parent;
typedef Genode::Path<MAX_PATH_LEN> Path;
Path _path;
size_t _length() const
{
struct stat s;
int res = Fuse::fuse()->op.getattr(_path.base(), &s);
if (res != 0)
return 0;
return s.st_size;
}
public:
Symlink(Node *parent, char const *name, bool create = false)
:
Node(name),
_parent(parent),
_path(name, parent->name())
{ }
Status status()
{
struct stat s;
int res = Fuse::fuse()->op.getattr(_path.base(), &s);
if (res != 0)
return Status();
Status status;
status.inode = s.st_ino ? s.st_ino : 1;
status.size = s.st_size;
status.mode = File_system::Status::MODE_FILE;
return status;
}
size_t read(char *dst, size_t len, seek_off_t seek_offset)
{
int res = Fuse::fuse()->op.readlink(_path.base(), dst, len);
if (res != 0)
return 0;
return Genode::strlen(dst);
}
size_t write(char const *src, size_t len, seek_off_t seek_offset)
{
/* Ideal symlink operations are atomic. */
if (seek_offset) return 0;
int res = Fuse::fuse()->op.symlink(src, _path.base());
if (res != 0)
return 0;
return len;
}
file_size_t length() const { return _length(); }
};
#endif /* _SYMLINK_H_ */