2013-12-05 15:45:14 +01:00
|
|
|
/**
|
|
|
|
* \brief File node
|
|
|
|
* \author Norman Feske
|
|
|
|
* \author Christian Helmuth
|
|
|
|
* \auhtor Sebastian Sumpf
|
|
|
|
* \date 2013-11-11
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2013-12-05 15:45:14 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2013-12-05 15:45:14 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _FILE_H_
|
|
|
|
#define _FILE_H_
|
|
|
|
|
2015-04-23 21:26:54 +02:00
|
|
|
/* Genode includes */
|
|
|
|
#include <file_system/util.h>
|
|
|
|
|
2013-12-05 15:45:14 +01:00
|
|
|
#include "node.h"
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
namespace Rump_fs {
|
2013-12-05 15:45:14 +01:00
|
|
|
class File;
|
|
|
|
}
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
class Rump_fs::File : public Node
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
|
|
|
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); }
|
|
|
|
|
2019-03-20 14:52:13 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
size_t read(char *dst, size_t len, seek_off_t seek_offset) override
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2016-04-26 16:28:07 +02:00
|
|
|
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);
|
2013-12-05 15:45:14 +01:00
|
|
|
|
|
|
|
return ret == -1 ? 0 : ret;
|
|
|
|
}
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
size_t write(char const *src, size_t len, seek_off_t seek_offset) override
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2016-04-26 16:28:07 +02:00
|
|
|
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);
|
2013-12-05 15:45:14 +01:00
|
|
|
|
|
|
|
return ret == -1 ? 0 : ret;
|
|
|
|
}
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
virtual Status status() override
|
|
|
|
{
|
2019-03-20 14:52:13 +01:00
|
|
|
struct stat st;
|
|
|
|
if (rump_sys_fstat(_fd, &st) < 0) {
|
|
|
|
st.st_size = 0;
|
|
|
|
st.st_mtime = 0;
|
|
|
|
}
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
Status s;
|
|
|
|
|
|
|
|
s.inode = inode();
|
2019-03-20 14:52:13 +01:00
|
|
|
s.size = st.st_size;
|
2017-06-20 14:23:22 +02:00
|
|
|
s.mode = File_system::Status::MODE_FILE;
|
2019-03-20 14:52:13 +01:00
|
|
|
s.modification_time = { (int64_t)st.st_mtime };
|
2017-06-20 14:23:22 +02:00
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void truncate(file_size_t size) override
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
|
|
|
rump_sys_ftruncate(_fd, size);
|
|
|
|
|
|
|
|
mark_as_updated();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _FILE_H_ */
|