lib/vfs: new permissions errors

New errors STAT_ERR_NO_PERM, DIRENT_ERR_NO_PERM, and READLINK_NO_PERM to
distinguish lookup errors from permissions or other errors.

Issue #1751
This commit is contained in:
Emery Hemingway 2016-04-01 11:42:31 +02:00 committed by Christian Helmuth
parent 14ca140135
commit b8e52189d5
3 changed files with 29 additions and 14 deletions

View File

@ -385,6 +385,7 @@ int Libc::Vfs_plugin::stat(char const *path, struct stat *buf)
switch (_root_dir.stat(path, stat)) { switch (_root_dir.stat(path, stat)) {
case Result::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1; case Result::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1;
case Result::STAT_ERR_NO_PERM: errno = EACCES; return -1;
case Result::STAT_OK: break; case Result::STAT_OK: break;
} }
@ -459,7 +460,8 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf,
unsigned const index = handle->seek() / sizeof(Vfs::Directory_service::Dirent); unsigned const index = handle->seek() / sizeof(Vfs::Directory_service::Dirent);
switch (handle->ds().dirent(fd->fd_path, index, dirent_out)) { switch (handle->ds().dirent(fd->fd_path, index, dirent_out)) {
case Result::DIRENT_ERR_INVALID_PATH: /* XXX errno */ return -1; case Result::DIRENT_ERR_INVALID_PATH: errno = ENOENT; return -1;
case Result::DIRENT_ERR_NO_PERM: errno = EACCES; return -1;
case Result::DIRENT_OK: break; case Result::DIRENT_OK: break;
} }
@ -745,6 +747,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, size_t buf_size)
switch (_root_dir.readlink(path, buf, buf_size, out_len)) { switch (_root_dir.readlink(path, buf, buf_size, out_len)) {
case Result::READLINK_ERR_NO_ENTRY: errno = ENOENT; return -1; case Result::READLINK_ERR_NO_ENTRY: errno = ENOENT; return -1;
case Result::READLINK_ERR_NO_PERM: errno = EACCES; return -1;
case Result::READLINK_OK: break; case Result::READLINK_OK: break;
}; };

View File

@ -94,7 +94,8 @@ struct Vfs::Directory_service
unsigned device; unsigned device;
}; };
enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS, STAT_OK }; enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS,
STAT_ERR_NO_PERM, STAT_OK };
virtual Stat_result stat(char const *path, Stat &) = 0; virtual Stat_result stat(char const *path, Stat &) = 0;
@ -103,7 +104,7 @@ struct Vfs::Directory_service
** Dirent ** ** Dirent **
************/ ************/
enum Dirent_result { DIRENT_ERR_INVALID_PATH, DIRENT_OK }; enum Dirent_result { DIRENT_ERR_INVALID_PATH, DIRENT_ERR_NO_PERM, DIRENT_OK };
enum { DIRENT_MAX_NAME_LEN = 128 }; enum { DIRENT_MAX_NAME_LEN = 128 };
@ -141,7 +142,7 @@ struct Vfs::Directory_service
** Readlink ** ** Readlink **
**************/ **************/
enum Readlink_result { READLINK_ERR_NO_ENTRY, READLINK_OK }; enum Readlink_result { READLINK_ERR_NO_ENTRY, READLINK_ERR_NO_PERM, READLINK_OK };
virtual Readlink_result readlink(char const *path, char *buf, virtual Readlink_result readlink(char const *path, char *buf,
file_size buf_size, file_size &out_len) = 0; file_size buf_size, file_size &out_len) = 0;

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2013 Genode Labs GmbH * Copyright (C) 2011-2016 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -1087,10 +1087,10 @@ namespace {
if (verbose) if (verbose)
PWRN("stat syscall failed for path \"%s\"", path); PWRN("stat syscall failed for path \"%s\"", path);
switch (sysio()->error.stat) { switch (sysio()->error.stat) {
case Vfs::Directory_service::STAT_OK: /* never reached */ case Vfs::Directory_service::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1;
case Vfs::Directory_service::STAT_ERR_NO_ENTRY: errno = ENOENT; break; case Vfs::Directory_service::STAT_ERR_NO_PERM: errno = EACCES; return -1;
case Vfs::Directory_service::STAT_OK: break; /* never reached */
} }
return -1;
} }
_sysio_to_stat_struct(sysio(), buf); _sysio_to_stat_struct(sysio(), buf);
@ -1165,9 +1165,16 @@ namespace {
Genode::strncpy(sysio()->symlink_in.oldpath, oldpath, sizeof(sysio()->symlink_in.oldpath)); Genode::strncpy(sysio()->symlink_in.oldpath, oldpath, sizeof(sysio()->symlink_in.oldpath));
Genode::strncpy(sysio()->symlink_in.newpath, newpath, sizeof(sysio()->symlink_in.newpath)); Genode::strncpy(sysio()->symlink_in.newpath, newpath, sizeof(sysio()->symlink_in.newpath));
if (!noux_syscall(Noux::Session::SYSCALL_SYMLINK)) { if (!noux_syscall(Noux::Session::SYSCALL_SYMLINK)) {
PERR("symlink error"); PWRN("symlink syscall failed for path \"%s\"", newpath);
/* XXX set errno */ typedef Vfs::Directory_service::Symlink_result Result;
return -1; switch (sysio()->error.symlink) {
case Result::SYMLINK_ERR_NO_ENTRY: errno = ENOENT; return -1;
case Result::SYMLINK_ERR_EXISTS: errno = EEXIST; return -1;
case Result::SYMLINK_ERR_NO_SPACE: errno = ENOSPC; return -1;
case Result::SYMLINK_ERR_NO_PERM: errno = EPERM; return -1;
case Result::SYMLINK_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; return -1;
case Result::SYMLINK_OK: break;
}
} }
return 0; return 0;
@ -1707,9 +1714,13 @@ namespace {
sysio()->readlink_in.bufsiz = bufsiz; sysio()->readlink_in.bufsiz = bufsiz;
if (!noux_syscall(Noux::Session::SYSCALL_READLINK)) { if (!noux_syscall(Noux::Session::SYSCALL_READLINK)) {
PWRN("readlink syscall failed for \"%s\"", path); PWRN("readlink syscall failed for path \"%s\"", path);
/* XXX set errno */ typedef Vfs::Directory_service::Readlink_result Result;
return -1; switch (sysio()->error.readlink) {
case Result::READLINK_ERR_NO_ENTRY: errno = ENOENT; return -1;
case Result::READLINK_ERR_NO_PERM: errno = EPERM; return -1;
case Result::READLINK_OK: break;
}
} }
ssize_t size = Genode::min((size_t)sysio()->readlink_out.count, bufsiz); ssize_t size = Genode::min((size_t)sysio()->readlink_out.count, bufsiz);