Compare commits
11 Commits
3a06c18e10
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 86ca343cf0 | |||
| b680ffdd5b | |||
| 14799e0d58 | |||
| b7452a449b | |||
| ea6ec785a9 | |||
| 6d88cf4bf3 | |||
| aef0163017 | |||
| b0fda122e0 | |||
| 79af171384 | |||
| 5931642cc2 | |||
| 26a49162e6 |
@@ -1,8 +1,8 @@
|
|||||||
find_program(IFC
|
find_program(XPCG
|
||||||
NAMES ifc
|
NAMES xpcg
|
||||||
REQUIRED
|
REQUIRED
|
||||||
HINTS ${BUILD_TOOLS_DIR})
|
HINTS ${BUILD_TOOLS_DIR})
|
||||||
message(STATUS "Found interface compiler: ${IFC}")
|
message(STATUS "Found interface generator: ${XPCG}")
|
||||||
|
|
||||||
function(add_interface)
|
function(add_interface)
|
||||||
set(options)
|
set(options)
|
||||||
@@ -20,9 +20,9 @@ function(add_interface)
|
|||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${header_path}
|
OUTPUT ${header_path}
|
||||||
COMMAND ${IFC} ${arg_PATH}
|
COMMAND ${XPCG} ${arg_PATH}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${arg_PARENT_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${arg_PARENT_DIR}
|
||||||
COMMENT "Compiling interface: ${arg_NAME}")
|
COMMENT "Generating interface: ${arg_NAME}")
|
||||||
|
|
||||||
add_custom_target(ifgen-${arg_NAME} ALL
|
add_custom_target(ifgen-${arg_NAME} ALL
|
||||||
DEPENDS ${header_path})
|
DEPENDS ${header_path})
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ function(rosetta_add_library)
|
|||||||
${arg_SOURCES}
|
${arg_SOURCES}
|
||||||
${arg_HEADERS})
|
${arg_HEADERS})
|
||||||
set_target_properties(${static_lib_name} PROPERTIES OUTPUT_NAME "${lib_name}")
|
set_target_properties(${static_lib_name} PROPERTIES OUTPUT_NAME "${lib_name}")
|
||||||
|
target_compile_definitions(${static_lib_name} PRIVATE
|
||||||
|
BUILD_STATIC=1)
|
||||||
set(targets ${targets} ${static_lib_name})
|
set(targets ${targets} ${static_lib_name})
|
||||||
|
|
||||||
if (arg_PUBLIC_INCLUDE_DIRS)
|
if (arg_PUBLIC_INCLUDE_DIRS)
|
||||||
@@ -86,6 +88,8 @@ function(rosetta_add_library)
|
|||||||
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
target_compile_definitions(${shared_lib_name} PRIVATE
|
||||||
|
BUILD_SHARED=1)
|
||||||
set_target_properties(${shared_lib_name} PROPERTIES
|
set_target_properties(${shared_lib_name} PROPERTIES
|
||||||
SOVERSION 1)
|
SOVERSION 1)
|
||||||
target_link_options(${shared_lib_name} PRIVATE -Wl,--soname,${soname})
|
target_link_options(${shared_lib_name} PRIVATE -Wl,--soname,${soname})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
file(GLOB if_files *.if)
|
file(GLOB if_files *.xpc)
|
||||||
|
|
||||||
foreach (file ${if_files})
|
foreach (file ${if_files})
|
||||||
get_filename_component(name ${file} NAME_WLE)
|
get_filename_component(name ${file} NAME_WLE)
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
interface fs {
|
|
||||||
msg open(string path, int flags) -> (int err);
|
|
||||||
}
|
|
||||||
9
interface/fs.xpc
Normal file
9
interface/fs.xpc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
interface fs 6400;
|
||||||
|
|
||||||
|
func open[0](path: string, flags: int) -> (err: int);
|
||||||
|
func close[1]() -> (err: int);
|
||||||
|
|
||||||
|
func read[2](count: size) -> (err: int, nr_read: size, data: buffer);
|
||||||
|
func write[3](data: buffer) -> (err: int, nr_written: size);
|
||||||
|
|
||||||
|
func map[4](prot: int, flags: int) -> (vmo: handle);
|
||||||
2
kernel
2
kernel
Submodule kernel updated: 1d4cb882a8...de520cdd2d
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs core malloc)
|
set(source_dirs core malloc io)
|
||||||
|
|
||||||
set(public_include_dirs
|
set(public_include_dirs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
@@ -26,5 +26,5 @@ bsp_add_library(
|
|||||||
NAME libc
|
NAME libc
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(libc libmango)
|
target_link_libraries(libc libmango libxpc-static interface::fs)
|
||||||
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs stdio string)
|
set(source_dirs stdio string errno)
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
foreach (dir ${source_dirs})
|
||||||
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
@@ -21,3 +21,5 @@ sysroot_add_library(
|
|||||||
NAME libc-core
|
NAME libc-core
|
||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libc-core libmango)
|
||||||
|
|||||||
54
lib/libc/core/errno/errno.c
Normal file
54
lib/libc/core/errno/errno.c
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/status.h>
|
||||||
|
|
||||||
|
#if defined(BUILD_STATIC)
|
||||||
|
int __set_errno(int err)
|
||||||
|
{
|
||||||
|
return -err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BUILD_SHARED)
|
||||||
|
int __set_errno(int err)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int __errno_from_kern_status(unsigned int err)
|
||||||
|
{
|
||||||
|
switch (err) {
|
||||||
|
case KERN_OK:
|
||||||
|
return SUCCESS;
|
||||||
|
case KERN_UNIMPLEMENTED:
|
||||||
|
return ENOSYS;
|
||||||
|
case KERN_NAME_EXISTS:
|
||||||
|
return EEXIST;
|
||||||
|
case KERN_INVALID_ARGUMENT:
|
||||||
|
return EINVAL;
|
||||||
|
case KERN_UNSUPPORTED:
|
||||||
|
return ENOTSUP;
|
||||||
|
case KERN_NO_MEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case KERN_NO_ENTRY:
|
||||||
|
return ENOENT;
|
||||||
|
case KERN_WOULD_BLOCK:
|
||||||
|
return EWOULDBLOCK;
|
||||||
|
case KERN_NO_DEVICE:
|
||||||
|
return ENODEV;
|
||||||
|
case KERN_DEVICE_STUCK:
|
||||||
|
case KERN_IO_ERROR:
|
||||||
|
return EIO;
|
||||||
|
case KERN_FATAL_ERROR:
|
||||||
|
return ENXIO;
|
||||||
|
case KERN_BAD_STATE:
|
||||||
|
return EPERM;
|
||||||
|
case KERN_MEMORY_FAULT:
|
||||||
|
return EFAULT;
|
||||||
|
case KERN_ACCESS_DENIED:
|
||||||
|
return EACCES;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -139,4 +139,7 @@
|
|||||||
#define EQFULL 106 /* Interface output queue is full */
|
#define EQFULL 106 /* Interface output queue is full */
|
||||||
#define ELAST 106 /* Must be equal largest errno */
|
#define ELAST 106 /* Must be equal largest errno */
|
||||||
|
|
||||||
|
extern int __set_errno(int err);
|
||||||
|
extern int __errno_from_kern_status(unsigned int err);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,4 +14,6 @@ extern int strncmp(const char *s1, const char *s2, unsigned long n);
|
|||||||
extern void *memset(void *str, int c, size_t n);
|
extern void *memset(void *str, int c, size_t n);
|
||||||
extern void *memcpy(void *dst, const void *src, size_t len);
|
extern void *memcpy(void *dst, const void *src, size_t len);
|
||||||
|
|
||||||
|
extern char *strdup(char *s);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#ifndef UNISTD_H_
|
#ifndef UNISTD_H_
|
||||||
#define UNISTD_H_
|
#define UNISTD_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
extern int open(const char *path, int flags);
|
extern int open(const char *path, int flags);
|
||||||
extern int close(int fd);
|
extern int close(int fd);
|
||||||
|
|
||||||
|
extern int read(int fd, void *buf, size_t count);
|
||||||
|
extern int write(int fd, const void *buf, size_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
33
lib/libc/io/CMakeLists.txt
Normal file
33
lib/libc/io/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
set(source_dirs unistd stdio)
|
||||||
|
|
||||||
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
|
foreach (dir ${source_dirs})
|
||||||
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
|
file(GLOB dir_headers ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.h)
|
||||||
|
|
||||||
|
set(sources ${sources} ${dir_sources})
|
||||||
|
set(headers ${headers} ${dir_headers})
|
||||||
|
endforeach (dir)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||||
|
set(headers ${headers} ${sub_headers})
|
||||||
|
|
||||||
|
set(component_sources ${sources} PARENT_SCOPE)
|
||||||
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
|
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||||
|
|
||||||
|
rosetta_add_library(STATIC
|
||||||
|
NAME libc-io
|
||||||
|
PUBLIC_INCLUDE_DIRS
|
||||||
|
${public_include_dirs}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libc-io
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libc-io libc-core interface::fs libxpc-static libmango)
|
||||||
2
lib/libc/io/fs.c
Normal file
2
lib/libc/io/fs.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define MSG_IMPLEMENTATION
|
||||||
|
#include <rosetta/fs.h>
|
||||||
43
lib/libc/io/include/sys/mman.h
Normal file
43
lib/libc/io/include/sys/mman.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef SYS_MMAN_H_
|
||||||
|
#define SYS_MMAN_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define PROT_NONE 0x00u
|
||||||
|
#define PROT_EXEC 0x01u
|
||||||
|
#define PROT_READ 0x02u
|
||||||
|
#define PROT_WRITE 0x04u
|
||||||
|
|
||||||
|
#define MAP_SHARED 0x01u
|
||||||
|
#define MAP_SHARED_VALIDATE 0x03u
|
||||||
|
#define MAP_PRIVATE 0x04u
|
||||||
|
#define MAP_32BIT 0x08u
|
||||||
|
#define MAP_ANON MAP_ANONYMOUS
|
||||||
|
#define MAP_ANONYMOUS 0x10u
|
||||||
|
#define MAP_DENYWRITE 0x20u
|
||||||
|
#define MAP_EXECUTABLE 0x40u
|
||||||
|
#define MAP_FILE 0x80u
|
||||||
|
#define MAP_FIXED 0x100u
|
||||||
|
#define MAP_FIXED_NOREPLACE 0x300u
|
||||||
|
#define MAP_GROWSDOWN 0x400u
|
||||||
|
#define MAP_HUGETLB 0x800u
|
||||||
|
#define MAP_HUGE_2MB 0x1000u
|
||||||
|
#define MAP_HUGE_1GB 0x2000u
|
||||||
|
#define MAP_LOCKED 0x4000u
|
||||||
|
#define MAP_NONBLOCK 0x8000u
|
||||||
|
#define MAP_NORESERVE 0x10000u
|
||||||
|
#define MAP_POPULATE 0x20000u
|
||||||
|
#define MAP_STACK 0x40000u
|
||||||
|
#define MAP_SYNC 0x80000u
|
||||||
|
#define MAP_UNINITIALIZED 0x100000u
|
||||||
|
|
||||||
|
extern void *mmap(
|
||||||
|
void *addr,
|
||||||
|
size_t length,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
int fd,
|
||||||
|
off_t offset);
|
||||||
|
|
||||||
|
#endif
|
||||||
18
lib/libc/io/include/sys/remote.h
Normal file
18
lib/libc/io/include/sys/remote.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef SYS_REMOTE_H_
|
||||||
|
#define SYS_REMOTE_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
enum sys_remote_id {
|
||||||
|
SYS_REMOTE_NONE,
|
||||||
|
SYS_REMOTE_NSD,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern bool sys_remote_get(
|
||||||
|
enum sys_remote_id id,
|
||||||
|
tid_t *out_tid,
|
||||||
|
unsigned int *out_chid);
|
||||||
|
extern void sys_remote_set(enum sys_remote_id id, tid_t tid, unsigned int chid);
|
||||||
|
|
||||||
|
#endif
|
||||||
45
lib/libc/io/remote.c
Normal file
45
lib/libc/io/remote.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
#define TID_INVALID ((tid_t) - 1)
|
||||||
|
#define CHID_INVALID ((unsigned int)-1)
|
||||||
|
|
||||||
|
struct remote {
|
||||||
|
tid_t tid;
|
||||||
|
unsigned int chid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct remote remotes[] = {
|
||||||
|
[SYS_REMOTE_NONE] = {.tid = TID_INVALID, .chid = CHID_INVALID},
|
||||||
|
[SYS_REMOTE_NSD] = {.tid = TID_INVALID, .chid = CHID_INVALID},
|
||||||
|
};
|
||||||
|
static const size_t nr_remotes = sizeof remotes / sizeof remotes[0];
|
||||||
|
|
||||||
|
bool sys_remote_get(
|
||||||
|
enum sys_remote_id id,
|
||||||
|
tid_t *out_tid,
|
||||||
|
unsigned int *out_chid)
|
||||||
|
{
|
||||||
|
if (id < 0 || id >= nr_remotes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct remote *remote = &remotes[id];
|
||||||
|
if (remote->tid == TID_INVALID || remote->chid == CHID_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_tid = remote->tid;
|
||||||
|
*out_chid = remote->chid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_remote_set(enum sys_remote_id id, tid_t tid, unsigned int chid)
|
||||||
|
{
|
||||||
|
if (id < 0 || id >= nr_remotes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct remote *remote = &remotes[id];
|
||||||
|
remote->tid = tid;
|
||||||
|
remote->chid = chid;
|
||||||
|
}
|
||||||
0
lib/libc/io/unistd/close.c
Normal file
0
lib/libc/io/unistd/close.c
Normal file
6
lib/libc/io/unistd/mmap.c
Normal file
6
lib/libc/io/unistd/mmap.c
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
40
lib/libc/io/unistd/open.c
Normal file
40
lib/libc/io/unistd/open.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
int open(const char *path, int flags)
|
||||||
|
{
|
||||||
|
tid_t remote_tid;
|
||||||
|
unsigned int remote_chid;
|
||||||
|
if (!sys_remote_get(SYS_REMOTE_NSD, &remote_tid, &remote_chid)) {
|
||||||
|
return __set_errno(ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t port;
|
||||||
|
kern_status_t status = port_create(&port);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = port_connect(port, remote_tid, remote_chid);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(port);
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = SUCCESS;
|
||||||
|
status = fs_open(port, path, flags, &err);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(port);
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
kern_handle_close(port);
|
||||||
|
return __set_errno(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)port;
|
||||||
|
}
|
||||||
21
lib/libc/io/unistd/read.c
Normal file
21
lib/libc/io/unistd/read.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
int read(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
size_t nr_read;
|
||||||
|
kern_status_t status = fs_read(fd, count, &err, &nr_read, buf, count);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
return __set_errno(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nr_read;
|
||||||
|
}
|
||||||
0
lib/libc/io/unistd/write.c
Normal file
0
lib/libc/io/unistd/write.c
Normal file
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs stdlib)
|
set(source_dirs stdlib string)
|
||||||
|
|
||||||
file(GLOB sources *.c *.h)
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
|
|||||||
14
lib/libc/malloc/string/strdup.c
Normal file
14
lib/libc/malloc/string/strdup.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *strdup(char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
char *out = malloc(len + 1);
|
||||||
|
if (!out) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out, s, len + 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(libfs libmango interface::fs libc)
|
target_link_libraries(libfs libmango interface::fs libc libxpc)
|
||||||
target_link_libraries(libfs-static libmango interface::fs libc-core)
|
target_link_libraries(libfs-static libmango interface::fs libc-core libxpc-static)
|
||||||
|
|
||||||
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
#include <fs/allocator.h>
|
#include <fs/allocator.h>
|
||||||
#include <fs/context.h>
|
#include <fs/context.h>
|
||||||
|
#include <fs/dentry.h>
|
||||||
|
#include <fs/inode.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <fs/superblock.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
BTREE_DEFINE_SIMPLE_GET(struct fs_file, unsigned long, f_node, f_id, get_file);
|
BTREE_DEFINE_SIMPLE_GET(struct fs_file, unsigned long, f_node, f_id, get_file);
|
||||||
BTREE_DEFINE_SIMPLE_INSERT(struct fs_file, f_node, f_id, put_file);
|
BTREE_DEFINE_SIMPLE_INSERT(struct fs_file, f_node, f_id, put_file);
|
||||||
@@ -16,9 +22,7 @@ struct fs_context {
|
|||||||
struct fs_vtable ctx_vtable;
|
struct fs_vtable ctx_vtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_context *fs_context_create(
|
struct fs_context *fs_context_create(struct fs_allocator *alloc)
|
||||||
struct fs_allocator *alloc,
|
|
||||||
struct fs_superblock *sb)
|
|
||||||
{
|
{
|
||||||
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@@ -27,10 +31,10 @@ struct fs_context *fs_context_create(
|
|||||||
|
|
||||||
memset(ctx, 0x0, sizeof *ctx);
|
memset(ctx, 0x0, sizeof *ctx);
|
||||||
|
|
||||||
ctx->ctx_sb = sb;
|
|
||||||
ctx->ctx_alloc = alloc;
|
ctx->ctx_alloc = alloc;
|
||||||
|
|
||||||
ctx->ctx_vtable.open = fs_msg_open;
|
ctx->ctx_vtable.open = fs_msg_open;
|
||||||
|
ctx->ctx_vtable.read = fs_msg_read;
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
@@ -40,6 +44,35 @@ void fs_context_destroy(struct fs_context *ctx)
|
|||||||
fs_free(ctx->ctx_alloc, ctx);
|
fs_free(ctx->ctx_alloc, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_context_mount_filesystem(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
fs_mount_function_t func,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags)
|
||||||
|
{
|
||||||
|
if (!func) {
|
||||||
|
return FS_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_superblock *sb = NULL;
|
||||||
|
enum fs_status status = func(ctx, arg, flags, &sb);
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sb) {
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->ctx_sb = sb;
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_context_unmount_filesystem(struct fs_context *ctx)
|
||||||
|
{
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
||||||
{
|
{
|
||||||
struct fs_file *f = get_file(&ctx->ctx_filelist, id);
|
struct fs_file *f = get_file(&ctx->ctx_filelist, id);
|
||||||
@@ -58,29 +91,104 @@ struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct fs_file *fs_context_get_file(struct fs_context *ctx, unsigned long id)
|
||||||
|
{
|
||||||
|
return get_file(&ctx->ctx_filelist, id);
|
||||||
|
}
|
||||||
|
|
||||||
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_dentry *fs_context_resolve_path(
|
static size_t get_first_path_component(const char *in, char *out, size_t max)
|
||||||
struct fs_context *ctx,
|
|
||||||
const char *path)
|
|
||||||
{
|
{
|
||||||
return NULL;
|
size_t i = 0;
|
||||||
|
while (i < max - 1) {
|
||||||
|
if (in[i] == '\0' || in[i] == '/') {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t fs_context_dispatch_msg(
|
out[i] = in[i];
|
||||||
struct fs_context *ctx,
|
i++;
|
||||||
kern_handle_t channel,
|
}
|
||||||
struct msg_endpoint *sender,
|
|
||||||
struct msg_header *hdr)
|
out[i] = '\0';
|
||||||
{
|
return i;
|
||||||
return fs_dispatch(
|
}
|
||||||
channel,
|
|
||||||
&ctx->ctx_vtable,
|
extern enum fs_status fs_context_resolve_path(
|
||||||
sender,
|
struct fs_context *ctx,
|
||||||
hdr,
|
const char *path,
|
||||||
NULL,
|
struct fs_dentry **out)
|
||||||
0,
|
{
|
||||||
ctx);
|
if (!ctx->ctx_sb || !ctx->ctx_sb->s_root) {
|
||||||
|
return FS_ERR_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_dentry *cur = ctx->ctx_sb->s_root;
|
||||||
|
|
||||||
|
char tok[256];
|
||||||
|
|
||||||
|
while (*path != '\0') {
|
||||||
|
while (*path == '/') {
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tok_len
|
||||||
|
= get_first_path_component(path, tok, sizeof tok);
|
||||||
|
|
||||||
|
if (!tok_len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_dir = *(path + tok_len) != '\0';
|
||||||
|
|
||||||
|
if (cur->d_inode->i_mode != FS_INODE_DIR) {
|
||||||
|
return FS_ERR_NOT_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_dentry *next = NULL;
|
||||||
|
enum fs_status status
|
||||||
|
= fs_inode_lookup(cur->d_inode, tok, &next);
|
||||||
|
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next) {
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = next;
|
||||||
|
|
||||||
|
path += tok_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = cur;
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t fs_context_dispatch_msg(struct fs_context *ctx, xpc_msg_t *msg)
|
||||||
|
{
|
||||||
|
return fs_dispatch(NULL, msg, &ctx->ctx_vtable, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fs_context_alloc(struct fs_context *ctx, size_t count)
|
||||||
|
{
|
||||||
|
return fs_alloc(ctx->ctx_alloc, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fs_context_calloc(struct fs_context *ctx, size_t count, size_t sz)
|
||||||
|
{
|
||||||
|
return fs_calloc(ctx->ctx_alloc, count, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fs_context_realloc(struct fs_context *ctx, void *p, size_t count)
|
||||||
|
{
|
||||||
|
return fs_realloc(ctx->ctx_alloc, p, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_context_free(struct fs_context *ctx, void *p)
|
||||||
|
{
|
||||||
|
fs_free(ctx->ctx_alloc, p);
|
||||||
}
|
}
|
||||||
|
|||||||
41
lib/libfs/file.c
Normal file
41
lib/libfs/file.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
struct fs_inode *fs_file_get_inode(const struct fs_file *f)
|
||||||
|
{
|
||||||
|
return f->f_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fs_file_get_cursor(const struct fs_file *f)
|
||||||
|
{
|
||||||
|
return f->f_seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_read) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t seek = f->f_seek;
|
||||||
|
enum fs_status status = f->f_ops->f_read(f, buf, count, &seek);
|
||||||
|
f->f_seek = seek;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_write(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_write) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t seek = f->f_seek;
|
||||||
|
enum fs_status status = f->f_ops->f_write(f, buf, count, &seek);
|
||||||
|
f->f_seek = seek;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
|
|
||||||
|
#include <fs/dentry.h>
|
||||||
#include <fs/file.h>
|
#include <fs/file.h>
|
||||||
|
#include <fs/inode.h>
|
||||||
|
|
||||||
struct fs_file {
|
struct fs_file {
|
||||||
/* id of the open file, equal to the koid of the port being used to
|
/* id of the open file, equal to the koid of the port being used to
|
||||||
@@ -12,6 +14,10 @@ struct fs_file {
|
|||||||
struct btree_node f_node;
|
struct btree_node f_node;
|
||||||
|
|
||||||
const struct fs_file_ops *f_ops;
|
const struct fs_file_ops *f_ops;
|
||||||
|
|
||||||
|
off_t f_seek;
|
||||||
|
struct fs_inode *f_inode;
|
||||||
|
struct fs_dentry *f_dent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,30 +2,54 @@
|
|||||||
#define FS_CONTEXT_H_
|
#define FS_CONTEXT_H_
|
||||||
|
|
||||||
#include <rosetta/fs.h>
|
#include <rosetta/fs.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
struct fs_dentry;
|
||||||
struct fs_context;
|
struct fs_context;
|
||||||
struct fs_allocator;
|
struct fs_allocator;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
|
|
||||||
extern struct fs_context *fs_context_create(
|
enum fs_mount_flags {
|
||||||
struct fs_allocator *alloc,
|
FS_MOUNT_READONLY = 0x01u,
|
||||||
struct fs_superblock *sb);
|
};
|
||||||
|
|
||||||
|
typedef enum fs_status (*fs_mount_function_t)(
|
||||||
|
struct fs_context *,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags,
|
||||||
|
struct fs_superblock **);
|
||||||
|
|
||||||
|
extern struct fs_context *fs_context_create(struct fs_allocator *alloc);
|
||||||
extern void fs_context_destroy(struct fs_context *ctx);
|
extern void fs_context_destroy(struct fs_context *ctx);
|
||||||
|
|
||||||
|
extern enum fs_status fs_context_mount_filesystem(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
fs_mount_function_t func,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags);
|
||||||
|
extern enum fs_status fs_context_unmount_filesystem(struct fs_context *ctx);
|
||||||
|
|
||||||
extern struct fs_file *fs_context_open_file(
|
extern struct fs_file *fs_context_open_file(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
unsigned long id);
|
unsigned long id);
|
||||||
|
extern struct fs_file *fs_context_get_file(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
unsigned long id);
|
||||||
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
||||||
|
|
||||||
extern struct fs_dentry *fs_context_resolve_path(
|
extern enum fs_status fs_context_resolve_path(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
const char *path);
|
const char *path,
|
||||||
|
struct fs_dentry **out);
|
||||||
|
|
||||||
extern kern_status_t fs_context_dispatch_msg(
|
extern kern_status_t fs_context_dispatch_msg(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
kern_handle_t channel,
|
xpc_msg_t *msg);
|
||||||
struct msg_endpoint *sender,
|
|
||||||
struct msg_header *hdr);
|
extern void *fs_context_alloc(struct fs_context *ctx, size_t count);
|
||||||
|
extern void *fs_context_calloc(struct fs_context *ctx, size_t count, size_t sz);
|
||||||
|
extern void *fs_context_realloc(struct fs_context *ctx, void *p, size_t count);
|
||||||
|
extern void fs_context_free(struct fs_context *ctx, void *p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ struct fs_dentry {
|
|||||||
struct fs_superblock *d_sb;
|
struct fs_superblock *d_sb;
|
||||||
const struct fs_dentry_ops *d_ops;
|
const struct fs_dentry_ops *d_ops;
|
||||||
void *d_fsdata;
|
void *d_fsdata;
|
||||||
|
char *d_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,11 +5,31 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
struct xpc_buffer;
|
||||||
|
|
||||||
struct fs_file_ops {
|
struct fs_file_ops {
|
||||||
ssize_t (*f_read)(struct fs_file *, void *, size_t);
|
enum fs_status (*f_read)(
|
||||||
ssize_t (*f_write)(struct fs_file *, const void *, size_t);
|
struct fs_file *,
|
||||||
off_t (*f_seek)(struct fs_file *, off_t, int);
|
struct xpc_buffer *,
|
||||||
|
size_t,
|
||||||
|
off_t *);
|
||||||
|
enum fs_status (*f_write)(
|
||||||
|
struct fs_file *,
|
||||||
|
const struct xpc_buffer *,
|
||||||
|
size_t,
|
||||||
|
off_t *);
|
||||||
|
enum fs_status (*f_seek)(struct fs_file *, off_t, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct fs_inode *fs_file_get_inode(const struct fs_file *f);
|
||||||
|
extern size_t fs_file_get_cursor(const struct fs_file *f);
|
||||||
|
extern enum fs_status fs_file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count);
|
||||||
|
extern enum fs_status fs_file_write(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,17 +1,37 @@
|
|||||||
#ifndef FS_INODE_H_
|
#ifndef FS_INODE_H_
|
||||||
#define FS_INODE_H_
|
#define FS_INODE_H_
|
||||||
|
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_inode;
|
struct fs_inode;
|
||||||
struct fs_dentry;
|
struct fs_dentry;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
|
struct fs_file_ops;
|
||||||
|
|
||||||
|
enum fs_inode_mode {
|
||||||
|
FS_INODE_REG = 0x01u,
|
||||||
|
FS_INODE_DIR = 0x02u,
|
||||||
|
};
|
||||||
|
|
||||||
struct fs_inode_ops {
|
struct fs_inode_ops {
|
||||||
int (*i_lookup)(struct fs_inode *, struct fs_dentry *);
|
enum fs_status (*i_lookup)(
|
||||||
|
struct fs_inode *,
|
||||||
|
const char *,
|
||||||
|
struct fs_dentry **);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_inode {
|
struct fs_inode {
|
||||||
|
enum fs_inode_mode i_mode;
|
||||||
struct fs_superblock *i_sb;
|
struct fs_superblock *i_sb;
|
||||||
const struct fs_inode_ops *i_ops;
|
const struct fs_inode_ops *i_ops;
|
||||||
|
const struct fs_file_ops *i_fops;
|
||||||
|
size_t i_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern enum fs_status fs_inode_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
18
lib/libfs/include/fs/status.h
Normal file
18
lib/libfs/include/fs/status.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef FS_STATUS_H_
|
||||||
|
#define FS_STATUS_H_
|
||||||
|
|
||||||
|
enum fs_status {
|
||||||
|
FS_SUCCESS = 0,
|
||||||
|
FS_ERR_NO_ENTRY,
|
||||||
|
FS_ERR_NO_MEMORY,
|
||||||
|
FS_ERR_INVALID_ARGUMENT,
|
||||||
|
FS_ERR_NOT_IMPLEMENTED,
|
||||||
|
FS_ERR_IS_DIRECTORY,
|
||||||
|
FS_ERR_NOT_DIRECTORY,
|
||||||
|
FS_ERR_BAD_STATE,
|
||||||
|
FS_ERR_INTERNAL_FAILURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int fs_status_to_errno(enum fs_status status);
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/libfs/inode.c
Normal file
13
lib/libfs/inode.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <fs/inode.h>
|
||||||
|
|
||||||
|
enum fs_status fs_inode_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out)
|
||||||
|
{
|
||||||
|
if (!inode->i_ops || !inode->i_ops->i_lookup) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inode->i_ops->i_lookup(inode, name, out);
|
||||||
|
}
|
||||||
@@ -2,12 +2,17 @@
|
|||||||
#define _FS_INTERFACE_H_
|
#define _FS_INTERFACE_H_
|
||||||
|
|
||||||
#include <mango/types.h>
|
#include <mango/types.h>
|
||||||
|
#include <xpc/buffer.h>
|
||||||
|
#include <xpc/context.h>
|
||||||
|
#include <xpc/endpoint.h>
|
||||||
|
#include <xpc/string.h>
|
||||||
|
|
||||||
struct msg_endpoint;
|
struct msg_endpoint;
|
||||||
|
|
||||||
extern kern_status_t fs_msg_open(
|
extern kern_status_t fs_msg_open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *ctx,
|
||||||
const char *path,
|
const xpc_endpoint_t *sender,
|
||||||
|
const xpc_string_t *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg);
|
void *arg);
|
||||||
@@ -18,4 +23,13 @@ extern kern_status_t fs_msg_close(
|
|||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_read(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
size_t count,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_read,
|
||||||
|
xpc_buffer_t *out_data,
|
||||||
|
void *arg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,21 +1,53 @@
|
|||||||
|
#include "../file.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fs/context.h>
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
extern kern_status_t fs_msg_open(
|
extern kern_status_t fs_msg_open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *xpc,
|
||||||
const char *path,
|
xpc_endpoint_t *sender,
|
||||||
|
const xpc_string_t *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
char path_buf[4096];
|
||||||
|
size_t path_len = 0;
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_string_read(path, path_buf, sizeof path_buf, &path_len);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
struct fs_context *ctx = arg;
|
struct fs_context *ctx = arg;
|
||||||
|
|
||||||
struct fs_dentry *dent = fs_context_resolve_path(ctx, path);
|
struct fs_file *f = fs_context_open_file(ctx, sender->e_port);
|
||||||
if (!dent) {
|
if (!f) {
|
||||||
*out_err = ENOENT;
|
*out_err = ENOMEM;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->f_inode) {
|
||||||
|
*out_err = EBUSY;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_dentry *dent = NULL;
|
||||||
|
enum fs_status fs_status
|
||||||
|
= fs_context_resolve_path(ctx, path_buf, &dent);
|
||||||
|
if (fs_status != FS_SUCCESS) {
|
||||||
|
fs_context_close_file(ctx, f);
|
||||||
|
*out_err = fs_status_to_errno(status);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->f_seek = 0;
|
||||||
|
f->f_dent = dent;
|
||||||
|
f->f_inode = dent->d_inode;
|
||||||
|
f->f_ops = dent->d_inode->i_fops;
|
||||||
|
|
||||||
*out_err = SUCCESS;
|
*out_err = SUCCESS;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
30
lib/libfs/interface/read.c
Normal file
30
lib/libfs/interface/read.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_read(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
xpc_endpoint_t *sender,
|
||||||
|
size_t count,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_read,
|
||||||
|
xpc_buffer_t *out_data,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start = fs_file_get_cursor(f);
|
||||||
|
enum fs_status status = fs_file_read(f, out_data, count);
|
||||||
|
size_t end = fs_file_get_cursor(f);
|
||||||
|
|
||||||
|
*out_err = fs_status_to_errno(status);
|
||||||
|
*out_nr_read = end - start;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
25
lib/libfs/status.c
Normal file
25
lib/libfs/status.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
int fs_status_to_errno(enum fs_status status)
|
||||||
|
{
|
||||||
|
switch (status) {
|
||||||
|
case FS_SUCCESS:
|
||||||
|
return SUCCESS;
|
||||||
|
case FS_ERR_NO_ENTRY:
|
||||||
|
return ENOENT;
|
||||||
|
case FS_ERR_NO_MEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case FS_ERR_INVALID_ARGUMENT:
|
||||||
|
return EINVAL;
|
||||||
|
case FS_ERR_NOT_IMPLEMENTED:
|
||||||
|
return ENOSYS;
|
||||||
|
case FS_ERR_IS_DIRECTORY:
|
||||||
|
return EISDIR;
|
||||||
|
case FS_ERR_NOT_DIRECTORY:
|
||||||
|
return ENOTDIR;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
lib/libxpc/CMakeLists.txt
Normal file
28
lib/libxpc/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
|
file(GLOB headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME libxpc SHARED STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libxpc
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libxpc-static
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libxpc libmango libc)
|
||||||
|
target_link_libraries(libxpc-static libmango libc-core)
|
||||||
|
|
||||||
|
#set_target_properties(libxpc-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||||
59
lib/libxpc/buffer.c
Normal file
59
lib/libxpc/buffer.c
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <mango/status.h>
|
||||||
|
#include <xpc/buffer.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
|
kern_status_t xpc_buffer_read(
|
||||||
|
const xpc_buffer_t *buf,
|
||||||
|
void *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read)
|
||||||
|
{
|
||||||
|
if ((buf->buf_flags & (XPC_BUFFER_F_IN | XPC_BUFFER_F_REMOTE))
|
||||||
|
!= (XPC_BUFFER_F_IN | XPC_BUFFER_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_read = max;
|
||||||
|
if (to_read > buf->buf_len) {
|
||||||
|
to_read = buf->buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_msg_read(buf->buf_origin, buf->buf_offset, out, to_read);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
*nr_read = to_read;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_buffer_write(
|
||||||
|
xpc_buffer_t *buf,
|
||||||
|
const void *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
if ((buf->buf_flags & (XPC_BUFFER_F_OUT | XPC_BUFFER_F_REMOTE))
|
||||||
|
!= (XPC_BUFFER_F_OUT | XPC_BUFFER_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_write = len;
|
||||||
|
if (to_write > buf->buf_max) {
|
||||||
|
to_write = buf->buf_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_msg_write(buf->buf_origin, buf->buf_offset, in, to_write);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
*nr_written = to_write;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
86
lib/libxpc/include/xpc/buffer.h
Normal file
86
lib/libxpc/include/xpc/buffer.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#ifndef XPC_BUFFER_H_
|
||||||
|
#define XPC_BUFFER_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <xpc/status.h>
|
||||||
|
|
||||||
|
#define XPC_BUFFER_IN(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.buf_flags = XPC_BUFFER_F_IN | XPC_BUFFER_F_REMOTE, \
|
||||||
|
.buf_origin = (msg), \
|
||||||
|
.buf_offset = (offset), \
|
||||||
|
.buf_len = (size), \
|
||||||
|
}
|
||||||
|
#define XPC_BUFFER_OUT(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.buf_flags = XPC_BUFFER_F_OUT | XPC_BUFFER_F_REMOTE, \
|
||||||
|
.buf_origin = (msg), \
|
||||||
|
.buf_offset = (offset), \
|
||||||
|
.buf_len = (size), \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xpc_msg;
|
||||||
|
|
||||||
|
typedef enum xpc_buffer_flags {
|
||||||
|
/* the buffer can be read from */
|
||||||
|
XPC_BUFFER_F_IN = 0x01u,
|
||||||
|
/* the buffer can be written to */
|
||||||
|
XPC_BUFFER_F_OUT = 0x02u,
|
||||||
|
/* the buffer is backed by a buffer located in another address space.
|
||||||
|
* the buffer can only be accessed via xpc_buffer_read and/or
|
||||||
|
* xpc_buffer_write */
|
||||||
|
XPC_BUFFER_F_REMOTE = 0x04u,
|
||||||
|
/* free the buffer backing this buffer when the buffer is discarded.
|
||||||
|
* this is only used for out-buffers. the buffer must have been
|
||||||
|
* allocated using xpc_context_alloc, as it will be freed via a call
|
||||||
|
* to xpc_context_free */
|
||||||
|
XPC_BUFFER_F_FREE_ON_DISCARD = 0x08u,
|
||||||
|
} xpc_buffer_flags_t;
|
||||||
|
|
||||||
|
typedef struct xpc_buffer {
|
||||||
|
xpc_buffer_flags_t buf_flags;
|
||||||
|
union {
|
||||||
|
/* fields that are only valid if F_OUT is set */
|
||||||
|
struct {
|
||||||
|
/* only valid if F_OUT is set. specifies the maximum
|
||||||
|
* number of chars that can be written to buf_buf,
|
||||||
|
* including the null terminator. */
|
||||||
|
size_t buf_max;
|
||||||
|
/* only valid if F_OUT is set.
|
||||||
|
* if F_FREE_ON_DISCARD is set, must be either NULL or
|
||||||
|
* allocated via xpc_context_alloc */
|
||||||
|
const char *buf_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* fields that are only valid if F_IN is set */
|
||||||
|
struct {
|
||||||
|
/* only valid if F_IN is set. offset of the buffer data
|
||||||
|
* within the associated message. used when reading
|
||||||
|
* buffer data from a message. */
|
||||||
|
size_t buf_offset;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* only valid if F_REMOTE is set.
|
||||||
|
* used to read/write buffer data from/to the sender's address
|
||||||
|
* space. */
|
||||||
|
const struct xpc_msg *buf_origin;
|
||||||
|
|
||||||
|
/* valid for both F_IN and F_OUT buffers.
|
||||||
|
* F_IN: specifies the length of the incoming buffer data.
|
||||||
|
* F_OUT: specifies how many bytes from buf_ptr to send. */
|
||||||
|
size_t buf_len;
|
||||||
|
} xpc_buffer_t;
|
||||||
|
|
||||||
|
extern xpc_status_t xpc_buffer_read(
|
||||||
|
const xpc_buffer_t *s,
|
||||||
|
void *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read);
|
||||||
|
extern xpc_status_t xpc_buffer_write(
|
||||||
|
xpc_buffer_t *s,
|
||||||
|
const void *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written);
|
||||||
|
|
||||||
|
#endif
|
||||||
8
lib/libxpc/include/xpc/context.h
Normal file
8
lib/libxpc/include/xpc/context.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef XPC_CONTEXT_H_
|
||||||
|
#define XPC_CONTEXT_H_
|
||||||
|
|
||||||
|
typedef struct xpc_context {
|
||||||
|
|
||||||
|
} xpc_context_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/libxpc/include/xpc/endpoint.h
Normal file
13
lib/libxpc/include/xpc/endpoint.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef XPC_ENDPOINT_H_
|
||||||
|
#define XPC_ENDPOINT_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
typedef struct xpc_endpoint {
|
||||||
|
kern_handle_t e_channel;
|
||||||
|
tid_t e_task;
|
||||||
|
koid_t e_port;
|
||||||
|
msgid_t e_msg;
|
||||||
|
} xpc_endpoint_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
53
lib/libxpc/include/xpc/msg.h
Normal file
53
lib/libxpc/include/xpc/msg.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef XPC_MSG_H_
|
||||||
|
#define XPC_MSG_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <xpc/endpoint.h>
|
||||||
|
|
||||||
|
#define XPC_MSG_MAGIC 0x5850434D
|
||||||
|
|
||||||
|
typedef struct xpc_msg_header {
|
||||||
|
uint32_t hdr_magic;
|
||||||
|
uint32_t hdr_interface;
|
||||||
|
uint16_t hdr_func;
|
||||||
|
uint16_t hdr_status;
|
||||||
|
} xpc_msg_header_t;
|
||||||
|
|
||||||
|
typedef struct xpc_msg {
|
||||||
|
xpc_endpoint_t msg_sender;
|
||||||
|
xpc_msg_header_t msg_header;
|
||||||
|
size_t msg_handles_count;
|
||||||
|
|
||||||
|
kern_msg_handle_t msg_handles[KERN_MSG_MAX_HANDLES];
|
||||||
|
} xpc_msg_t;
|
||||||
|
|
||||||
|
extern void xpc_msg_header_init(
|
||||||
|
xpc_msg_header_t *msg,
|
||||||
|
unsigned long interface,
|
||||||
|
unsigned short func);
|
||||||
|
extern bool xpc_msg_header_validate(const xpc_msg_header_t *msg);
|
||||||
|
extern kern_status_t xpc_msg_recv(kern_handle_t channel, xpc_msg_t *out);
|
||||||
|
extern kern_status_t xpc_msg_read(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
void *p,
|
||||||
|
size_t count);
|
||||||
|
extern kern_status_t xpc_msg_write(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
const void *p,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
|
extern kern_status_t xpc_msg_reply(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
kern_iovec_t *iov,
|
||||||
|
size_t iov_count,
|
||||||
|
kern_msg_handle_t *handles,
|
||||||
|
size_t handle_count);
|
||||||
|
extern kern_status_t xpc_msg_reply_error(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
unsigned short code);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
lib/libxpc/include/xpc/status.h
Normal file
12
lib/libxpc/include/xpc/status.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef XPC_STATUS_H_
|
||||||
|
#define XPC_STATUS_H_
|
||||||
|
|
||||||
|
typedef enum xpc_status {
|
||||||
|
XPC_SUCCESS = 0,
|
||||||
|
XPC_ERR_BAD_STATE,
|
||||||
|
XPC_ERR_INVALID_ARGUMENT,
|
||||||
|
XPC_ERR_NO_MEMORY,
|
||||||
|
XPC_ERR_MEMORY_FAULT,
|
||||||
|
} xpc_status_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
85
lib/libxpc/include/xpc/string.h
Normal file
85
lib/libxpc/include/xpc/string.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#ifndef XPC_STRING_H_
|
||||||
|
#define XPC_STRING_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <xpc/status.h>
|
||||||
|
|
||||||
|
#define XPC_STRING_NPOS ((size_t)-1)
|
||||||
|
|
||||||
|
#define XPC_STRING_IN(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.s_flags = XPC_STRING_F_IN | XPC_STRING_F_REMOTE, \
|
||||||
|
.s_origin = (msg), \
|
||||||
|
.s_offset = (offset), \
|
||||||
|
.s_len = (size), \
|
||||||
|
}
|
||||||
|
#define XPC_STRING_OUT(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.s_flags = XPC_STRING_F_OUT | XPC_STRING_F_REMOTE, \
|
||||||
|
.s_origin = (msg), \
|
||||||
|
.s_offset = (offset), \
|
||||||
|
.s_len = (size), \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xpc_msg;
|
||||||
|
|
||||||
|
typedef enum xpc_string_flags {
|
||||||
|
/* the string can be read from */
|
||||||
|
XPC_STRING_F_IN = 0x01u,
|
||||||
|
/* the string can be written to */
|
||||||
|
XPC_STRING_F_OUT = 0x02u,
|
||||||
|
/* the string is backed by a buffer located in another address space.
|
||||||
|
* the string can only be accessed via xpc_string_read and/or
|
||||||
|
* xpc_string_write */
|
||||||
|
XPC_STRING_F_REMOTE = 0x04u,
|
||||||
|
/* free the buffer backing this string when the string is discarded.
|
||||||
|
* this is only used for out-strings. the buffer must have been
|
||||||
|
* allocated using xpc_context_alloc, as it will be freed via a call
|
||||||
|
* to xpc_context_free */
|
||||||
|
XPC_STRING_F_FREE_ON_DISCARD = 0x08u,
|
||||||
|
} xpc_string_flags_t;
|
||||||
|
|
||||||
|
typedef struct xpc_string {
|
||||||
|
xpc_string_flags_t s_flags;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
/* only valid if F_OUT is set. specifies the maximum
|
||||||
|
* number of chars that can be written to s_buf,
|
||||||
|
* including the null terminator. */
|
||||||
|
size_t s_max;
|
||||||
|
/* only valid if F_OUT is set.
|
||||||
|
* if F_FREE_ON_DISCARD is set, must be either NULL or
|
||||||
|
* allocated via xpc_context_alloc */
|
||||||
|
const char *s_buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* only valid if F_IN is set. offset of the string data
|
||||||
|
* within the associated message. used when reading
|
||||||
|
* string data from a message. */
|
||||||
|
size_t s_offset;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* only valid if F_REMOTE is set.
|
||||||
|
* used to read/write string data from/to the sender's address space. */
|
||||||
|
const struct xpc_msg *s_origin;
|
||||||
|
|
||||||
|
/* valid for both F_IN and F_OUT strings.
|
||||||
|
* F_IN: specifies the length of the incoming string data.
|
||||||
|
* F_OUT: specifies how many characters from s_buf to send. */
|
||||||
|
size_t s_len;
|
||||||
|
} xpc_string_t;
|
||||||
|
|
||||||
|
extern xpc_status_t xpc_string_read(
|
||||||
|
const xpc_string_t *s,
|
||||||
|
char *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read);
|
||||||
|
extern xpc_status_t xpc_string_write(
|
||||||
|
xpc_string_t *s,
|
||||||
|
const char *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written);
|
||||||
|
|
||||||
|
#endif
|
||||||
112
lib/libxpc/msg.c
Normal file
112
lib/libxpc/msg.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#include <mango/msg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
|
void xpc_msg_header_init(
|
||||||
|
xpc_msg_header_t *msg,
|
||||||
|
unsigned long interface,
|
||||||
|
unsigned short func)
|
||||||
|
{
|
||||||
|
memset(msg, 0x0, sizeof *msg);
|
||||||
|
|
||||||
|
msg->hdr_magic = XPC_MSG_MAGIC;
|
||||||
|
msg->hdr_interface = interface;
|
||||||
|
msg->hdr_func = func;
|
||||||
|
msg->hdr_status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xpc_msg_header_validate(const xpc_msg_header_t *msg)
|
||||||
|
{
|
||||||
|
return msg->hdr_magic == XPC_MSG_MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_recv(kern_handle_t channel, xpc_msg_t *out)
|
||||||
|
{
|
||||||
|
kern_iovec_t iov = IOVEC(&out->msg_header, sizeof out->msg_header);
|
||||||
|
kern_msg_t msg = {
|
||||||
|
.msg_data = &iov,
|
||||||
|
.msg_data_count = 1,
|
||||||
|
.msg_handles = out->msg_handles,
|
||||||
|
.msg_handles_count = KERN_MSG_MAX_HANDLES,
|
||||||
|
};
|
||||||
|
kern_status_t status = msg_recv(channel, &msg);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xpc_msg_header_validate(&out->msg_header)) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->msg_sender.e_channel = channel;
|
||||||
|
out->msg_sender.e_task = msg.msg_sender;
|
||||||
|
out->msg_sender.e_port = msg.msg_endpoint;
|
||||||
|
out->msg_sender.e_msg = msg.msg_id;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_read(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
void *p,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
kern_iovec_t iov = IOVEC(p, count);
|
||||||
|
size_t r = 0;
|
||||||
|
return msg_read(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
offset,
|
||||||
|
&iov,
|
||||||
|
1,
|
||||||
|
&r);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_write(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
const void *p,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
kern_iovec_t iov = IOVEC(p, count);
|
||||||
|
size_t w = 0;
|
||||||
|
return msg_write(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
offset,
|
||||||
|
&iov,
|
||||||
|
1,
|
||||||
|
&w);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_reply(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
kern_iovec_t *iov,
|
||||||
|
size_t iov_count,
|
||||||
|
kern_msg_handle_t *handles,
|
||||||
|
size_t handle_count)
|
||||||
|
{
|
||||||
|
kern_msg_t reply = MSG(iov, iov_count, handles, handle_count);
|
||||||
|
return msg_reply(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
&reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_reply_error(const xpc_msg_t *msg, unsigned short code)
|
||||||
|
{
|
||||||
|
xpc_msg_header_t reply_data = {
|
||||||
|
.hdr_magic = XPC_MSG_MAGIC,
|
||||||
|
.hdr_interface = msg->msg_header.hdr_interface,
|
||||||
|
.hdr_func = msg->msg_header.hdr_func,
|
||||||
|
.hdr_status = code,
|
||||||
|
};
|
||||||
|
|
||||||
|
kern_iovec_t iov = IOVEC(&reply_data, sizeof reply_data);
|
||||||
|
kern_msg_t reply = MSG(&iov, 1, NULL, 0);
|
||||||
|
return msg_reply(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
&reply);
|
||||||
|
}
|
||||||
60
lib/libxpc/string.c
Normal file
60
lib/libxpc/string.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#include <mango/status.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
#include <xpc/string.h>
|
||||||
|
|
||||||
|
xpc_status_t xpc_string_read(
|
||||||
|
const xpc_string_t *s,
|
||||||
|
char *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read)
|
||||||
|
{
|
||||||
|
if ((s->s_flags & (XPC_STRING_F_IN | XPC_STRING_F_REMOTE))
|
||||||
|
!= (XPC_STRING_F_IN | XPC_STRING_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_read = max - 1;
|
||||||
|
if (to_read > s->s_len) {
|
||||||
|
to_read = s->s_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_msg_read(s->s_origin, s->s_offset, out, to_read);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[to_read] = '\0';
|
||||||
|
/* TODO */
|
||||||
|
*nr_read = to_read;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpc_status_t xpc_string_write(
|
||||||
|
xpc_string_t *s,
|
||||||
|
const char *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
if ((s->s_flags & (XPC_STRING_F_OUT | XPC_STRING_F_REMOTE))
|
||||||
|
!= (XPC_STRING_F_IN | XPC_STRING_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_write = len;
|
||||||
|
if (to_write > s->s_max - 1) {
|
||||||
|
to_write = s->s_max - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_msg_write(s->s_origin, s->s_offset, in, to_write);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
*nr_written = to_write;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ set_property(SOURCE ${arch_sources} PROPERTY LANGUAGE C)
|
|||||||
add_executable(bootstrap ${c_sources} ${arch_sources})
|
add_executable(bootstrap ${c_sources} ${arch_sources})
|
||||||
|
|
||||||
target_link_libraries(bootstrap
|
target_link_libraries(bootstrap
|
||||||
libmango libc-core libc-malloc libfs-static liblaunch
|
libmango libc-core libc-malloc libfs-static liblaunch libxpc-static
|
||||||
interface::fs)
|
interface::fs)
|
||||||
|
|
||||||
target_compile_options(bootstrap PRIVATE
|
target_compile_options(bootstrap PRIVATE
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ static enum launch_status resolve_dependency(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static kern_status_t open(
|
static kern_status_t open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
const char *path,
|
const char *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
@@ -178,51 +179,46 @@ int main(
|
|||||||
.fs_arg = &heap,
|
.fs_arg = &heap,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_context *fs = fs_context_create(&fs_allocator, NULL);
|
struct fs_context *fs = fs_context_create(&fs_allocator);
|
||||||
if (!fs) {
|
if (!fs) {
|
||||||
kern_logf("cannot initialise fs");
|
kern_logf("cannot initialise fs");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_status = fs_context_mount_filesystem(
|
||||||
|
fs,
|
||||||
|
tar_mount,
|
||||||
|
(void *)bsp_base,
|
||||||
|
0);
|
||||||
|
if (fs_status != FS_SUCCESS) {
|
||||||
|
kern_logf("cannot mount filesustem (%d)", fs_status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct msg_endpoint sender;
|
xpc_msg_t msg;
|
||||||
struct msg_header hdr;
|
kern_status_t status = xpc_msg_recv(channel, &msg);
|
||||||
kern_msg_handle_t handles[KERN_MSG_MAX_HANDLES] = {0};
|
|
||||||
kern_status_t status = msg_recv_generic(
|
|
||||||
channel,
|
|
||||||
&sender,
|
|
||||||
&hdr,
|
|
||||||
handles,
|
|
||||||
KERN_MSG_MAX_HANDLES);
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
kern_logf("message recv error %d", status);
|
kern_logf("message recv error %d", status);
|
||||||
msg_reply_generic(
|
|
||||||
channel,
|
|
||||||
&sender,
|
|
||||||
&hdr,
|
|
||||||
KERN_UNSUPPORTED);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (hdr.hdr_protocol) {
|
switch (msg.msg_header.hdr_interface) {
|
||||||
case PROTOCOL_FS:
|
case INTERFACE_FS:
|
||||||
status = fs_context_dispatch_msg(
|
status = fs_context_dispatch_msg(fs, &msg);
|
||||||
fs,
|
|
||||||
channel,
|
|
||||||
&sender,
|
|
||||||
&hdr);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
kern_logf(
|
kern_logf(
|
||||||
"unknown message protocol %u",
|
"unknown message protocol %u",
|
||||||
hdr.hdr_protocol);
|
msg.msg_header.hdr_interface);
|
||||||
msg_reply_generic(
|
xpc_msg_reply_error(&msg, KERN_UNSUPPORTED);
|
||||||
channel,
|
|
||||||
&sender,
|
|
||||||
&hdr,
|
|
||||||
KERN_UNSUPPORTED);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_logf("message reply error %d", status);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
138
sys/bootstrap/queue.c
Normal file
138
sys/bootstrap/queue.c
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
size_t queue_length(struct queue *q)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
struct queue_entry *x = q->q_first;
|
||||||
|
while (x) {
|
||||||
|
i++;
|
||||||
|
x = x->qe_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_insert_before(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *before)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = before->qe_prev;
|
||||||
|
if (x) {
|
||||||
|
x->qe_next = entry;
|
||||||
|
} else {
|
||||||
|
q->q_first = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_prev = x;
|
||||||
|
|
||||||
|
before->qe_prev = entry;
|
||||||
|
entry->qe_next = before;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_insert_after(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *after)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = after->qe_next;
|
||||||
|
if (x) {
|
||||||
|
x->qe_prev = entry;
|
||||||
|
} else {
|
||||||
|
q->q_last = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_prev = x;
|
||||||
|
|
||||||
|
after->qe_next = entry;
|
||||||
|
entry->qe_prev = after;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push_front(struct queue *q, struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
if (q->q_first) {
|
||||||
|
q->q_first->qe_prev = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_next = q->q_first;
|
||||||
|
entry->qe_prev = NULL;
|
||||||
|
|
||||||
|
q->q_first = entry;
|
||||||
|
|
||||||
|
if (!q->q_last) {
|
||||||
|
q->q_last = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push_back(struct queue *q, struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
if (q->q_last) {
|
||||||
|
q->q_last->qe_next = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_prev = q->q_last;
|
||||||
|
entry->qe_next = NULL;
|
||||||
|
|
||||||
|
q->q_last = entry;
|
||||||
|
|
||||||
|
if (!q->q_first) {
|
||||||
|
q->q_first = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct queue_entry *queue_pop_front(struct queue *q)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = q->q_first;
|
||||||
|
if (x) {
|
||||||
|
queue_delete(q, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct queue_entry *queue_pop_back(struct queue *q)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = q->q_last;
|
||||||
|
if (x) {
|
||||||
|
queue_delete(q, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_delete(struct queue *q, struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == q->q_first) {
|
||||||
|
q->q_first = q->q_first->qe_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == q->q_last) {
|
||||||
|
q->q_last = q->q_last->qe_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->qe_next) {
|
||||||
|
entry->qe_next->qe_prev = entry->qe_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->qe_prev) {
|
||||||
|
entry->qe_prev->qe_next = entry->qe_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_next = entry->qe_prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_delete_all(struct queue *q)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = q->q_first;
|
||||||
|
while (x) {
|
||||||
|
struct queue_entry *next = x->qe_next;
|
||||||
|
x->qe_next = x->qe_prev = NULL;
|
||||||
|
x = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->q_first = q->q_last = NULL;
|
||||||
|
}
|
||||||
100
sys/bootstrap/queue.h
Normal file
100
sys/bootstrap/queue.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#ifndef QUEUE_H_
|
||||||
|
#define QUEUE_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define QUEUE_CONTAINER(t, m, v) \
|
||||||
|
((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
|
||||||
|
|
||||||
|
#define QUEUE_INIT ((struct queue) {.q_first = NULL, .q_last = NULL})
|
||||||
|
#define QUEUE_ENTRY_INIT \
|
||||||
|
((struct queue_entry) {.qe_next = NULL, .qe_prev = NULL})
|
||||||
|
|
||||||
|
#define queue_foreach(iter_type, iter_name, queue_name, node_member) \
|
||||||
|
for (iter_type *iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_first(queue_name)); \
|
||||||
|
iter_name; \
|
||||||
|
iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_next(&((iter_name)->node_member))))
|
||||||
|
|
||||||
|
#define queue_foreach_r(iter_type, iter_name, queue_name, node_member) \
|
||||||
|
for (iter_type *iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_last(queue_name)); \
|
||||||
|
iter_name; \
|
||||||
|
iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_prev(&((iter_name)->node_member))))
|
||||||
|
|
||||||
|
struct queue_entry {
|
||||||
|
struct queue_entry *qe_next;
|
||||||
|
struct queue_entry *qe_prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct queue {
|
||||||
|
struct queue_entry *q_first;
|
||||||
|
struct queue_entry *q_last;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void queue_init(struct queue *q)
|
||||||
|
{
|
||||||
|
memset(q, 0x00, sizeof *q);
|
||||||
|
}
|
||||||
|
static inline bool queue_empty(struct queue *q)
|
||||||
|
{
|
||||||
|
return q->q_first == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct queue_entry *queue_first(struct queue *q)
|
||||||
|
{
|
||||||
|
return q->q_first;
|
||||||
|
}
|
||||||
|
static inline struct queue_entry *queue_last(struct queue *q)
|
||||||
|
{
|
||||||
|
return q->q_last;
|
||||||
|
}
|
||||||
|
static inline struct queue_entry *queue_next(struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
return entry->qe_next;
|
||||||
|
}
|
||||||
|
static inline struct queue_entry *queue_prev(struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
return entry->qe_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern size_t queue_length(struct queue *q);
|
||||||
|
|
||||||
|
extern void queue_insert_before(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *before);
|
||||||
|
extern void queue_insert_after(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *after);
|
||||||
|
|
||||||
|
extern void queue_push_front(struct queue *q, struct queue_entry *entry);
|
||||||
|
extern void queue_push_back(struct queue *q, struct queue_entry *entry);
|
||||||
|
|
||||||
|
extern struct queue_entry *queue_pop_front(struct queue *q);
|
||||||
|
extern struct queue_entry *queue_pop_back(struct queue *q);
|
||||||
|
|
||||||
|
extern void queue_delete(struct queue *q, struct queue_entry *entry);
|
||||||
|
extern void queue_delete_all(struct queue *q);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,8 +1,30 @@
|
|||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
#include <fs/dentry.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/inode.h>
|
||||||
|
#include <fs/superblock.h>
|
||||||
#include <mango/handle.h>
|
#include <mango/handle.h>
|
||||||
|
#include <mango/log.h>
|
||||||
#include <mango/vm.h>
|
#include <mango/vm.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <xpc/buffer.h>
|
||||||
|
|
||||||
|
struct tar_superblock {
|
||||||
|
struct fs_superblock sb_base;
|
||||||
|
struct tar_bin_header *sb_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tar_entry {
|
||||||
|
struct fs_dentry e_dentry;
|
||||||
|
struct fs_inode e_inode;
|
||||||
|
void *e_data;
|
||||||
|
struct queue_entry e_entry;
|
||||||
|
struct queue e_children;
|
||||||
|
};
|
||||||
|
|
||||||
size_t getsize(const char *in)
|
size_t getsize(const char *in)
|
||||||
{
|
{
|
||||||
@@ -94,3 +116,300 @@ int tar_header_decode(const struct tar_bin_header *in, struct tar_header *out)
|
|||||||
out->size = getsize(in->size);
|
out->size = getsize(in->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct tar_entry *entry_from_dentry(struct fs_dentry *dent)
|
||||||
|
{
|
||||||
|
return QUEUE_CONTAINER(struct tar_entry, e_dentry, dent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tar_entry *entry_from_inode(struct fs_inode *inode)
|
||||||
|
{
|
||||||
|
return QUEUE_CONTAINER(struct tar_entry, e_inode, inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tar_entry *entry_get_child(
|
||||||
|
struct tar_entry *entry,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct queue_entry *cur = queue_first(&entry->e_children);
|
||||||
|
while (cur) {
|
||||||
|
struct tar_entry *child
|
||||||
|
= QUEUE_CONTAINER(struct tar_entry, e_entry, cur);
|
||||||
|
|
||||||
|
if (!strcmp(child->e_dentry.d_name, name)) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = queue_next(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fs_dentry_ops dentry_ops = {};
|
||||||
|
|
||||||
|
static enum fs_status dir_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out)
|
||||||
|
{
|
||||||
|
struct tar_entry *entry = entry_from_inode(inode);
|
||||||
|
struct tar_entry *child = entry_get_child(entry, name);
|
||||||
|
if (!child) {
|
||||||
|
return FS_ERR_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = &child->e_dentry;
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fs_status file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
xpc_buffer_t *buf,
|
||||||
|
size_t count,
|
||||||
|
off_t *seek)
|
||||||
|
{
|
||||||
|
off_t offset = *seek;
|
||||||
|
struct tar_entry *entry = entry_from_inode(fs_file_get_inode(f));
|
||||||
|
if (!entry) {
|
||||||
|
return FS_ERR_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset >= entry->e_inode.i_size) {
|
||||||
|
count = 0;
|
||||||
|
} else if (offset + count > entry->e_inode.i_size) {
|
||||||
|
count = entry->e_inode.i_size - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *src = (char *)entry->e_data + offset;
|
||||||
|
size_t w;
|
||||||
|
xpc_buffer_write(buf, src, count, &w);
|
||||||
|
|
||||||
|
offset += count;
|
||||||
|
*seek = offset;
|
||||||
|
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fs_file_ops file_ops = {
|
||||||
|
.f_read = file_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct fs_inode_ops file_inode_ops = {
|
||||||
|
.i_lookup = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct fs_inode_ops dir_inode_ops = {
|
||||||
|
.i_lookup = dir_lookup,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct tar_entry *create_dir_entry(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
struct tar_superblock *sb,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct tar_entry *entry = fs_context_alloc(ctx, sizeof *entry);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(entry, 0x0, sizeof *entry);
|
||||||
|
|
||||||
|
entry->e_inode.i_sb = &sb->sb_base;
|
||||||
|
entry->e_inode.i_mode = FS_INODE_DIR;
|
||||||
|
entry->e_inode.i_ops = &dir_inode_ops;
|
||||||
|
|
||||||
|
entry->e_dentry.d_sb = &sb->sb_base;
|
||||||
|
entry->e_dentry.d_ops = &dentry_ops;
|
||||||
|
entry->e_dentry.d_inode = &entry->e_inode;
|
||||||
|
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
entry->e_dentry.d_name = fs_context_alloc(ctx, name_len + 1);
|
||||||
|
if (!entry->e_dentry.d_name) {
|
||||||
|
fs_context_free(ctx, entry);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(entry->e_dentry.d_name, name, name_len + 1);
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tar_entry *create_file_entry(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
struct tar_superblock *sb,
|
||||||
|
struct tar_header *header,
|
||||||
|
void *data,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct tar_entry *entry = fs_context_alloc(ctx, sizeof *entry);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(entry, 0x0, sizeof *entry);
|
||||||
|
|
||||||
|
entry->e_inode.i_sb = &sb->sb_base;
|
||||||
|
entry->e_inode.i_mode = FS_INODE_REG;
|
||||||
|
entry->e_inode.i_ops = &file_inode_ops;
|
||||||
|
entry->e_inode.i_fops = &file_ops;
|
||||||
|
entry->e_inode.i_size = header->size;
|
||||||
|
|
||||||
|
entry->e_dentry.d_sb = &sb->sb_base;
|
||||||
|
entry->e_dentry.d_ops = &dentry_ops;
|
||||||
|
entry->e_dentry.d_inode = &entry->e_inode;
|
||||||
|
|
||||||
|
entry->e_data = data;
|
||||||
|
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
entry->e_dentry.d_name = fs_context_alloc(ctx, name_len + 1);
|
||||||
|
if (!entry->e_dentry.d_name) {
|
||||||
|
fs_context_free(ctx, entry);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(entry->e_dentry.d_name, name, name_len + 1);
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t get_first_path_component(const char *in, char *out, size_t max)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < max - 1) {
|
||||||
|
if (in[i] == '\0' || in[i] == '/') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = in[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fs_status add_entry_to_tree(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
struct tar_superblock *sb,
|
||||||
|
struct tar_header *entry,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct tar_entry *cur = entry_from_dentry(sb->sb_base.s_root);
|
||||||
|
const char *path = entry->filename;
|
||||||
|
|
||||||
|
char tok[256];
|
||||||
|
|
||||||
|
while (*path != '\0') {
|
||||||
|
while (*path == '/') {
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tok_len
|
||||||
|
= get_first_path_component(path, tok, sizeof tok);
|
||||||
|
|
||||||
|
if (!tok_len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tar_entry *next = entry_get_child(cur, tok);
|
||||||
|
bool is_file = *(path + tok_len) == '\0';
|
||||||
|
if (next) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_file) {
|
||||||
|
next = create_file_entry(ctx, sb, entry, data, tok);
|
||||||
|
} else {
|
||||||
|
next = create_dir_entry(ctx, sb, tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next) {
|
||||||
|
return FS_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_push_back(&cur->e_children, &next->e_entry);
|
||||||
|
next->e_dentry.d_parent = &cur->e_dentry;
|
||||||
|
|
||||||
|
next:
|
||||||
|
cur = next;
|
||||||
|
path += tok_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fs_status build_dentry_tree(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
struct tar_superblock *sb)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct tar_entry *root = create_dir_entry(ctx, sb, "/");
|
||||||
|
if (!root) {
|
||||||
|
return FS_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->sb_base.s_root = &root->e_dentry;
|
||||||
|
struct tar_bin_header *bin_header = sb->sb_data;
|
||||||
|
struct tar_header header;
|
||||||
|
enum fs_status status = FS_SUCCESS;
|
||||||
|
|
||||||
|
for (size_t i = 0;; i++) {
|
||||||
|
tar_header_decode(bin_header, &header);
|
||||||
|
if (bin_header->filename[0] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *s = (char *)bin_header;
|
||||||
|
s += sizeof *bin_header;
|
||||||
|
|
||||||
|
bool add = true;
|
||||||
|
|
||||||
|
if (!strcmp(header.filename, "././@PaxHeader")) {
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
status = add_entry_to_tree(ctx, sb, &header, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += header.size;
|
||||||
|
s += ((sizeof *bin_header)
|
||||||
|
- ((uintptr_t)s % (sizeof *bin_header)));
|
||||||
|
|
||||||
|
bin_header = (struct tar_bin_header *)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status tar_mount(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags,
|
||||||
|
struct fs_superblock **out)
|
||||||
|
{
|
||||||
|
struct tar_superblock *sb = fs_context_alloc(ctx, sizeof *sb);
|
||||||
|
if (!sb) {
|
||||||
|
return FS_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->sb_data = arg;
|
||||||
|
|
||||||
|
enum fs_status status = build_dentry_tree(ctx, sb);
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
fs_context_free(ctx, sb);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = (struct fs_superblock *)sb;
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef TAR_H_
|
#ifndef TAR_H_
|
||||||
#define TAR_H_
|
#define TAR_H_
|
||||||
|
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/status.h>
|
||||||
#include <mango/types.h>
|
#include <mango/types.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -42,4 +44,10 @@ extern int tar_header_decode(
|
|||||||
const struct tar_bin_header *in,
|
const struct tar_bin_header *in,
|
||||||
struct tar_header *out);
|
struct tar_header *out);
|
||||||
|
|
||||||
|
extern enum fs_status tar_mount(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags,
|
||||||
|
struct fs_superblock **out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ set_target_properties(ld PROPERTIES
|
|||||||
SUFFIX ".so")
|
SUFFIX ".so")
|
||||||
|
|
||||||
target_link_libraries(ld
|
target_link_libraries(ld
|
||||||
libc-core libc-malloc libmango librosetta
|
libc-core libc-malloc libc-io libmango librosetta libxpc-static
|
||||||
interface::fs)
|
interface::fs)
|
||||||
|
|
||||||
target_compile_options(ld PRIVATE
|
target_compile_options(ld PRIVATE
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#define MSG_IMPLEMENTATION
|
#define MSG_IMPLEMENTATION
|
||||||
#define MSG_NO_MALLOC
|
#define MSG_NO_MALLOC
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <heap/heap.h>
|
#include <heap/heap.h>
|
||||||
#include <mango/log.h>
|
#include <mango/log.h>
|
||||||
#include <mango/msg.h>
|
#include <mango/msg.h>
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int main(const struct rosetta_bootstrap *bs)
|
int main(const struct rosetta_bootstrap *bs)
|
||||||
@@ -24,32 +26,39 @@ int main(const struct rosetta_bootstrap *bs)
|
|||||||
kern_logf("argv[%zu]: %s", i, bs->bs_argv[i]);
|
kern_logf("argv[%zu]: %s", i, bs->bs_argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_handle_t port;
|
sys_remote_set(SYS_REMOTE_NSD, 0, 0);
|
||||||
kern_status_t status = port_create(&port);
|
|
||||||
if (status != KERN_OK) {
|
|
||||||
kern_logf("port creation failed %d", status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
port_connect(port, 0, 0);
|
|
||||||
|
|
||||||
const char *path = "/usr/lib/libc.so";
|
const char *path = "/usr/lib/libc.so";
|
||||||
int flags = 4;
|
int flags = 4;
|
||||||
int err = 0;
|
int fd = open(path, flags);
|
||||||
|
|
||||||
kern_logf("sending msg: open(%s, %d)", path, flags);
|
kern_logf("sending msg: open(%s, %d)", path, flags);
|
||||||
status = fs_open(port, path, flags, &err);
|
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (fd < 0) {
|
||||||
kern_logf("open call failed (status %d)", status);
|
|
||||||
} else {
|
|
||||||
kern_logf(
|
kern_logf(
|
||||||
"open(%s, %d) = %s (%s)",
|
"open(%s, %d) = %s (%s)",
|
||||||
path,
|
path,
|
||||||
flags,
|
flags,
|
||||||
strerror_code(err),
|
strerror_code(fd),
|
||||||
strerror(err));
|
strerror(fd));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_logf(
|
||||||
|
"open(%s, %d) = %s (%s)",
|
||||||
|
path,
|
||||||
|
flags,
|
||||||
|
strerror_code(SUCCESS),
|
||||||
|
strerror(SUCCESS));
|
||||||
|
|
||||||
|
unsigned char buf[32] = {0};
|
||||||
|
int nr = read(fd, buf, sizeof buf);
|
||||||
|
|
||||||
|
if (nr < 0) {
|
||||||
|
kern_logf("read call failed (%s)", strerror(nr));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_logf("data: %x %c %c %c", buf[0], buf[1], buf[2], buf[3]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@ add_subdirectory(
|
|||||||
../kernel/tools
|
../kernel/tools
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/kernel-tools)
|
${CMAKE_CURRENT_BINARY_DIR}/kernel-tools)
|
||||||
|
|
||||||
add_subdirectory(ifc)
|
add_subdirectory(xpcg)
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
file(GLOB sources
|
|
||||||
*.c *.h
|
|
||||||
backend/c-mpc/*.c backend/c-mpc/*.h)
|
|
||||||
|
|
||||||
add_executable(ifc ${sources})
|
|
||||||
|
|
||||||
target_link_libraries(ifc Bluelib::Core Bluelib::Ds Bluelib::Cmd Bluelib::Io)
|
|
||||||
7
toolchain/xpcg/CMakeLists.txt
Normal file
7
toolchain/xpcg/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
*.c *.h
|
||||||
|
backend/c-mpc/*.c backend/c-mpc/*.h)
|
||||||
|
|
||||||
|
add_executable(xpcg ${sources})
|
||||||
|
|
||||||
|
target_link_libraries(xpcg Bluelib::Core Bluelib::Ds Bluelib::Cmd Bluelib::Io)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_BACKEND_H_
|
#ifndef XPCG_BACKEND_H_
|
||||||
#define IFC_BACKEND_H_
|
#define XPCG_BACKEND_H_
|
||||||
|
|
||||||
struct interface_definition;
|
struct interface_definition;
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,14 @@ const struct type *ctx_get_type(struct ctx *ctx, const char *name)
|
|||||||
return ctx_get_builtin_type(ctx, TYPE_HANDLE);
|
return ctx_get_builtin_type(ctx, TYPE_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(name, "size")) {
|
||||||
|
return ctx_get_builtin_type(ctx, TYPE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(name, "buffer")) {
|
||||||
|
return ctx_get_builtin_type(ctx, TYPE_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_CTX_H_
|
#ifndef XPCG_CTX_H_
|
||||||
#define IFC_CTX_H_
|
#define XPCG_CTX_H_
|
||||||
|
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_FILE_SPAN_H_
|
#ifndef XPCG_FILE_SPAN_H_
|
||||||
#define IFC_FILE_SPAN_H_
|
#define XPCG_FILE_SPAN_H_
|
||||||
|
|
||||||
struct file_cell {
|
struct file_cell {
|
||||||
unsigned int c_row, c_col;
|
unsigned int c_row, c_col;
|
||||||
@@ -6,7 +6,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct interface_definition *interface_definition_create(const char *name)
|
struct interface_definition *interface_definition_create(
|
||||||
|
const char *name,
|
||||||
|
long long id)
|
||||||
{
|
{
|
||||||
struct interface_definition *out = malloc(sizeof *out);
|
struct interface_definition *out = malloc(sizeof *out);
|
||||||
if (!out) {
|
if (!out) {
|
||||||
@@ -16,6 +18,7 @@ struct interface_definition *interface_definition_create(const char *name)
|
|||||||
memset(out, 0x0, sizeof *out);
|
memset(out, 0x0, sizeof *out);
|
||||||
|
|
||||||
out->if_name = b_strdup(name);
|
out->if_name = b_strdup(name);
|
||||||
|
out->if_id = id;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_INTERFACE_H_
|
#ifndef XPCG_INTERFACE_H_
|
||||||
#define IFC_INTERFACE_H_
|
#define XPCG_INTERFACE_H_
|
||||||
|
|
||||||
#include <blue/core/queue.h>
|
#include <blue/core/queue.h>
|
||||||
|
|
||||||
@@ -7,11 +7,13 @@ struct msg_definition;
|
|||||||
|
|
||||||
struct interface_definition {
|
struct interface_definition {
|
||||||
char *if_name;
|
char *if_name;
|
||||||
|
long long if_id;
|
||||||
b_queue if_msg;
|
b_queue if_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct interface_definition *interface_definition_create(
|
extern struct interface_definition *interface_definition_create(
|
||||||
const char *name);
|
const char *name,
|
||||||
|
long long id);
|
||||||
extern void interface_definition_destroy(struct interface_definition *iface);
|
extern void interface_definition_destroy(struct interface_definition *iface);
|
||||||
|
|
||||||
extern bool interface_definition_has_msg(
|
extern bool interface_definition_has_msg(
|
||||||
@@ -29,18 +29,21 @@
|
|||||||
static struct lex_token_def symbols[] = {
|
static struct lex_token_def symbols[] = {
|
||||||
LEX_TOKEN_DEF(SYM_COMMA, ","),
|
LEX_TOKEN_DEF(SYM_COMMA, ","),
|
||||||
LEX_TOKEN_DEF(SYM_HYPHEN, "-"),
|
LEX_TOKEN_DEF(SYM_HYPHEN, "-"),
|
||||||
|
LEX_TOKEN_DEF(SYM_LEFT_BRACKET, "["),
|
||||||
|
LEX_TOKEN_DEF(SYM_RIGHT_BRACKET, "]"),
|
||||||
LEX_TOKEN_DEF(SYM_LEFT_BRACE, "{"),
|
LEX_TOKEN_DEF(SYM_LEFT_BRACE, "{"),
|
||||||
LEX_TOKEN_DEF(SYM_RIGHT_BRACE, "}"),
|
LEX_TOKEN_DEF(SYM_RIGHT_BRACE, "}"),
|
||||||
LEX_TOKEN_DEF(SYM_LEFT_PAREN, "("),
|
LEX_TOKEN_DEF(SYM_LEFT_PAREN, "("),
|
||||||
LEX_TOKEN_DEF(SYM_RIGHT_PAREN, ")"),
|
LEX_TOKEN_DEF(SYM_RIGHT_PAREN, ")"),
|
||||||
LEX_TOKEN_DEF(SYM_SEMICOLON, ";"),
|
LEX_TOKEN_DEF(SYM_SEMICOLON, ";"),
|
||||||
|
LEX_TOKEN_DEF(SYM_COLON, ":"),
|
||||||
LEX_TOKEN_DEF(SYM_HYPHEN_RIGHT_ANGLE, "->"),
|
LEX_TOKEN_DEF(SYM_HYPHEN_RIGHT_ANGLE, "->"),
|
||||||
};
|
};
|
||||||
static const size_t nr_symbols = sizeof symbols / sizeof symbols[0];
|
static const size_t nr_symbols = sizeof symbols / sizeof symbols[0];
|
||||||
|
|
||||||
static struct lex_token_def keywords[] = {
|
static struct lex_token_def keywords[] = {
|
||||||
LEX_TOKEN_DEF(KW_INTERFACE, "interface"),
|
LEX_TOKEN_DEF(KW_INTERFACE, "interface"),
|
||||||
LEX_TOKEN_DEF(KW_MSG, "msg"),
|
LEX_TOKEN_DEF(KW_FUNC, "func"),
|
||||||
};
|
};
|
||||||
static const size_t nr_keywords = sizeof keywords / sizeof keywords[0];
|
static const size_t nr_keywords = sizeof keywords / sizeof keywords[0];
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_LEX_H_
|
#ifndef XPCG_LEX_H_
|
||||||
#define IFC_LEX_H_
|
#define XPCG_LEX_H_
|
||||||
|
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
@@ -64,7 +64,10 @@ static void print_interface(struct interface_definition *iface)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ifc(const b_command *self, const b_arglist *opt, const b_array *args)
|
static int xpcg(
|
||||||
|
const b_command *self,
|
||||||
|
const b_arglist *opt,
|
||||||
|
const b_array *args)
|
||||||
{
|
{
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
b_arglist_get_string(opt, B_COMMAND_INVALID_ID, ARG_SRCPATH, 0, &path);
|
b_arglist_get_string(opt, B_COMMAND_INVALID_ID, ARG_SRCPATH, 0, &path);
|
||||||
@@ -132,10 +135,10 @@ static int ifc(const b_command *self, const b_arglist *opt, const b_array *args)
|
|||||||
|
|
||||||
B_COMMAND(CMD_ID, B_COMMAND_INVALID_ID)
|
B_COMMAND(CMD_ID, B_COMMAND_INVALID_ID)
|
||||||
{
|
{
|
||||||
B_COMMAND_NAME("ifc");
|
B_COMMAND_NAME("xpcg");
|
||||||
B_COMMAND_DESC("interface definition compiler.");
|
B_COMMAND_DESC("xpc interface generator.");
|
||||||
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
|
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
|
||||||
B_COMMAND_FUNCTION(ifc);
|
B_COMMAND_FUNCTION(xpcg);
|
||||||
B_COMMAND_HELP_OPTION();
|
B_COMMAND_HELP_OPTION();
|
||||||
|
|
||||||
B_COMMAND_ARG(ARG_SRCPATH)
|
B_COMMAND_ARG(ARG_SRCPATH)
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct msg_definition *msg_definition_create(const char *name)
|
struct msg_definition *msg_definition_create(const char *name, long long id)
|
||||||
{
|
{
|
||||||
struct msg_definition *out = malloc(sizeof *out);
|
struct msg_definition *out = malloc(sizeof *out);
|
||||||
if (!out) {
|
if (!out) {
|
||||||
@@ -14,6 +14,7 @@ struct msg_definition *msg_definition_create(const char *name)
|
|||||||
memset(out, 0x0, sizeof *out);
|
memset(out, 0x0, sizeof *out);
|
||||||
|
|
||||||
out->msg_name = b_strdup(name);
|
out->msg_name = b_strdup(name);
|
||||||
|
out->msg_id = id;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_MSG_H_
|
#ifndef XPCG_MSG_H_
|
||||||
#define IFC_MSG_H_
|
#define XPCG_MSG_H_
|
||||||
|
|
||||||
#include <blue/core/queue.h>
|
#include <blue/core/queue.h>
|
||||||
|
|
||||||
@@ -13,13 +13,16 @@ struct msg_parameter {
|
|||||||
|
|
||||||
struct msg_definition {
|
struct msg_definition {
|
||||||
char *msg_name;
|
char *msg_name;
|
||||||
|
long long msg_id;
|
||||||
b_queue_entry msg_entry;
|
b_queue_entry msg_entry;
|
||||||
|
|
||||||
b_queue msg_params;
|
b_queue msg_params;
|
||||||
b_queue msg_results;
|
b_queue msg_results;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct msg_definition *msg_definition_create(const char *name);
|
extern struct msg_definition *msg_definition_create(
|
||||||
|
const char *name,
|
||||||
|
long long id);
|
||||||
extern void msg_definition_destroy(struct msg_definition *msg);
|
extern void msg_definition_destroy(struct msg_definition *msg);
|
||||||
|
|
||||||
extern bool msg_definition_has_param(
|
extern bool msg_definition_has_param(
|
||||||
@@ -48,26 +48,55 @@ static bool parse_word(struct lex *lex, char **out)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parse_int(struct lex *lex, long long *out)
|
||||||
|
{
|
||||||
|
struct token *tok = lex_peek(lex);
|
||||||
|
if (!tok || tok->tok_type != TOK_INT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = tok->tok_int;
|
||||||
|
lex_advance(lex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
||||||
{
|
{
|
||||||
struct msg_definition *msg = NULL;
|
struct msg_definition *msg = NULL;
|
||||||
|
|
||||||
if (!parse_keyword(lex, KW_MSG)) {
|
if (!parse_keyword(lex, KW_FUNC)) {
|
||||||
report_error("expected `msg` keyword\n");
|
report_error("expected `func` keyword\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *msg_name = NULL;
|
char *msg_name = NULL;
|
||||||
if (!parse_word(lex, &msg_name)) {
|
if (!parse_word(lex, &msg_name)) {
|
||||||
report_error("expected message identifier\n");
|
report_error("expected function identifier\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = msg_definition_create(msg_name);
|
long long msg_id = 0;
|
||||||
|
if (!parse_symbol(lex, SYM_LEFT_BRACKET)) {
|
||||||
|
report_error("expected `[` after function identifier\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_int(lex, &msg_id)) {
|
||||||
|
report_error("expected function id number after `[`\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_symbol(lex, SYM_RIGHT_BRACKET)) {
|
||||||
|
report_error("expected `]` after function id number\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = msg_definition_create(msg_name, msg_id);
|
||||||
free(msg_name);
|
free(msg_name);
|
||||||
|
|
||||||
if (!parse_symbol(lex, SYM_LEFT_PAREN)) {
|
if (!parse_symbol(lex, SYM_LEFT_PAREN)) {
|
||||||
report_error("expected `(` after message identifier\n");
|
report_error(
|
||||||
|
"expected `(` after function id number specifier\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,14 +108,31 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
|
if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
|
||||||
report_error("expected `,` after message parameter\n");
|
report_error(
|
||||||
|
"expected `,` after function "
|
||||||
|
"parameter\n");
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *param_name;
|
||||||
|
if (!parse_word(lex, ¶m_name)) {
|
||||||
|
report_error("expected function parameter name\n");
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_symbol(lex, SYM_COLON)) {
|
||||||
|
report_error(
|
||||||
|
"expected `:` after function parameter "
|
||||||
|
"name\n");
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *type_name;
|
char *type_name;
|
||||||
if (!parse_word(lex, &type_name)) {
|
if (!parse_word(lex, &type_name)) {
|
||||||
report_error("expected message parameter type\n");
|
report_error("expected function parameter type\n");
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -94,7 +140,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
const struct type *type = ctx_get_type(ctx, type_name);
|
const struct type *type = ctx_get_type(ctx, type_name);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
report_error(
|
report_error(
|
||||||
"message parameter has unknown type "
|
"function parameter has unknown type "
|
||||||
"'%s'\n",
|
"'%s'\n",
|
||||||
type_name);
|
type_name);
|
||||||
free(type_name);
|
free(type_name);
|
||||||
@@ -104,19 +150,13 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
|
|
||||||
free(type_name);
|
free(type_name);
|
||||||
|
|
||||||
char *param_name;
|
|
||||||
if (!parse_word(lex, ¶m_name)) {
|
|
||||||
report_error("expected message parameter name\n");
|
|
||||||
ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool duplicate = msg_definition_has_param(msg, param_name)
|
bool duplicate = msg_definition_has_param(msg, param_name)
|
||||||
|| msg_definition_has_result(msg, param_name);
|
|| msg_definition_has_result(msg, param_name);
|
||||||
if (duplicate) {
|
if (duplicate) {
|
||||||
free(param_name);
|
free(param_name);
|
||||||
report_error(
|
report_error(
|
||||||
"message has multiple parameters/results with "
|
"function has multiple "
|
||||||
|
"parameters/results with "
|
||||||
"name '%s'\n",
|
"name '%s'\n",
|
||||||
param_name);
|
param_name);
|
||||||
ok = false;
|
ok = false;
|
||||||
@@ -133,12 +173,14 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!parse_symbol(lex, SYM_HYPHEN_RIGHT_ANGLE)) {
|
if (!parse_symbol(lex, SYM_HYPHEN_RIGHT_ANGLE)) {
|
||||||
report_error("expected `->` after message parameter list\n");
|
report_error(
|
||||||
|
"expected `->` after function parameter "
|
||||||
|
"list\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parse_symbol(lex, SYM_LEFT_PAREN)) {
|
if (!parse_symbol(lex, SYM_LEFT_PAREN)) {
|
||||||
report_error("expected `(` for message results list\n");
|
report_error("expected `(` for function results list\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,14 +192,30 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
|
|
||||||
if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
|
if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
|
||||||
report_error(
|
report_error(
|
||||||
"expected `,` or `)` after message result\n");
|
"expected `,` or `)` after function "
|
||||||
|
"result\n");
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *result_name;
|
||||||
|
if (!parse_word(lex, &result_name)) {
|
||||||
|
report_error("expected function parameter name\n");
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_symbol(lex, SYM_COLON)) {
|
||||||
|
report_error(
|
||||||
|
"expected `:` after function result "
|
||||||
|
"name\n");
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *type_name;
|
char *type_name;
|
||||||
if (!parse_word(lex, &type_name)) {
|
if (!parse_word(lex, &type_name)) {
|
||||||
report_error("expected message result type\n");
|
report_error("expected function result type\n");
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -165,7 +223,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
const struct type *type = ctx_get_type(ctx, type_name);
|
const struct type *type = ctx_get_type(ctx, type_name);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
report_error(
|
report_error(
|
||||||
"message result has unknown type "
|
"function result has unknown type "
|
||||||
"'%s'\n",
|
"'%s'\n",
|
||||||
type_name);
|
type_name);
|
||||||
free(type_name);
|
free(type_name);
|
||||||
@@ -174,18 +232,12 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
}
|
}
|
||||||
free(type_name);
|
free(type_name);
|
||||||
|
|
||||||
char *result_name;
|
|
||||||
if (!parse_word(lex, &result_name)) {
|
|
||||||
report_error("expected message parameter name\n");
|
|
||||||
ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool duplicate = msg_definition_has_param(msg, result_name)
|
bool duplicate = msg_definition_has_param(msg, result_name)
|
||||||
|| msg_definition_has_result(msg, result_name);
|
|| msg_definition_has_result(msg, result_name);
|
||||||
if (duplicate) {
|
if (duplicate) {
|
||||||
report_error(
|
report_error(
|
||||||
"message has multiple parameters/results with "
|
"function has multiple "
|
||||||
|
"parameters/results with "
|
||||||
"name '%s'\n",
|
"name '%s'\n",
|
||||||
result_name);
|
result_name);
|
||||||
free(result_name);
|
free(result_name);
|
||||||
@@ -199,7 +251,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!parse_symbol(lex, SYM_SEMICOLON)) {
|
if (!parse_symbol(lex, SYM_SEMICOLON)) {
|
||||||
report_error("expected `;` after message definition\n");
|
report_error("expected `;` after function definition\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,29 +278,35 @@ struct interface_definition *parse_interface_definition(
|
|||||||
|
|
||||||
char *if_name = NULL;
|
char *if_name = NULL;
|
||||||
if (!parse_word(lex, &if_name)) {
|
if (!parse_word(lex, &if_name)) {
|
||||||
report_error("expected interface identifier");
|
report_error("expected interface name");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
iface = interface_definition_create(if_name);
|
long long if_id = 0;
|
||||||
|
if (!parse_int(lex, &if_id)) {
|
||||||
|
report_error("expected interface id number");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_symbol(lex, SYM_SEMICOLON)) {
|
||||||
|
report_error("expected `;` after interface definition");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = interface_definition_create(if_name, if_id);
|
||||||
free(if_name);
|
free(if_name);
|
||||||
if (!iface) {
|
if (!iface) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parse_symbol(lex, SYM_LEFT_BRACE)) {
|
|
||||||
report_error("expected `{` after interface identifier");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
while (ok) {
|
while (ok) {
|
||||||
if (parse_symbol(lex, SYM_RIGHT_BRACE)) {
|
if (!lex_peek(lex) && lex_get_status(lex) == ERR_EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peek_keyword(lex, KW_MSG)) {
|
if (peek_keyword(lex, KW_FUNC)) {
|
||||||
struct msg_definition *msg
|
struct msg_definition *msg
|
||||||
= parse_msg_definition(ctx, lex);
|
= parse_msg_definition(ctx, lex);
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
@@ -268,7 +326,7 @@ struct interface_definition *parse_interface_definition(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_error("expected `}` or message definition\n");
|
report_error("expected eof or function definition\n");
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_PARSE_H_
|
#ifndef XPCG_PARSE_H_
|
||||||
#define IFC_PARSE_H_
|
#define XPCG_PARSE_H_
|
||||||
|
|
||||||
struct ctx;
|
struct ctx;
|
||||||
struct lex;
|
struct lex;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_STATUS_H_
|
#ifndef XPCG_STATUS_H_
|
||||||
#define IFC_STATUS_H_
|
#define XPCG_STATUS_H_
|
||||||
|
|
||||||
enum status {
|
enum status {
|
||||||
SUCCESS = 0,
|
SUCCESS = 0,
|
||||||
@@ -40,6 +40,7 @@ const char *token_symbol_to_string(enum token_symbol sym)
|
|||||||
ENUM_STR(SYM_NONE);
|
ENUM_STR(SYM_NONE);
|
||||||
ENUM_STR(SYM_COMMA);
|
ENUM_STR(SYM_COMMA);
|
||||||
ENUM_STR(SYM_SEMICOLON);
|
ENUM_STR(SYM_SEMICOLON);
|
||||||
|
ENUM_STR(SYM_COLON);
|
||||||
ENUM_STR(SYM_HYPHEN);
|
ENUM_STR(SYM_HYPHEN);
|
||||||
ENUM_STR(SYM_LEFT_BRACE);
|
ENUM_STR(SYM_LEFT_BRACE);
|
||||||
ENUM_STR(SYM_RIGHT_BRACE);
|
ENUM_STR(SYM_RIGHT_BRACE);
|
||||||
@@ -56,7 +57,7 @@ const char *token_keyword_to_string(enum token_keyword kw)
|
|||||||
switch (kw) {
|
switch (kw) {
|
||||||
ENUM_STR(KW_NONE);
|
ENUM_STR(KW_NONE);
|
||||||
ENUM_STR(KW_INTERFACE);
|
ENUM_STR(KW_INTERFACE);
|
||||||
ENUM_STR(KW_MSG);
|
ENUM_STR(KW_FUNC);
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IFC_TOKEN_H_
|
#ifndef XPCG_TOKEN_H_
|
||||||
#define IFC_TOKEN_H_
|
#define XPCG_TOKEN_H_
|
||||||
|
|
||||||
#include "file-span.h"
|
#include "file-span.h"
|
||||||
|
|
||||||
@@ -34,6 +34,9 @@ enum token_symbol {
|
|||||||
SYM_COMMA = __TOK_UBOUND,
|
SYM_COMMA = __TOK_UBOUND,
|
||||||
SYM_HYPHEN,
|
SYM_HYPHEN,
|
||||||
SYM_SEMICOLON,
|
SYM_SEMICOLON,
|
||||||
|
SYM_COLON,
|
||||||
|
SYM_LEFT_BRACKET,
|
||||||
|
SYM_RIGHT_BRACKET,
|
||||||
SYM_LEFT_BRACE,
|
SYM_LEFT_BRACE,
|
||||||
SYM_RIGHT_BRACE,
|
SYM_RIGHT_BRACE,
|
||||||
SYM_LEFT_PAREN,
|
SYM_LEFT_PAREN,
|
||||||
@@ -45,7 +48,7 @@ enum token_symbol {
|
|||||||
enum token_keyword {
|
enum token_keyword {
|
||||||
KW_NONE = 0,
|
KW_NONE = 0,
|
||||||
KW_INTERFACE = __SYM_UBOUND,
|
KW_INTERFACE = __SYM_UBOUND,
|
||||||
KW_MSG,
|
KW_FUNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct token {
|
struct token {
|
||||||
@@ -11,6 +11,12 @@ void type_print(const struct type *ty)
|
|||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
printf("string");
|
printf("string");
|
||||||
break;
|
break;
|
||||||
|
case TYPE_SIZE:
|
||||||
|
printf("size");
|
||||||
|
break;
|
||||||
|
case TYPE_BUFFER:
|
||||||
|
printf("buffer");
|
||||||
|
break;
|
||||||
case TYPE_HANDLE:
|
case TYPE_HANDLE:
|
||||||
printf("handle");
|
printf("handle");
|
||||||
break;
|
break;
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
#ifndef IFC_TYPE_H_
|
#ifndef XPCG_TYPE_H_
|
||||||
#define IFC_TYPE_H_
|
#define XPCG_TYPE_H_
|
||||||
|
|
||||||
enum type_id {
|
enum type_id {
|
||||||
TYPE_NONE,
|
TYPE_NONE,
|
||||||
TYPE_INT,
|
TYPE_INT,
|
||||||
|
TYPE_SIZE,
|
||||||
TYPE_STRING,
|
TYPE_STRING,
|
||||||
|
TYPE_BUFFER,
|
||||||
TYPE_HANDLE,
|
TYPE_HANDLE,
|
||||||
TYPE_OTHER,
|
TYPE_OTHER,
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user