mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
parent
280fc59edf
commit
dcfcbce856
@ -77,6 +77,7 @@ namespace Libc {
|
||||
virtual void freeaddrinfo(struct ::addrinfo *res);
|
||||
virtual int fstat(File_descriptor *, struct stat *buf);
|
||||
virtual int fsync(File_descriptor *);
|
||||
virtual int ftruncate(File_descriptor *, ::off_t length);
|
||||
virtual int getaddrinfo(const char *node, const char *service,
|
||||
const struct ::addrinfo *hints,
|
||||
struct ::addrinfo **res);
|
||||
|
@ -50,7 +50,6 @@ DUMMY(-1, _fpathconf)
|
||||
DUMMY(-1, fpathconf)
|
||||
DUMMY(-1, freebsd7___semctl)
|
||||
DUMMY(-1, fstatat)
|
||||
DUMMY(-1, ftruncate)
|
||||
DUMMY(-1, getcontext)
|
||||
DUMMY( 0, __getcwd)
|
||||
DUMMY( 0, getdtablesize)
|
||||
|
@ -219,6 +219,10 @@ extern "C" int fsync(int libc_fd) {
|
||||
FD_FUNC_WRAPPER(fsync, libc_fd); }
|
||||
|
||||
|
||||
extern "C" int ftruncate(int libc_fd, ::off_t length) {
|
||||
FD_FUNC_WRAPPER(ftruncate, libc_fd, length); }
|
||||
|
||||
|
||||
extern "C" int getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
|
@ -154,6 +154,7 @@ DUMMY(int, -1, fchdir, (File_descriptor *));
|
||||
DUMMY(int, -1, fcntl, (File_descriptor *, int cmd, long arg));
|
||||
DUMMY(int, -1, fstat, (File_descriptor *, struct stat *));
|
||||
DUMMY(int, -1, fsync, (File_descriptor *));
|
||||
DUMMY(int, -1, ftruncate, (File_descriptor *, ::off_t));
|
||||
DUMMY(ssize_t, -1, getdirentries, (File_descriptor *, char *, ::size_t, ::off_t *));
|
||||
DUMMY(int, -1, getpeername, (File_descriptor *, struct sockaddr *, socklen_t *));
|
||||
DUMMY(int, -1, getsockname, (File_descriptor *, struct sockaddr *, socklen_t *));
|
||||
|
@ -312,6 +312,33 @@ class Plugin : public Libc::Plugin
|
||||
}
|
||||
}
|
||||
|
||||
int ftruncate(Libc::File_descriptor *fd, ::off_t length)
|
||||
{
|
||||
using namespace Ffat;
|
||||
|
||||
/* 'f_truncate()' truncates to the current seek pointer */
|
||||
|
||||
if (lseek(fd, length, SEEK_SET) == -1)
|
||||
return -1;
|
||||
|
||||
FRESULT res = f_truncate(_get_ffat_file(fd));
|
||||
|
||||
switch(res) {
|
||||
case FR_OK:
|
||||
return 0;
|
||||
case FR_DISK_ERR:
|
||||
case FR_INT_ERR:
|
||||
case FR_NOT_READY:
|
||||
case FR_INVALID_OBJECT:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
default:
|
||||
/* not supposed to occur according to the libffat documentation */
|
||||
PERR("f_truncate() returned an unexpected error code");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t getdirentries(Libc::File_descriptor *fd, char *buf,
|
||||
::size_t nbytes, ::off_t *basep)
|
||||
{
|
||||
|
@ -356,6 +356,25 @@ class Plugin : public Libc::Plugin
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ftruncate(Libc::File_descriptor *fd, ::off_t length)
|
||||
{
|
||||
File_system::Node_handle node_handle = context(fd)->node_handle();
|
||||
File_system::File_handle &file_handle =
|
||||
static_cast<File_system::File_handle&>(node_handle);
|
||||
|
||||
try {
|
||||
file_system()->truncate(file_handle, length);
|
||||
} catch (File_system::Invalid_handle) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
} catch (File_system::Permission_denied) {
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* *basep does not get initialized by the libc and is therefore
|
||||
* useless for determining a specific directory index. This
|
||||
|
@ -31,6 +31,13 @@ namespace Ffat { extern "C" {
|
||||
#include <ffat/ff.h>
|
||||
} }
|
||||
|
||||
/*
|
||||
* This macro is defined in later versions of the FatFs lib, but not in the
|
||||
* one currently used for Genode.
|
||||
*/
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
@ -767,14 +774,44 @@ namespace File_system {
|
||||
|
||||
using namespace Ffat;
|
||||
|
||||
FRESULT res = f_truncate(file->ffat_fil());
|
||||
/* 'f_truncate()' truncates to the current seek pointer */
|
||||
|
||||
FRESULT res = f_lseek(file->ffat_fil(), size);
|
||||
|
||||
switch(res) {
|
||||
case FR_OK:
|
||||
/* according to the FatFs documentation this can happen */
|
||||
if (f_tell(file->ffat_fil()) != size) {
|
||||
PERR("f_lseek() could not seek to offset %llu", size);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case FR_DISK_ERR:
|
||||
PERR("f_lseek() failed with error code FR_DISK_ERR");
|
||||
return;
|
||||
case FR_INT_ERR:
|
||||
PERR("f_lseek() failed with error code FR_INT_ERR");
|
||||
return;
|
||||
case FR_NOT_READY:
|
||||
PERR("f_lseek() failed with error code FR_NOT_READY");
|
||||
return;
|
||||
case FR_INVALID_OBJECT:
|
||||
PERR("f_lseek() failed with error code FR_INVALID_OBJECT");
|
||||
throw Invalid_handle();
|
||||
default:
|
||||
/* not supposed to occur according to the libffat documentation */
|
||||
PERR("f_lseek() returned an unexpected error code");
|
||||
return;
|
||||
}
|
||||
|
||||
res = f_truncate(file->ffat_fil());
|
||||
|
||||
switch(res) {
|
||||
case FR_OK:
|
||||
return;
|
||||
case FR_INVALID_OBJECT:
|
||||
PERR("f_truncate() failed with error code FR_INVALID_OBJECT");
|
||||
return;
|
||||
throw Invalid_handle();
|
||||
case FR_DISK_ERR:
|
||||
PERR("f_truncate() failed with error code FR_DISK_ERR");
|
||||
return;
|
||||
|
@ -47,6 +47,7 @@ int main(int argc, char *argv[])
|
||||
char const *file_name = "test.tst";
|
||||
char const *file_name2 = "test2.tst";
|
||||
char const *file_name3 = "test3.tst";
|
||||
char const *file_name4 = "test4.tst";
|
||||
char const *pattern = "a single line of text";
|
||||
|
||||
size_t pattern_size = strlen(pattern) + 1;
|
||||
@ -165,6 +166,20 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* test 'ftruncate()' */
|
||||
CALL_AND_CHECK(fd, open(file_name4, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name4);
|
||||
CALL_AND_CHECK(ret, ftruncate(fd, 100), ret == 0, ""); /* increase size */
|
||||
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
||||
CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
|
||||
(ret == 0) && (stat_buf.st_size == 100),
|
||||
"file_name=%s", file_name4);
|
||||
CALL_AND_CHECK(fd, open(file_name4, O_WRONLY), fd >= 0, "file_name=%s", file_name4);
|
||||
CALL_AND_CHECK(ret, ftruncate(fd, 10), ret == 0, ""); /* decrease size */
|
||||
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
||||
CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
|
||||
(ret == 0) && (stat_buf.st_size == 10),
|
||||
"file_name=%s", file_name4);
|
||||
|
||||
if (i < (iterations - 1))
|
||||
sleep(2);
|
||||
}
|
||||
|
@ -88,6 +88,14 @@ namespace File_system {
|
||||
}
|
||||
|
||||
file_size_t length() const { return _length; }
|
||||
|
||||
void truncate(file_size_t size)
|
||||
{
|
||||
if (size < _chunk.used_size())
|
||||
_chunk.truncate(size);
|
||||
else
|
||||
_length = size;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,15 @@ namespace File_system {
|
||||
destroy(env()->heap(), node);
|
||||
}
|
||||
|
||||
void truncate(File_handle, file_size_t size) { }
|
||||
void truncate(File_handle file_handle, file_size_t size)
|
||||
{
|
||||
if (!_writable)
|
||||
throw Permission_denied();
|
||||
|
||||
File *file = _handle_registry.lookup_and_lock(file_handle);
|
||||
Node_lock_guard file_guard(*file);
|
||||
file->truncate(size);
|
||||
}
|
||||
|
||||
void move(Dir_handle from_dir_handle, Name const &from_name,
|
||||
Dir_handle to_dir_handle, Name const &to_name)
|
||||
|
@ -40,6 +40,7 @@ namespace Noux {
|
||||
SYSCALL_STAT,
|
||||
SYSCALL_LSTAT,
|
||||
SYSCALL_FSTAT,
|
||||
SYSCALL_FTRUNCATE,
|
||||
SYSCALL_FCNTL,
|
||||
SYSCALL_OPEN,
|
||||
SYSCALL_CLOSE,
|
||||
@ -83,6 +84,7 @@ namespace Noux {
|
||||
NOUX_DECL_SYSCALL_NAME(STAT)
|
||||
NOUX_DECL_SYSCALL_NAME(LSTAT)
|
||||
NOUX_DECL_SYSCALL_NAME(FSTAT)
|
||||
NOUX_DECL_SYSCALL_NAME(FTRUNCATE)
|
||||
NOUX_DECL_SYSCALL_NAME(FCNTL)
|
||||
NOUX_DECL_SYSCALL_NAME(OPEN)
|
||||
NOUX_DECL_SYSCALL_NAME(CLOSE)
|
||||
|
@ -271,126 +271,130 @@ namespace Noux {
|
||||
char ai_canonname[255];
|
||||
};
|
||||
|
||||
enum General_error { ERR_FD_INVALID, NUM_GENERAL_ERRORS };
|
||||
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
||||
enum Fchdir_error { FCHDIR_ERR_NOT_DIR = NUM_GENERAL_ERRORS };
|
||||
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = NUM_GENERAL_ERRORS };
|
||||
enum Open_error { OPEN_ERR_UNACCESSIBLE, OPEN_ERR_NO_PERM,
|
||||
OPEN_ERR_EXISTS };
|
||||
enum Execve_error { EXECVE_NONEXISTENT = NUM_GENERAL_ERRORS };
|
||||
enum Unlink_error { UNLINK_ERR_NO_ENTRY, UNLINK_ERR_NO_PERM };
|
||||
enum Rename_error { RENAME_ERR_NO_ENTRY, RENAME_ERR_CROSS_FS,
|
||||
RENAME_ERR_NO_PERM };
|
||||
enum Mkdir_error { MKDIR_ERR_EXISTS, MKDIR_ERR_NO_ENTRY,
|
||||
MKDIR_ERR_NO_SPACE, MKDIR_ERR_NO_PERM,
|
||||
MKDIR_ERR_NAME_TOO_LONG};
|
||||
enum General_error { ERR_FD_INVALID, NUM_GENERAL_ERRORS };
|
||||
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
||||
enum Fchdir_error { FCHDIR_ERR_NOT_DIR = NUM_GENERAL_ERRORS };
|
||||
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = NUM_GENERAL_ERRORS };
|
||||
enum Ftruncate_error { FTRUNCATE_ERR_NO_PERM = NUM_GENERAL_ERRORS };
|
||||
enum Open_error { OPEN_ERR_UNACCESSIBLE, OPEN_ERR_NO_PERM,
|
||||
OPEN_ERR_EXISTS };
|
||||
enum Execve_error { EXECVE_NONEXISTENT = NUM_GENERAL_ERRORS };
|
||||
enum Unlink_error { UNLINK_ERR_NO_ENTRY, UNLINK_ERR_NO_PERM };
|
||||
enum Rename_error { RENAME_ERR_NO_ENTRY, RENAME_ERR_CROSS_FS,
|
||||
RENAME_ERR_NO_PERM };
|
||||
enum Mkdir_error { MKDIR_ERR_EXISTS, MKDIR_ERR_NO_ENTRY,
|
||||
MKDIR_ERR_NO_SPACE, MKDIR_ERR_NO_PERM,
|
||||
MKDIR_ERR_NAME_TOO_LONG};
|
||||
|
||||
union {
|
||||
General_error general;
|
||||
Stat_error stat;
|
||||
Fchdir_error fchdir;
|
||||
Fcntl_error fcntl;
|
||||
Open_error open;
|
||||
Execve_error execve;
|
||||
Unlink_error unlink;
|
||||
Rename_error rename;
|
||||
Mkdir_error mkdir;
|
||||
General_error general;
|
||||
Stat_error stat;
|
||||
Fchdir_error fchdir;
|
||||
Fcntl_error fcntl;
|
||||
Ftruncate_error ftruncate;
|
||||
Open_error open;
|
||||
Execve_error execve;
|
||||
Unlink_error unlink;
|
||||
Rename_error rename;
|
||||
Mkdir_error mkdir;
|
||||
} error;
|
||||
|
||||
union {
|
||||
|
||||
SYSIO_DECL(getcwd, { }, { Path path; });
|
||||
SYSIO_DECL(getcwd, { }, { Path path; });
|
||||
|
||||
SYSIO_DECL(write, { int fd; size_t count; Chunk chunk; },
|
||||
{ size_t count; });
|
||||
SYSIO_DECL(write, { int fd; size_t count; Chunk chunk; },
|
||||
{ size_t count; });
|
||||
|
||||
SYSIO_DECL(stat, { Path path; }, { Stat st; });
|
||||
SYSIO_DECL(stat, { Path path; }, { Stat st; });
|
||||
|
||||
SYSIO_DECL(fstat, { int fd; }, { Stat st; });
|
||||
SYSIO_DECL(fstat, { int fd; }, { Stat st; });
|
||||
|
||||
SYSIO_DECL(fcntl, { int fd; long long_arg; Fcntl_cmd cmd; },
|
||||
{ int result; });
|
||||
SYSIO_DECL(ftruncate, { int fd; off_t length; }, { });
|
||||
|
||||
SYSIO_DECL(open, { Path path; int mode; }, { int fd; });
|
||||
SYSIO_DECL(fcntl, { int fd; long long_arg; Fcntl_cmd cmd; },
|
||||
{ int result; });
|
||||
|
||||
SYSIO_DECL(close, { int fd; }, { });
|
||||
SYSIO_DECL(open, { Path path; int mode; }, { int fd; });
|
||||
|
||||
SYSIO_DECL(ioctl, : Ioctl_in { int fd; }, : Ioctl_out { });
|
||||
SYSIO_DECL(close, { int fd; }, { });
|
||||
|
||||
SYSIO_DECL(lseek, { int fd; off_t offset; Lseek_whence whence; },
|
||||
{ off_t offset; });
|
||||
SYSIO_DECL(ioctl, : Ioctl_in { int fd; }, : Ioctl_out { });
|
||||
|
||||
SYSIO_DECL(dirent, { int fd; }, { Dirent entry; });
|
||||
SYSIO_DECL(lseek, { int fd; off_t offset; Lseek_whence whence; },
|
||||
{ off_t offset; });
|
||||
|
||||
SYSIO_DECL(fchdir, { int fd; }, { });
|
||||
SYSIO_DECL(dirent, { int fd; }, { Dirent entry; });
|
||||
|
||||
SYSIO_DECL(read, { int fd; size_t count; },
|
||||
{ Chunk chunk; size_t count; });
|
||||
SYSIO_DECL(fchdir, { int fd; }, { });
|
||||
|
||||
SYSIO_DECL(execve, { Path filename; Args args; Env env; }, { });
|
||||
SYSIO_DECL(read, { int fd; size_t count; },
|
||||
{ Chunk chunk; size_t count; });
|
||||
|
||||
SYSIO_DECL(select, { Select_fds fds; Select_timeout timeout; },
|
||||
{ Select_fds fds; });
|
||||
SYSIO_DECL(execve, { Path filename; Args args; Env env; }, { });
|
||||
|
||||
SYSIO_DECL(fork, { addr_t ip; addr_t sp;
|
||||
addr_t parent_cap_addr; },
|
||||
{ int pid; });
|
||||
SYSIO_DECL(select, { Select_fds fds; Select_timeout timeout; },
|
||||
{ Select_fds fds; });
|
||||
|
||||
SYSIO_DECL(getpid, { }, { int pid; });
|
||||
SYSIO_DECL(fork, { addr_t ip; addr_t sp;
|
||||
addr_t parent_cap_addr; },
|
||||
{ int pid; });
|
||||
|
||||
SYSIO_DECL(wait4, { int pid; bool nohang; },
|
||||
{ int pid; int status; });
|
||||
SYSIO_DECL(pipe, { }, { int fd[2]; });
|
||||
SYSIO_DECL(getpid, { }, { int pid; });
|
||||
|
||||
SYSIO_DECL(dup2, { int fd; int to_fd; }, { });
|
||||
SYSIO_DECL(wait4, { int pid; bool nohang; },
|
||||
{ int pid; int status; });
|
||||
SYSIO_DECL(pipe, { }, { int fd[2]; });
|
||||
|
||||
SYSIO_DECL(unlink, { Path path; }, { });
|
||||
SYSIO_DECL(dup2, { int fd; int to_fd; }, { });
|
||||
|
||||
SYSIO_DECL(rename, { Path from_path; Path to_path; }, { });
|
||||
SYSIO_DECL(unlink, { Path path; }, { });
|
||||
|
||||
SYSIO_DECL(mkdir, { Path path; int mode; }, { });
|
||||
SYSIO_DECL(rename, { Path from_path; Path to_path; }, { });
|
||||
|
||||
SYSIO_DECL(socket, { int domain; int type; int protocol; },
|
||||
{ int fd; });
|
||||
SYSIO_DECL(mkdir, { Path path; int mode; }, { });
|
||||
|
||||
SYSIO_DECL(socket, { int domain; int type; int protocol; },
|
||||
{ int fd; });
|
||||
|
||||
/* XXX for now abuse Chunk for passing optval */
|
||||
SYSIO_DECL(getsockopt, { int fd; int level; int optname; Chunk optval;
|
||||
socklen_t optlen; }, { int result; });
|
||||
SYSIO_DECL(getsockopt, { int fd; int level; int optname; Chunk optval;
|
||||
socklen_t optlen; }, { int result; });
|
||||
|
||||
SYSIO_DECL(setsockopt, { int fd; int level;
|
||||
int optname; Chunk optval;
|
||||
socklen_t optlen; }, { });
|
||||
SYSIO_DECL(setsockopt, { int fd; int level;
|
||||
int optname; Chunk optval;
|
||||
socklen_t optlen; }, { });
|
||||
|
||||
SYSIO_DECL(accept, { int fd; struct sockaddr addr; socklen_t addrlen; },
|
||||
{ int fd; });
|
||||
SYSIO_DECL(accept, { int fd; struct sockaddr addr; socklen_t addrlen; },
|
||||
{ int fd; });
|
||||
|
||||
SYSIO_DECL(bind, { int fd; struct sockaddr addr;
|
||||
socklen_t addrlen; }, { int result; });
|
||||
SYSIO_DECL(bind, { int fd; struct sockaddr addr;
|
||||
socklen_t addrlen; }, { int result; });
|
||||
|
||||
SYSIO_DECL(getpeername, { int fd; struct sockaddr addr;
|
||||
socklen_t addrlen; }, { });
|
||||
|
||||
SYSIO_DECL(listen, { int fd; int type; int backlog; },
|
||||
{ int result; });
|
||||
SYSIO_DECL(listen, { int fd; int type; int backlog; },
|
||||
{ int result; });
|
||||
|
||||
SYSIO_DECL(send, { int fd; Chunk buf; size_t len; int flags; },
|
||||
{ ssize_t len; });
|
||||
SYSIO_DECL(send, { int fd; Chunk buf; size_t len; int flags; },
|
||||
{ ssize_t len; });
|
||||
|
||||
SYSIO_DECL(sendto, { int fd; Chunk buf; size_t len; int flags;
|
||||
struct sockaddr dest_addr; socklen_t addrlen; },
|
||||
{ ssize_t len; });
|
||||
SYSIO_DECL(sendto, { int fd; Chunk buf; size_t len; int flags;
|
||||
struct sockaddr dest_addr; socklen_t addrlen; },
|
||||
{ ssize_t len; });
|
||||
|
||||
SYSIO_DECL(recv, { int fd; Chunk buf; size_t len; int flags; },
|
||||
{ size_t len; });
|
||||
SYSIO_DECL(recv, { int fd; Chunk buf; size_t len; int flags; },
|
||||
{ size_t len; });
|
||||
|
||||
SYSIO_DECL(recvfrom, { int fd; Chunk buf; size_t len; int flags;
|
||||
struct sockaddr src_addr; socklen_t addrlen; },
|
||||
{ size_t len; });
|
||||
SYSIO_DECL(recvfrom, { int fd; Chunk buf; size_t len; int flags;
|
||||
struct sockaddr src_addr; socklen_t addrlen; },
|
||||
{ size_t len; });
|
||||
|
||||
SYSIO_DECL(shutdown, { int fd; int how; }, { });
|
||||
SYSIO_DECL(shutdown, { int fd; int how; }, { });
|
||||
|
||||
SYSIO_DECL(connect, { int fd; struct sockaddr addr; socklen_t addrlen; },
|
||||
{ int result; });
|
||||
SYSIO_DECL(connect, { int fd; struct sockaddr addr; socklen_t addrlen; },
|
||||
{ int result; });
|
||||
|
||||
SYSIO_DECL(getaddrinfo, { Hostname hostname; Servname servname;
|
||||
Addrinfo hints;
|
||||
|
@ -552,6 +552,7 @@ namespace {
|
||||
int fstat(Libc::File_descriptor *, struct stat *);
|
||||
int fsync(Libc::File_descriptor *);
|
||||
int fstatfs(Libc::File_descriptor *, struct statfs *);
|
||||
int ftruncate(Libc::File_descriptor *, ::off_t);
|
||||
int fcntl(Libc::File_descriptor *, int, long);
|
||||
ssize_t getdirentries(Libc::File_descriptor *, char *, ::size_t, ::off_t *);
|
||||
::off_t lseek(Libc::File_descriptor *, ::off_t offset, int whence);
|
||||
@ -855,6 +856,21 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
int Plugin::ftruncate(Libc::File_descriptor *fd, ::off_t length)
|
||||
{
|
||||
sysio()->ftruncate_in.fd = noux_fd(fd->context);
|
||||
sysio()->ftruncate_in.length = length;
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_FTRUNCATE)) {
|
||||
switch (sysio()->error.ftruncate) {
|
||||
case Noux::Sysio::FTRUNCATE_ERR_NO_PERM: errno = EPERM; break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg)
|
||||
{
|
||||
/* copy arguments to sysio */
|
||||
|
@ -518,6 +518,7 @@ namespace Noux {
|
||||
|
||||
bool write(Sysio *sysio, Vfs_handle *handle) { return false; }
|
||||
bool read(Sysio *sysio, Vfs_handle *vfs_handle) { return false; }
|
||||
bool ftruncate(Sysio *sysio, Vfs_handle *vfs_handle) { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,9 @@ namespace Noux {
|
||||
*/
|
||||
struct File_io_service
|
||||
{
|
||||
virtual bool write(Sysio *sysio, Vfs_handle *vfs_handle) = 0;
|
||||
virtual bool read(Sysio *sysio, Vfs_handle *vfs_handle) = 0;
|
||||
virtual bool write(Sysio *sysio, Vfs_handle *vfs_handle) = 0;
|
||||
virtual bool read(Sysio *sysio, Vfs_handle *vfs_handle) = 0;
|
||||
virtual bool ftruncate(Sysio *sysio, Vfs_handle *vfs_handle) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -516,6 +516,27 @@ namespace Noux {
|
||||
source.release_packet(packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftruncate(Sysio *sysio, Vfs_handle *vfs_handle)
|
||||
{
|
||||
Fs_vfs_handle const *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
|
||||
|
||||
Sysio::Ftruncate_error error;
|
||||
|
||||
try {
|
||||
_fs.truncate(handle->file_handle(), sysio->ftruncate_in.length);
|
||||
return true;
|
||||
} catch (::File_system::Invalid_handle) {
|
||||
/* should not happen */
|
||||
error = Sysio::FTRUNCATE_ERR_NO_PERM;
|
||||
} catch (::File_system::Permission_denied) {
|
||||
error = Sysio::FTRUNCATE_ERR_NO_PERM;
|
||||
}
|
||||
|
||||
sysio->error.ftruncate = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,14 +50,15 @@ namespace Noux {
|
||||
|
||||
virtual ~Io_channel() { }
|
||||
|
||||
virtual bool write(Sysio *sysio, size_t &count) { return false; }
|
||||
virtual bool read(Sysio *sysio) { return false; }
|
||||
virtual bool fstat(Sysio *sysio) { return false; }
|
||||
virtual bool fcntl(Sysio *sysio) { return false; }
|
||||
virtual bool fchdir(Sysio *sysio, Pwd *pwd) { return false; }
|
||||
virtual bool dirent(Sysio *sysio) { return false; }
|
||||
virtual bool ioctl(Sysio *sysio) { return false; }
|
||||
virtual bool lseek(Sysio *sysio) { return false; }
|
||||
virtual bool write(Sysio *sysio, size_t &count) { return false; }
|
||||
virtual bool read(Sysio *sysio) { return false; }
|
||||
virtual bool fstat(Sysio *sysio) { return false; }
|
||||
virtual bool ftruncate(Sysio *sysio) { return false; }
|
||||
virtual bool fcntl(Sysio *sysio) { return false; }
|
||||
virtual bool fchdir(Sysio *sysio, Pwd *pwd) { return false; }
|
||||
virtual bool dirent(Sysio *sysio) { return false; }
|
||||
virtual bool ioctl(Sysio *sysio) { return false; }
|
||||
virtual bool lseek(Sysio *sysio) { return false; }
|
||||
|
||||
/**
|
||||
* Return true if an unblocking condition of the channel is satisfied
|
||||
|
@ -121,6 +121,16 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYSCALL_FTRUNCATE:
|
||||
{
|
||||
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->ftruncate_in.fd);
|
||||
|
||||
while (!io->check_unblock(true, false, false))
|
||||
_block_for_io_channel(io);
|
||||
|
||||
return io->ftruncate(_sysio);
|
||||
}
|
||||
|
||||
case SYSCALL_STAT:
|
||||
case SYSCALL_LSTAT: /* XXX implement difference between 'lstat' and 'stat' */
|
||||
|
||||
|
@ -468,6 +468,12 @@ namespace Noux {
|
||||
sysio->read_out.count = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftruncate(Sysio *sysio, Vfs_handle *handle)
|
||||
{
|
||||
PDBG("called\n");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,8 @@ namespace Noux {
|
||||
sysio->read_out.count = _terminal.read(sysio->read_out.chunk, sysio->read_in.count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftruncate(Sysio *sysio, Vfs_handle *vfs_handle) { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,9 @@ namespace Noux {
|
||||
static bool _msg(char const *sc) {
|
||||
PERR("%s not supported by file system", sc); return false; }
|
||||
|
||||
bool write(Sysio *sysio, Vfs_handle *handle) { return _msg("write"); }
|
||||
bool read(Sysio *sysio, Vfs_handle *handle) { return _msg("read"); }
|
||||
bool write(Sysio *sysio, Vfs_handle *handle) { return _msg("write"); }
|
||||
bool read(Sysio *sysio, Vfs_handle *handle) { return _msg("read"); }
|
||||
bool ftruncate(Sysio *sysio, Vfs_handle *handle) { return _msg("ftruncate"); }
|
||||
};
|
||||
static Pseudo_file_io_service fs;
|
||||
return &fs;
|
||||
|
@ -65,6 +65,11 @@ namespace Noux {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ftruncate(Sysio *sysio)
|
||||
{
|
||||
return _fh->fs()->ftruncate(sysio, _fh);
|
||||
}
|
||||
|
||||
bool fcntl(Sysio *sysio)
|
||||
{
|
||||
switch (sysio->fcntl_in.cmd) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user