Genode File-system server
Repurpose the File_system server from Dagfs.
This commit is contained in:
parent
a10a7a4e50
commit
319432aad9
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
/blobset
|
/blobset
|
||||||
/tests/test_set
|
/tests/test_set
|
||||||
/tests/test_http
|
/tests/test_http
|
||||||
/genode/bin/blobsets_http
|
/genode/bin/
|
||||||
|
|
|
@ -7,12 +7,12 @@ license = "AGPLv3"
|
||||||
srcDir = "src"
|
srcDir = "src"
|
||||||
binDir = "bin"
|
binDir = "bin"
|
||||||
bin = @[
|
bin = @[
|
||||||
#"dagfs_fs",
|
|
||||||
#"blobset_fs_store",
|
#"blobset_fs_store",
|
||||||
#"dagfs_server",
|
#"dagfs_server",
|
||||||
#"dagfs_tcp_store"
|
#"dagfs_tcp_store"
|
||||||
#"blobset_rom"
|
"blobsets_fs",
|
||||||
"blobsets_http"
|
"blobsets_http",
|
||||||
|
"blobsets_rom",
|
||||||
]
|
]
|
||||||
backend = "cpp"
|
backend = "cpp"
|
||||||
|
|
||||||
|
|
367
genode/src/blobsets_fs.nim
Normal file
367
genode/src/blobsets_fs.nim
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
import std/tables, std/xmltree, std/strtabs, std/strutils, std/streams, std/xmlparser
|
||||||
|
|
||||||
|
import genode, genode/signals, genode/parents, genode/servers, genode/roms
|
||||||
|
|
||||||
|
import blobsets, blobsets/filestores, ./filesystemsession
|
||||||
|
|
||||||
|
const
|
||||||
|
currentPath = currentSourcePath.rsplit("/", 1)[0]
|
||||||
|
fsComponentH = currentPath & "/fs_component.h"
|
||||||
|
|
||||||
|
const FsH = "<file_system_session/file_system_session.h>"
|
||||||
|
|
||||||
|
proc raiseInvalidHandle() {.noreturn, header: FsH,
|
||||||
|
importcpp: "throw File_system::Invalid_handle()".}
|
||||||
|
proc raiseInvalidName() {.noreturn, header: FsH,
|
||||||
|
importcpp: "throw File_system::Invalid_name()".}
|
||||||
|
proc raiseLookupFailed() {.noreturn, header: FsH,
|
||||||
|
importcpp: "throw File_system::Lookup_failed()".}
|
||||||
|
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 validPathAssert(name: string) =
|
||||||
|
if name[name.low] != '/' or name[name.high] == '/': raiseLookupFailed()
|
||||||
|
|
||||||
|
template validNameAssert(name: string) =
|
||||||
|
if name.contains '/': raiseInvalidName()
|
||||||
|
|
||||||
|
type
|
||||||
|
FsCapability {.
|
||||||
|
importcpp: "File_system::Session_capability",
|
||||||
|
header: "<file_system_session/capability.h>".} = object
|
||||||
|
|
||||||
|
FsSessionComponentBase {.
|
||||||
|
importcpp: "File_system::SessionComponentBase", header: fsComponentH.} = object
|
||||||
|
|
||||||
|
FsSessionComponent = Constructible[FsSessionComponentBase]
|
||||||
|
|
||||||
|
Handle = culong
|
||||||
|
|
||||||
|
NodeKind = enum
|
||||||
|
nodeNode,
|
||||||
|
dirNode,
|
||||||
|
fileNode,
|
||||||
|
|
||||||
|
Node = object
|
||||||
|
path: string
|
||||||
|
case kind: NodeKind
|
||||||
|
of fileNode:
|
||||||
|
id: BlobId
|
||||||
|
size: BiggestInt
|
||||||
|
stream: BlobStream
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
SessionPtr = ptr SessionObj
|
||||||
|
SessionRef = ref SessionObj
|
||||||
|
SessionObj = object
|
||||||
|
sig: SignalHandler
|
||||||
|
cpp: FsSessionComponent
|
||||||
|
store: BlobStore
|
||||||
|
label: string
|
||||||
|
fsSetId: SetId
|
||||||
|
fsSet: BlobSet
|
||||||
|
next: Handle
|
||||||
|
nodes: Table[Handle, Node]
|
||||||
|
cache: string
|
||||||
|
## Read files from the store into this buffer
|
||||||
|
cacheCid: BlobId
|
||||||
|
## CID of the cache contents
|
||||||
|
|
||||||
|
Session = ptr SessionObj | ref SessionObj | SessionObj
|
||||||
|
|
||||||
|
proc apply(s: Session; path: string; f: proc (id: BlobId; size: BiggestInt)) =
|
||||||
|
## Apply shortcut
|
||||||
|
apply(s.store, s.fsSet, path, f)
|
||||||
|
|
||||||
|
proc deliverSession*(parent: Parent; id: ServerId; cap: FsCapability) {.
|
||||||
|
importcpp: "#->deliver_session_cap(Genode::Parent::Server::Id{#}, #)".}
|
||||||
|
|
||||||
|
proc packetAvail(cpp: FsSessionComponent): bool {.
|
||||||
|
importcpp: "#->tx_sink()->packet_avail()".}
|
||||||
|
|
||||||
|
proc readyToAck(cpp: FsSessionComponent): bool {.
|
||||||
|
importcpp: "#->tx_sink()->ready_to_ack()".}
|
||||||
|
|
||||||
|
proc popRequest(cpp: FsSessionComponent): FsPacket {.
|
||||||
|
importcpp: "#->tx_sink()->get_packet()".}
|
||||||
|
|
||||||
|
proc packet_content(cpp: FsSessionComponent; pkt: FsPacket): pointer {.
|
||||||
|
importcpp: "#->tx_sink()->packet_content(@)".}
|
||||||
|
|
||||||
|
proc acknowledge(cpp: FsSessionComponent; pkt: FsPacket) {.
|
||||||
|
importcpp: "#->tx_sink()->acknowledge_packet(@)".}
|
||||||
|
|
||||||
|
proc manage(ep: Entrypoint; s: Session): FsCapability =
|
||||||
|
proc manage(ep: Entrypoint; cpp: FsSessionComponent): FsCapability {.
|
||||||
|
importcpp: "#.manage(*#)".}
|
||||||
|
result = ep.manage(s.cpp)
|
||||||
|
GC_ref(s)
|
||||||
|
|
||||||
|
proc dissolve(ep: Entrypoint; s: Session) =
|
||||||
|
proc dissolve(ep: Entrypoint; cpp: FsSessionComponent) {.
|
||||||
|
importcpp: "#.dissolve(*#)".}
|
||||||
|
dissolve s.sig
|
||||||
|
ep.dissolve(s.cpp)
|
||||||
|
destruct s.cpp
|
||||||
|
GC_unref(s)
|
||||||
|
|
||||||
|
proc nextId(s: Session): Handle =
|
||||||
|
result = s.next
|
||||||
|
inc s.next
|
||||||
|
|
||||||
|
proc inode(node: Node): culong = node.path.toKey.culong
|
||||||
|
## Dummy inode generator.
|
||||||
|
|
||||||
|
template fsRpc(session: SessionPtr; body: untyped) =
|
||||||
|
try: body
|
||||||
|
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)
|
||||||
|
else:
|
||||||
|
var path = $path
|
||||||
|
validPathAssert path
|
||||||
|
path = path.strip(chars={'/'})
|
||||||
|
session.nodes[result] = Node(path: path, kind: nodeNode)
|
||||||
|
|
||||||
|
type Status {.importcpp: "File_system::Status", pure.} = object
|
||||||
|
size {.importcpp.}: culonglong
|
||||||
|
mode {.importcpp.}: cuint
|
||||||
|
inode {.importcpp.}: culong
|
||||||
|
|
||||||
|
proc statusProc(state: pointer; handle: Handle): Status {.exportc.} =
|
||||||
|
const
|
||||||
|
DirMode = 1 shl 14
|
||||||
|
FileMode = 1 shl 15
|
||||||
|
let session = cast[ptr SessionObj](state)
|
||||||
|
fsRpc session:
|
||||||
|
var st: Status
|
||||||
|
let node = session.nodes[handle]
|
||||||
|
st.inode = node.inode
|
||||||
|
st.mode = DirMode
|
||||||
|
if node.path != "":
|
||||||
|
session.apply(node.path) do (id: BlobId; size: BiggestInt):
|
||||||
|
st.size = (culonglong)size
|
||||||
|
st.mode = FileMode
|
||||||
|
result = st
|
||||||
|
|
||||||
|
proc dirProc(state: pointer; path: cstring; create: cint): Handle {.exportc.} =
|
||||||
|
permissionsAssert(create == 0)
|
||||||
|
let session = cast[ptr SessionObj](state)
|
||||||
|
fsRpc session:
|
||||||
|
var path = $path
|
||||||
|
var n: Node
|
||||||
|
if path == "/":
|
||||||
|
n = Node(path: "", kind: dirNode)
|
||||||
|
else:
|
||||||
|
validPathAssert path
|
||||||
|
path = path.strip(chars={'/'})
|
||||||
|
if session.fsSet.contains path:
|
||||||
|
raiseLookupFailed()
|
||||||
|
n = Node(path: path, kind: dirNode)
|
||||||
|
result = session.nextId
|
||||||
|
session.nodes[result] = n
|
||||||
|
|
||||||
|
proc fileProc(state: pointer; dirH: Handle; name: cstring; mode: cuint; create: cint): Handle {.exportc.} =
|
||||||
|
permissionsAssert(create == 0)
|
||||||
|
let session = cast[ptr SessionObj](state)
|
||||||
|
fsRpc session:
|
||||||
|
let name = $name
|
||||||
|
validNameAssert name
|
||||||
|
var n: Node
|
||||||
|
let dir = session.nodes[dirH]
|
||||||
|
if dir.kind != dirNode:
|
||||||
|
raiseInvalidHandle()
|
||||||
|
let path = if dir.path == "": name else: dir.path & "/" & name
|
||||||
|
var success = false
|
||||||
|
session.apply(path) do (id: BlobId; size: BiggestInt):
|
||||||
|
let stream = session.store.openBlobStream(id, size, dataBlob)
|
||||||
|
n = Node(path: path, kind: fileNode, id: id, size: size, stream: stream)
|
||||||
|
success = true
|
||||||
|
if not success:
|
||||||
|
raiseLookupFailed()
|
||||||
|
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
|
||||||
|
|
||||||
|
proc unlinkProc(state: pointer; dirH: Handle; name: cstring) {.exportc.} =
|
||||||
|
raisePermissionDenied()
|
||||||
|
|
||||||
|
proc truncateProc(state: pointer; file: Handle, size: cuint) {.exportc.} =
|
||||||
|
raisePermissionDenied()
|
||||||
|
|
||||||
|
proc moveProc(state: pointer;
|
||||||
|
from_dir: Handle; from_name: cstring;
|
||||||
|
to_dir: Handle; to_name: cstring) {.exportc.} =
|
||||||
|
raisePermissionDenied()
|
||||||
|
|
||||||
|
proc processPacket(session: SessionRef; pkt: var FsPacket) =
|
||||||
|
## Process a File_system packet from the client.
|
||||||
|
if not session.nodes.hasKey(pkt.handle):
|
||||||
|
echo session.label, " sent packet with invalid handle"
|
||||||
|
else:
|
||||||
|
case pkt.operation
|
||||||
|
of READ:
|
||||||
|
let
|
||||||
|
node = session.nodes[pkt.handle]
|
||||||
|
pktBuf = cast[ptr array[maxChunkSize, char]](session.cpp.packetContent pkt)
|
||||||
|
# cast the pointer to an array pointer for indexing
|
||||||
|
case node.kind
|
||||||
|
of dirNode:
|
||||||
|
# pretend this is an empty directory
|
||||||
|
pkt.setLen 0
|
||||||
|
pkt.succeeded true
|
||||||
|
of fileNode:
|
||||||
|
node.stream.pos = pkt.position.int
|
||||||
|
let n = node.stream.read(pktBuf, pkt.len)
|
||||||
|
pkt.setLen n
|
||||||
|
pkt.succeeded true
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
of SYNC:
|
||||||
|
pkt.succeeded true
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc newSession(env: GenodeEnv; store: BlobStore; label: string; setId: SetId; fsSet: BlobSet; txBufSize: int): SessionRef =
|
||||||
|
proc construct(cpp: FsSessionComponent; env: GenodeEnv; txBufSize: int; state: SessionPtr; cap: SignalContextCapability) {.
|
||||||
|
importcpp.}
|
||||||
|
let session = SessionRef(
|
||||||
|
store: store,
|
||||||
|
label: label,
|
||||||
|
fsSetId: setId,
|
||||||
|
fsSet: fsSet,
|
||||||
|
nodes: initTable[Handle, Node](),
|
||||||
|
cache: "",
|
||||||
|
# Buffer for reading file data.
|
||||||
|
)
|
||||||
|
session.sig = env.ep.newSignalHandler do ():
|
||||||
|
while session.cpp.packetAvail and session.cpp.readyToAck:
|
||||||
|
var pkt = session.cpp.popRequest
|
||||||
|
pkt.succeeded false # processPacket must affirm success
|
||||||
|
try: session.processPacket(pkt)
|
||||||
|
except: discard
|
||||||
|
session.cpp.acknowledge(pkt)
|
||||||
|
session.cpp.construct(env, txBufSize, session[].addr, session.sig.cap)
|
||||||
|
result = session
|
||||||
|
|
||||||
|
componentConstructHook = proc(env: GenodeEnv) =
|
||||||
|
var
|
||||||
|
policies = newSeq[XmlNode](8)
|
||||||
|
sessions = initTable[ServerId, SessionRef]()
|
||||||
|
let store = newFileStore("/store")
|
||||||
|
# Use the file-system as the store backend
|
||||||
|
|
||||||
|
proc createSession(env: GenodeEnv; store: BlobStore; id: ServerId; label: string; setId: SetId; txBufSize: int) =
|
||||||
|
let
|
||||||
|
fsSet = store.loadSet(setId)
|
||||||
|
session = env.newSession(store, label, setId, fsSet, txBufSize)
|
||||||
|
cap = env.ep.manage session
|
||||||
|
sessions[id] = session
|
||||||
|
echo setId, " served to ", label
|
||||||
|
env.parent.deliverSession(id, cap)
|
||||||
|
|
||||||
|
proc processSessions(rom: RomClient) =
|
||||||
|
update rom
|
||||||
|
var requests = initSessionRequestsParser(rom)
|
||||||
|
|
||||||
|
for id in requests.close:
|
||||||
|
if sessions.contains id:
|
||||||
|
let s = sessions[id]
|
||||||
|
env.ep.dissolve s
|
||||||
|
sessions.del id
|
||||||
|
env.parent.sessionResponseClose(id)
|
||||||
|
|
||||||
|
for id, label, args in requests.create "File_system":
|
||||||
|
let policy = policies.lookupPolicy label
|
||||||
|
doAssert(not sessions.contains(id), "session already exists for id")
|
||||||
|
doAssert(label != "")
|
||||||
|
if policy.isNil:
|
||||||
|
echo "no policy matched '", label, "'"
|
||||||
|
env.parent.sessionResponseDeny(id)
|
||||||
|
else:
|
||||||
|
var setId: SetId
|
||||||
|
let pAttrs = policy.attrs
|
||||||
|
if not pAttrs.isNil and pAttrs.contains "root":
|
||||||
|
try: setId = toSetId(pAttrs["root"])
|
||||||
|
except ValueError: discard
|
||||||
|
else:
|
||||||
|
for e in label.elements:
|
||||||
|
try:
|
||||||
|
setId = toSetId(e)
|
||||||
|
break
|
||||||
|
except ValueError: continue
|
||||||
|
if setId.isValid:
|
||||||
|
try:
|
||||||
|
let
|
||||||
|
#rootPath = args.argString "root"
|
||||||
|
txBufSize = args.argInt "tx_buf_size"
|
||||||
|
env.createSession(store, id, label, setId, txBufSize.int)
|
||||||
|
except:
|
||||||
|
echo "failed to create session for '", label, "', ", getCurrentExceptionMsg()
|
||||||
|
env.parent.sessionResponseDeny(id)
|
||||||
|
else:
|
||||||
|
echo "no valid root policy for '", label, "'"
|
||||||
|
env.parent.sessionResponseDeny(id)
|
||||||
|
|
||||||
|
proc processConfig(rom: RomClient) {.gcsafe.} =
|
||||||
|
update rom
|
||||||
|
policies.setLen 0
|
||||||
|
let configXml = rom.xml
|
||||||
|
configXml.findAll("default-policy", policies)
|
||||||
|
if policies.len > 1:
|
||||||
|
echo "more than one '<default-policy/>' found, ignoring all"
|
||||||
|
policies.setLen 0
|
||||||
|
configXml.findAll("policy", policies)
|
||||||
|
|
||||||
|
for session in sessions.values:
|
||||||
|
# update root policies for active sessions
|
||||||
|
let policy = policies.lookupPolicy session.label
|
||||||
|
if not policy.isNil:
|
||||||
|
let pAttrs = policy.attrs
|
||||||
|
if not pAttrs.isNil and pAttrs.contains "root":
|
||||||
|
try:
|
||||||
|
let
|
||||||
|
idStr = pAttrs["root"]
|
||||||
|
policySetId = toSetId idStr
|
||||||
|
if session.fsSetId != policySetId:
|
||||||
|
let newSet = store.loadSet policySetId
|
||||||
|
session.fsSet = newSet
|
||||||
|
session.fsSetId = policySetId
|
||||||
|
echo idStr, " is new root of ", session.label
|
||||||
|
except:
|
||||||
|
echo "failed to update policy for '",
|
||||||
|
session.label, "', ", getCurrentExceptionMsg()
|
||||||
|
|
||||||
|
let
|
||||||
|
sessionsRom = env.newRomHandler("session_requests", processSessions)
|
||||||
|
configRom = env.newRomHandler("config", processConfig)
|
||||||
|
process configRom
|
||||||
|
process sessionsRom
|
||||||
|
|
||||||
|
env.parent.announce "File_system"
|
45
genode/src/filesystemsession.nim
Normal file
45
genode/src/filesystemsession.nim
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#
|
||||||
|
# \brief Nim File_system session support
|
||||||
|
# \author Emery Hemingway
|
||||||
|
# \date 2017-12-05
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
const FsH = "<file_system_session/file_system_session.h>"
|
||||||
|
|
||||||
|
type
|
||||||
|
FsPacket* {.
|
||||||
|
header: FsH, importcpp: "File_system::Packet_descriptor".} = object
|
||||||
|
|
||||||
|
Operation* {.
|
||||||
|
header: FsH, importcpp: "File_system::Packet_descriptor::Opcode".} = enum
|
||||||
|
READ, WRITE, CONTENT_CHANGED, READ_READY, SYNC
|
||||||
|
|
||||||
|
proc handle*(pkt: FsPacket): culong {.importcpp: "#.handle().value".}
|
||||||
|
proc operation*(pkt: FsPacket): Operation {.importcpp.}
|
||||||
|
proc position*(pkt: FsPacket): BiggestInt {.importcpp.}
|
||||||
|
proc len*(pkt: FsPacket): int {.importcpp: "length".}
|
||||||
|
proc setLen*(pkt: FsPacket; n: int) {.importcpp: "length".}
|
||||||
|
proc succeeded*(pkt: FsPacket): bool {.importcpp.}
|
||||||
|
proc succeeded*(pkt: FsPacket, b: bool) {.importcpp.}
|
||||||
|
|
||||||
|
type
|
||||||
|
FsDirentType* {.importcpp: "File_system::Directory_entry::Type".} = enum
|
||||||
|
TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK
|
||||||
|
|
||||||
|
FsDirent* {.
|
||||||
|
header: FsH, importcpp: "File_system::Directory_entry", final, pure.} = object
|
||||||
|
inode* {.importcpp.}: culong
|
||||||
|
kind* {.importcpp: "type".}: FsDirentType
|
||||||
|
name* {.importcpp.}: cstring
|
||||||
|
|
||||||
|
proc fsDirentSize*(): cint {.
|
||||||
|
importcpp: "sizeof(File_system::Directory_entry)".}
|
||||||
|
|
||||||
|
var MAX_NAME_LEN* {.importcpp:"File_system::MAX_NAME_LEN", noDecl.}: cint
|
93
genode/src/fs_component.h
Normal file
93
genode/src/fs_component.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* \brief C++ File_system session component for Nim
|
||||||
|
* \author Emery Hemingway
|
||||||
|
* \date 2017-12-02
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <file_system_session/rpc_object.h>
|
||||||
|
#include <root/component.h>
|
||||||
|
#include <libc/component.h>
|
||||||
|
#include <base/heap.h>
|
||||||
|
|
||||||
|
typedef unsigned long Handle;
|
||||||
|
|
||||||
|
Handle nodeProc(void *state, char *path);
|
||||||
|
Handle dirProc(void *state, char *path, int create);
|
||||||
|
Handle fileProc(void *state, Handle dir, char *name, unsigned int mode, int create);
|
||||||
|
File_system::Status statusProc(void *state, Handle handle);
|
||||||
|
void closeProc(void *state, Handle handle);
|
||||||
|
void unlinkProc(void *state, Handle dir, char *name);
|
||||||
|
void truncateProc(void *state, int file, File_system::file_size_t size);
|
||||||
|
void moveProc(void *state,
|
||||||
|
Handle from_dir, char *from_name,
|
||||||
|
Handle to_dir, char *to_name);
|
||||||
|
|
||||||
|
namespace File_system { struct SessionComponentBase; }
|
||||||
|
|
||||||
|
struct File_system::SessionComponentBase : File_system::Session_rpc_object
|
||||||
|
{
|
||||||
|
void *state;
|
||||||
|
|
||||||
|
SessionComponentBase(Genode::Env *env,
|
||||||
|
size_t tx_buf_size,
|
||||||
|
void *state,
|
||||||
|
Genode::Signal_context_capability cap)
|
||||||
|
: Session_rpc_object(env->pd().alloc(tx_buf_size), env->rm(), env->ep().rpc_ep()),
|
||||||
|
state(state)
|
||||||
|
{
|
||||||
|
_tx.sigh_packet_avail(cap);
|
||||||
|
_tx.sigh_ready_to_ack(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
** File_system session interface **
|
||||||
|
***********************************/
|
||||||
|
|
||||||
|
Node_handle node(File_system::Path const &path) override {
|
||||||
|
return Node_handle{ nodeProc(state, path.string()) }; }
|
||||||
|
|
||||||
|
Dir_handle dir(File_system::Path const &path, bool create) override {
|
||||||
|
return Dir_handle{ dirProc(state, path.string(), create) }; }
|
||||||
|
|
||||||
|
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) }; }
|
||||||
|
|
||||||
|
Symlink_handle symlink(Dir_handle, Name const &name, bool create) override {
|
||||||
|
throw Lookup_failed(); }
|
||||||
|
|
||||||
|
void close(Node_handle handle) override {
|
||||||
|
closeProc(state, handle.value); }
|
||||||
|
|
||||||
|
Status status(Node_handle handle) override {
|
||||||
|
return statusProc(state, handle.value); }
|
||||||
|
|
||||||
|
void control(Node_handle h, Control) override { }
|
||||||
|
|
||||||
|
void unlink(Dir_handle dir, Name const &name) override
|
||||||
|
{
|
||||||
|
if (!unlinkProc)
|
||||||
|
throw Permission_denied();
|
||||||
|
}
|
||||||
|
|
||||||
|
void truncate(File_handle, File_system::file_size_t size) override
|
||||||
|
{
|
||||||
|
if (!truncateProc)
|
||||||
|
throw Permission_denied();
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(Dir_handle, Name const &from,
|
||||||
|
Dir_handle, Name const &to) override
|
||||||
|
{
|
||||||
|
if (!moveProc)
|
||||||
|
throw Permission_denied();
|
||||||
|
}
|
||||||
|
};
|
|
@ -155,7 +155,7 @@ func isNonZero*(bh: BlobId): bool =
|
||||||
{.deprecated: [isValid: isNonZero].}
|
{.deprecated: [isValid: isNonZero].}
|
||||||
|
|
||||||
type
|
type
|
||||||
Key = int64
|
Key* = int64
|
||||||
|
|
||||||
const
|
const
|
||||||
keyBits = sizeof(Key) shl 3
|
keyBits = sizeof(Key) shl 3
|
||||||
|
|
|
@ -121,14 +121,15 @@ proc fsOpenIngestStream(s: BlobStore; size: BiggestInt; kind: BlobKind): IngestS
|
||||||
stream.leaves = newSeq[BlobId]()
|
stream.leaves = newSeq[BlobId]()
|
||||||
stream
|
stream
|
||||||
|
|
||||||
proc newFileStore*(root: string): FileStore =
|
proc newFileStore*(root: string): BlobStore =
|
||||||
## Create a new store object backed by a file-system.
|
## Create a new store object backed by a file-system.
|
||||||
try:
|
try:
|
||||||
createDir(root / $dataBlob)
|
createDir(root / $dataBlob)
|
||||||
createDir(root / $metaBlob)
|
createDir(root / $metaBlob)
|
||||||
except: discard
|
except: discard
|
||||||
new result
|
FileStore(
|
||||||
result.openBlobStreamImpl = fsOpenBlobStream
|
openBlobStreamImpl: fsOpenBlobStream,
|
||||||
result.openIngestStreamImpl = fsOpenIngestStream
|
openIngestStreamImpl: fsOpenIngestStream,
|
||||||
result.root = root
|
root: root,
|
||||||
result.buf = ""
|
buf: "",
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user