Do not throw exceptions during with_libc

This commit is contained in:
Ehmry - 2019-02-20 15:19:18 +01:00
parent 2c977bdc1e
commit 9bd6733f75
2 changed files with 74 additions and 38 deletions

View File

@ -11,6 +11,10 @@ const
const FsH = "<file_system_session/file_system_session.h>"
#[
# Cannot throw C++ exceptions from within Libc::with_libc
proc raiseInvalidHandle() {.noreturn, header: FsH,
importcpp: "throw File_system::Invalid_handle()".}
proc raiseInvalidName() {.noreturn, header: FsH,
@ -20,17 +24,22 @@ proc raiseLookupFailed() {.noreturn, header: FsH,
proc raisePermissionDenied() {.noreturn, header: FsH,
importcpp: "throw File_system::Permission_denied()".}
template permissionsAssert(cond: bool) =
if not cond: raisePermissionDenied()
template lookupAssert(cond: bool) =
if not cond: raiseLookupFailed()
]#
template assertInvalidHandle(cond: bool) =
if not cond: return (not Handle(0))
template permissionsAssert(cond: bool) =
if not cond: return (not Handle(0))
template validPathAssert(name: string) =
if name[name.low] != '/' or name[name.high] == '/': raiseLookupFailed()
if name[name.low] != '/' or name[name.high] == '/':
return (not Handle(0))
template validNameAssert(name: string) =
if name.contains '/': raiseInvalidName()
if name.contains '/': return (not Handle(0))
type
FsCapability {.
@ -122,18 +131,17 @@ proc inode(node: Node): culong = node.path.toKey.culong
template fsRpc(session: SessionPtr; body: untyped) =
try: body
except KeyError:
raiseLookupFailed()
#except KeyError:
# raiseLookupFailed()
except:
echo "failed, ", getCurrentExceptionMsg()
raisePermissionDenied()
proc nodeProc(session: pointer; path: cstring): Handle {.exportc.} =
let session = cast[SessionPtr](session)
fsRpc session:
result = session.nextId
if path == "/":
session.nodes[result] = Node(path: "", kind: dirNode)
session.nodes[result] = Node(path: "/", kind: dirNode)
else:
var path = $path
validPathAssert path
@ -153,12 +161,13 @@ proc statusProc(state: pointer; handle: Handle): Status {.exportc.} =
fsRpc session:
var st: Status
let node = session.nodes[handle]
st.inode = node.inode
st.inode = 0
st.mode = DirMode
if node.path != "":
if node.path != "/":
session.apply(node.path) do (id: BlobId; size: BiggestInt):
st.size = (culonglong)size
st.mode = FileMode
st.inode = node.inode
result = st
proc dirProc(state: pointer; path: cstring; create: cint): Handle {.exportc.} =
@ -173,7 +182,7 @@ proc dirProc(state: pointer; path: cstring; create: cint): Handle {.exportc.} =
validPathAssert path
path = path.strip(chars={'/'})
if session.fsSet.contains path:
raiseLookupFailed()
return (not Handle(0))
n = Node(path: path, kind: dirNode)
result = session.nextId
session.nodes[result] = n
@ -186,8 +195,7 @@ proc fileProc(state: pointer; dirH: Handle; name: cstring; mode: cuint; create:
validNameAssert name
var n: Node
let dir = session.nodes[dirH]
if dir.kind != dirNode:
raiseInvalidHandle()
assertInvalidHandle(dir.kind == dirNode)
let path = if dir.path == "": name else: dir.path & "/" & name
var success = false
session.apply(path) do (id: BlobId; size: BiggestInt):
@ -195,31 +203,31 @@ proc fileProc(state: pointer; dirH: Handle; name: cstring; mode: cuint; create:
n = Node(path: path, kind: fileNode, id: id, size: size, stream: stream)
success = true
if not success:
raiseLookupFailed()
return (not Handle(0))
result = session.nextId
session.nodes[result] = n
proc closeProc(state: pointer; h: Handle) {.exportc.} =
let session = cast[ptr SessionObj](state)
fsRpc session:
let n = session.nodes[h]
session.nodes.del h
case n.kind
of fileNode:
close n.stream
else:
discard
var n: Node
if session.nodes.take(h, n):
case n.kind
of fileNode:
close n.stream
else:
discard
proc unlinkProc(state: pointer; dirH: Handle; name: cstring) {.exportc.} =
raisePermissionDenied()
discard
proc truncateProc(state: pointer; file: Handle, size: cuint) {.exportc.} =
raisePermissionDenied()
discard
proc moveProc(state: pointer;
from_dir: Handle; from_name: cstring;
to_dir: Handle; to_name: cstring) {.exportc.} =
raisePermissionDenied()
discard
proc processPacket(session: SessionRef; pkt: var FsPacket) =
## Process a File_system packet from the client.
@ -280,7 +288,7 @@ componentConstructHook = proc(env: GenodeEnv) =
proc createSession(env: GenodeEnv; store: BlobStore; id: ServerId; label: string; setId: SetId; txBufSize: int) =
let
fsSet = store.loadSet(setId)
fsSet = store.load setId
session = env.newSession(store, label, setId, fsSet, txBufSize)
cap = env.ep.manage session
sessions[id] = session
@ -351,7 +359,7 @@ componentConstructHook = proc(env: GenodeEnv) =
idStr = pAttrs["root"]
policySetId = toSetId idStr
if session.fsSetId != policySetId:
let newSet = store.loadSet policySetId
let newSet = store.load policySetId
session.fsSet = newSet
session.fsSetId = policySetId
echo idStr, " is new root of ", session.label

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
* Copyright (C) 2017-2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -52,23 +52,51 @@ struct File_system::SessionComponentBase : File_system::Session_rpc_object
** File_system session interface **
***********************************/
Node_handle node(File_system::Path const &path) override {
return Node_handle{ nodeProc(state, path.string()) }; }
Node_handle node(File_system::Path const &path) override
{
Node_handle handle { ~0 };
Libc::with_libc([&] {
handle = Node_handle{ nodeProc(state, path.string()) }; });
return handle;
}
Dir_handle dir(File_system::Path const &path, bool create) override {
return Dir_handle{ dirProc(state, path.string(), create) }; }
Dir_handle dir(File_system::Path const &path, bool create) override
{
Dir_handle handle { ~0 };
Libc::with_libc([&] {
handle = Dir_handle{ dirProc(state, path.string(), create) }; });
if (handle.value == ~0)
throw Lookup_failed();
return handle;
}
File_handle file(Dir_handle dir, Name const &name, Mode mode, bool create) override {
return File_handle{ fileProc(state, dir.value, name.string(), unsigned(mode), create) }; }
File_handle file(Dir_handle dir, Name const &name, Mode mode, bool create) override
{
File_handle handle { ~0 };
Libc::with_libc([&] {
handle = File_handle{ fileProc(state, dir.value, name.string(), unsigned(mode), create) }; });
if (handle.value == ~0)
throw Lookup_failed();
return handle;
}
Symlink_handle symlink(Dir_handle, Name const &name, bool create) override {
throw Lookup_failed(); }
void close(Node_handle handle) override {
closeProc(state, handle.value); }
void close(Node_handle handle) override
{
Libc::with_libc([&] () { closeProc(state, handle.value); });
}
Status status(Node_handle handle) override {
return statusProc(state, handle.value); }
Status status(Node_handle handle) override
{
Status stat { };
Libc::with_libc([&] () {
stat = statusProc(state, handle.value); });
if (stat.inode == 0)
throw Invalid_handle();
return stat;
}
void control(Node_handle h, Control) override { }