genode/repos/dde_rump/src/server/rump_fs/file.h

182 lines
3.6 KiB
C++

/**
* \brief File node
* \author Norman Feske
* \author Christian Helmuth
* \auhtor Sebastian Sumpf
* \date 2013-11-11
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _FILE_H_
#define _FILE_H_
/* Genode includes */
#include <file_system/util.h>
#include "node.h"
namespace Rump_fs {
class File;
}
class Rump_fs::File : public Node
{
private:
int _fd;
int _access_mode(Mode const &mode)
{
switch (mode) {
case STAT_ONLY:
case READ_ONLY: return O_RDONLY;
case WRITE_ONLY: return O_WRONLY;
case READ_WRITE: return O_RDWR;
default: return O_RDONLY;
}
}
unsigned long _inode(int dir, char const *name, bool create)
{
int ret;
if (create) {
mode_t ugo = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
ret = rump_sys_mknodat(dir, name, S_IFREG | ugo, 0);
if (ret == -1 && errno != EEXIST)
throw No_space();
}
struct stat s;
ret = rump_sys_fstatat(dir, name, &s, 0);
if (ret == -1)
throw Lookup_failed();
return s.st_ino;
}
unsigned long _inode_path(char const *path)
{
int ret;
struct stat s;
ret = rump_sys_stat(path, &s);
if (ret == -1)
throw Lookup_failed();
return s.st_ino;
}
int _open(int dir, char const *name, Mode mode)
{
int fd = rump_sys_openat(dir, name, _access_mode(mode));
if (fd == -1)
throw Lookup_failed();
return fd;
}
int _open_path(char const *path, Mode mode)
{
int fd = rump_sys_open(path, _access_mode(mode));
if (fd == -1)
throw Lookup_failed();
return fd;
}
public:
File(int dir,
char const *name,
Mode mode,
bool create)
: Node(_inode(dir, name, create)),
_fd(_open(dir, name, mode))
{
Node::name(name);
}
File(char const *path, Mode mode)
:
Node(_inode_path(path)),
_fd(_open_path(path, mode))
{
Node::name(basename(path));
}
virtual ~File() { rump_sys_close(_fd); }
void update_modification_time(Timestamp const time) override
{
struct timespec ts[2] = {
{ .tv_sec = 0, .tv_nsec = 0 },
{ .tv_sec = time.value, .tv_nsec = 0 }
};
/* silently igore error */
rump_sys_futimens(_fd, (const timespec*)&ts);
}
size_t read(char *dst, size_t len, seek_off_t seek_offset) override
{
ssize_t ret;
if (seek_offset == SEEK_TAIL)
ret = rump_sys_lseek(_fd, -len, SEEK_END) != -1 ?
rump_sys_read(_fd, dst, len) : 0;
else
ret = rump_sys_pread(_fd, dst, len, seek_offset);
return ret == -1 ? 0 : ret;
}
size_t write(char const *src, size_t len, seek_off_t seek_offset) override
{
ssize_t ret;
if (seek_offset == SEEK_TAIL)
ret = rump_sys_lseek(_fd, 0, SEEK_END) != -1 ?
rump_sys_write(_fd, src, len) : 0;
else
ret = rump_sys_pwrite(_fd, src, len, seek_offset);
return ret == -1 ? 0 : ret;
}
virtual Status status() override
{
struct stat st { };
if (rump_sys_fstat(_fd, &st) < 0) {
st.st_size = 0;
st.st_mtime = 0;
}
return {
.size = (file_size_t)st.st_size,
.type = File_system::Node_type::CONTINUOUS_FILE,
.rwx = { .readable = (st.st_mode & S_IRUSR),
.writeable = (st.st_mode & S_IWUSR),
.executable = (st.st_mode & S_IXUSR) },
.inode = inode(),
.modification_time = { (int64_t)st.st_mtime }
};
}
void truncate(file_size_t size) override
{
rump_sys_ftruncate(_fd, size);
mark_as_updated();
}
};
#endif /* _FILE_H_ */