From 5f1a66b90cb81b2ad12617b49a2a03a764051e59 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Tue, 24 Jul 2012 18:47:16 +0200 Subject: [PATCH] Noux: handle 'not a directory' error in fchdir() Fixes #298. --- ports/include/noux_session/sysio.h | 2 ++ ports/src/lib/libc_noux/plugin.cc | 6 ++++-- ports/src/noux/vfs_io_channel.h | 18 +++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ports/include/noux_session/sysio.h b/ports/include/noux_session/sysio.h index 753afd9c8..af1732f71 100644 --- a/ports/include/noux_session/sysio.h +++ b/ports/include/noux_session/sysio.h @@ -273,6 +273,7 @@ namespace Noux { 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 }; enum Execve_error { EXECVE_NONEXISTENT = NUM_GENERAL_ERRORS }; @@ -286,6 +287,7 @@ namespace Noux { union { General_error general; Stat_error stat; + Fchdir_error fchdir; Fcntl_error fcntl; Open_error open; Execve_error execve; diff --git a/ports/src/lib/libc_noux/plugin.cc b/ports/src/lib/libc_noux/plugin.cc index 6d0a08aab..1a5edf49f 100644 --- a/ports/src/lib/libc_noux/plugin.cc +++ b/ports/src/lib/libc_noux/plugin.cc @@ -983,8 +983,10 @@ namespace { { sysio()->fchdir_in.fd = noux_fd(fd->context); if (!noux()->syscall(Noux::Session::SYSCALL_FCHDIR)) { - PERR("fchdir error"); - /* XXX set errno */ + switch (sysio()->error.fchdir) { + case Noux::Sysio::FCHDIR_ERR_NOT_DIR: errno = ENOTDIR; break; + default: errno = EPERM; break; + } return -1; } diff --git a/ports/src/noux/vfs_io_channel.h b/ports/src/noux/vfs_io_channel.h index 2b8619fa4..f6f731504 100644 --- a/ports/src/noux/vfs_io_channel.h +++ b/ports/src/noux/vfs_io_channel.h @@ -56,7 +56,13 @@ namespace Noux { bool fstat(Sysio *sysio) { - return _fh->ds()->stat(sysio, _leaf_path.base()); + /* + * 'sysio.stat_in' is not used in '_fh->ds()->stat()', + * so no 'sysio' member translation is needed here + */ + bool result = _fh->ds()->stat(sysio, _leaf_path.base()); + sysio->fstat_out.st = sysio->stat_out.st; + return result; } bool fcntl(Sysio *sysio) @@ -78,6 +84,16 @@ namespace Noux { bool fchdir(Sysio *sysio, Pwd *pwd) { + sysio->fstat_in.fd = sysio->fchdir_in.fd; + + fstat(sysio); + + if ((sysio->fstat_out.st.mode & Sysio::STAT_MODE_DIRECTORY) != + Sysio::STAT_MODE_DIRECTORY) { + sysio->error.fchdir = Sysio::FCHDIR_ERR_NOT_DIR; + return false; + } + pwd->pwd(_path.base()); return true; }