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)) {
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;
}
@ -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);
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;
}
@ -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)) {
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;
};

View File

@ -94,7 +94,8 @@ struct Vfs::Directory_service
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;
@ -103,7 +104,7 @@ struct Vfs::Directory_service
** 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 };
@ -141,7 +142,7 @@ struct Vfs::Directory_service
** 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,
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
* under the terms of the GNU General Public License version 2.
@ -1087,10 +1087,10 @@ namespace {
if (verbose)
PWRN("stat syscall failed for path \"%s\"", path);
switch (sysio()->error.stat) {
case Vfs::Directory_service::STAT_OK: /* never reached */
case Vfs::Directory_service::STAT_ERR_NO_ENTRY: errno = ENOENT; break;
case Vfs::Directory_service::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1;
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);
@ -1165,9 +1165,16 @@ namespace {
Genode::strncpy(sysio()->symlink_in.oldpath, oldpath, sizeof(sysio()->symlink_in.oldpath));
Genode::strncpy(sysio()->symlink_in.newpath, newpath, sizeof(sysio()->symlink_in.newpath));
if (!noux_syscall(Noux::Session::SYSCALL_SYMLINK)) {
PERR("symlink error");
/* XXX set errno */
return -1;
PWRN("symlink syscall failed for path \"%s\"", newpath);
typedef Vfs::Directory_service::Symlink_result Result;
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;
@ -1707,9 +1714,13 @@ namespace {
sysio()->readlink_in.bufsiz = bufsiz;
if (!noux_syscall(Noux::Session::SYSCALL_READLINK)) {
PWRN("readlink syscall failed for \"%s\"", path);
/* XXX set errno */
return -1;
PWRN("readlink syscall failed for path \"%s\"", path);
typedef Vfs::Directory_service::Readlink_result Result;
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);