Compare commits

...

79 Commits

Author SHA1 Message Date
wash 1674c8dbb2 ld: use shared mappings for read-only elf segments 2026-04-21 21:17:37 +01:00
wash 538904b7e4 liblaunch: implement private/shared mapping support 2026-04-21 21:17:08 +01:00
wash 58e99b046d libfs: implement private/shared mapping support 2026-04-21 21:16:50 +01:00
wash 55f755e7d9 libfs: remove unused include 2026-04-21 21:16:17 +01:00
wash 1c6ece7b55 libc: implement private/shared mapping support 2026-04-21 21:15:27 +01:00
wash 70e990a885 meta: update kernel 2026-04-21 21:13:04 +01:00
wash 4fbc6b9027 meta: add clang-format config 2026-04-20 22:21:37 +01:00
wash 4beab43728 meta: update kernel 2026-04-20 22:21:14 +01:00
wash f290ebcd84 cmake: change minimum version number to 3.31 2026-04-20 22:19:56 +01:00
wash 7aea4e0206 base: grub: auto-boot with serial logging enabled 2026-04-20 22:19:28 +01:00
wash a15ebef9c7 toolchain: build fx as a static library 2026-04-20 22:19:05 +01:00
wash 89c8f96829 x86_64: update successful-boot test 2026-04-20 22:18:47 +01:00
wash 809f19ebe7 herdd: only add service to list if loaded successfully 2026-04-20 22:18:03 +01:00
wash 6c80d375f2 herdd: task_duplicate test 2026-04-20 22:17:28 +01:00
wash 109ee7b79c ld: formatting tweaks 2026-04-20 22:15:05 +01:00
wash b5b95c661e ld: add function to dump loaded image list 2026-04-20 22:14:56 +01:00
wash 5dcc190f02 ld: temporarily change image mappings to MAP_PRIVATE for COW testing 2026-04-20 22:14:39 +01:00
wash 19683dbaa8 ld: zero-init data segment before reading contents from executable 2026-04-20 22:14:11 +01:00
wash f5c3d885ec bootstrap: update reference to static liblaunch 2026-04-20 22:12:12 +01:00
wash c64abb9bbc meta: update libfx 2026-04-20 22:11:35 +01:00
wash a11188b6bf liblaunch: build a shared version of the library 2026-04-20 22:11:21 +01:00
wash 5b996585d4 libfs: implement handling of lazy-attach cow-duplicate file mapping vmo 2026-04-19 20:56:09 +01:00
wash 466af317b2 libfs: add library to bsp 2026-04-19 20:55:17 +01:00
wash 0d97fe2340 libc: io: file ringbuffer is now cleared on init 2026-04-19 20:53:44 +01:00
wash 902537ad52 libc: io: vprintf now checks for stream error before returning 2026-04-19 20:53:21 +01:00
wash 07d5b4852c libc: io: fputc now updates errno on success 2026-04-19 20:52:29 +01:00
wash b07acb3cdf libc: core: add return-value to printf output callbacks 2026-04-19 20:51:23 +01:00
wash 0e3f010713 libc: core: initialise errno to SUCCESS 2026-04-19 20:48:59 +01:00
wash 92aaa5439b x86_64: update bochs config file 2026-04-19 20:46:50 +01:00
wash 648a7e2dfb x86_64: cmake: update cdrom generation to look for grub2-mkrescue 2026-04-19 20:46:32 +01:00
wash 4b6099584b x86_64: cmake: fix debug-kernel-monitor only being available if cdrom generation is enabled 2026-04-19 20:46:03 +01:00
wash 30dd0e753d meta: update kernel 2026-04-01 19:13:42 +01:00
wash fdd83287fc services: add device management service 2026-04-01 19:13:32 +01:00
wash 5a0e7bf14f services: nsd: convert config file to TOML 2026-04-01 19:13:18 +01:00
wash 15ebe38b69 services: herdd: implement scanning and parsing of runlevel and service config files 2026-04-01 19:12:55 +01:00
wash 0ef481c30f x86_64: cmake: add support for running qemu with debugging and stdio monitor output 2026-04-01 19:12:15 +01:00
wash b82e8012d6 cmake: link all targets to libgcc 2026-04-01 19:11:24 +01:00
wash cc026e0f61 cmake: add __rosetta__ compile definition 2026-04-01 19:11:00 +01:00
wash 6a928ec0ab toolchain: xpcg: update kernel constants 2026-04-01 19:10:24 +01:00
wash 3be9c022e0 ld: change return type of dl_runtime_resolve 2026-04-01 19:07:51 +01:00
wash d2e0fa79fa ld: implement GLOB_DAT and 64 relocation types 2026-04-01 19:07:31 +01:00
wash 70d32cd592 bootstrap: create stdio file descriptors for use by other tasks 2026-04-01 19:06:55 +01:00
wash 2f01138416 runlevel: convert config files to TOML 2026-04-01 19:05:59 +01:00
wash f70d64759f libfx: configure build and add libraries to sysroot and bsp 2026-04-01 19:05:32 +01:00
wash 8ebf44dca9 libfs: add support for special files not backed by a filesystem 2026-04-01 18:57:59 +01:00
wash f2e6e7785d libfs: replace kern_handle_duplicate with kern_handle_transfer 2026-04-01 18:56:30 +01:00
wash f6993553cd libfs: separating closing a file descriptor from releasing a reference to the file itself 2026-04-01 18:55:47 +01:00
wash 3a9539adbc liblaunch: implement stdio handle initialisation for child task 2026-04-01 18:53:28 +01:00
wash 28d986c628 liblaunch: ensure stack pointers remain aligned 2026-04-01 18:53:04 +01:00
wash 3bd5899ece libc: change libmango to a public dependency 2026-04-01 18:51:52 +01:00
wash 548387c43a libc: io: implement file io buffering and internal locking for concurrency 2026-04-01 18:51:13 +01:00
wash f2e650d368 libc: add a range of header files 2026-04-01 18:49:57 +01:00
wash c6ca934852 libc: pthread: add pthread_mutex_t definition 2026-04-01 18:49:27 +01:00
wash 0a231d2179 libc: pthread: fix pthread_unmap_exit calling the wrong syscall 2026-04-01 18:49:13 +01:00
wash 40682810ab libc: core: implement assert, ctype, wctype, and stdlib functions 2026-04-01 18:48:35 +01:00
wash 36a486cca6 libc: core: implement memcmp and memmove 2026-04-01 18:47:59 +01:00
wash 0d16c300e7 libc: core: implement sscanf and friends 2026-04-01 18:47:36 +01:00
wash 4057e77512 libc: remove log message from __libc_init 2026-04-01 18:45:45 +01:00
wash d53bbbb460 libc: rename fctprintf to __libc_fctprintf 2026-04-01 18:45:19 +01:00
wash 6787f28728 lib: c: core: implement strchr and strcspn 2026-03-25 20:21:28 +00:00
wash 96784f611f lib: c: io: implement standard FILE and DIR interfaces 2026-03-25 20:21:12 +00:00
wash b975256cb9 meta: update kernel 2026-03-24 20:26:19 +00:00
wash 8d22ec661c bootstrap: remove old request handler code 2026-03-24 20:26:12 +00:00
wash a91dc5965e services: herdd: getdents test 2026-03-24 20:25:49 +00:00
wash 329829c0e9 lib: fs: implement file cleanup using disconnect and detach events 2026-03-24 20:25:13 +00:00
wash dade9fa81f lib: xpc: add support for event messages 2026-03-24 20:24:36 +00:00
wash e9ccefd980 toolchain: xpcg: fix buffer length output not being set 2026-03-24 12:45:13 +00:00
wash 20723d4dff bootstrap: tar: implement readdir() 2026-03-24 12:44:33 +00:00
wash d2df4259e6 interface: fs: add fs.getdents function 2026-03-24 12:43:33 +00:00
wash e30368553f lib: c: io: implement getdents() 2026-03-24 12:42:39 +00:00
wash 660cb3bd71 lib: c: io: update fs_read usage 2026-03-24 12:42:08 +00:00
wash d3a25f0af7 lib: c: remove errno log messages 2026-03-24 12:41:41 +00:00
wash 30614e679b lib: xpc: implement support for iterating through directories 2026-03-24 12:41:12 +00:00
wash 1eb6853cb0 lib: xpc: implement scatter/gather i/o for buffers and messages 2026-03-24 12:40:16 +00:00
wash af3dd454b0 bootstrap: start herdd instead of systemd 2026-03-23 18:16:15 +00:00
wash 2a587942ac meta: add herdd runlevel configuration files 2026-03-23 18:15:55 +00:00
wash bf5052fd3d meta: replace systemd and ldd with herdd and nsd 2026-03-23 18:15:38 +00:00
wash d4d3ab13f4 prog: remove test program 2026-03-23 18:14:57 +00:00
wash 98dbaa05ac cmake: add support for building services with config files 2026-03-23 18:13:22 +00:00
150 changed files with 7051 additions and 357 deletions
+176
View File
@@ -0,0 +1,176 @@
BasedOnStyle: WebKit
IndentWidth: 8
---
Language: C
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: Right
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: OnePerLine
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
IncludeBlocks: Regroup
SortIncludes: true
IndentRequires: true
NamespaceIndentation: Inner
ReflowComments: true
SpacesBeforeTrailingComments: 3
TabWidth: 8
UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyExcessCharacter: 999999999
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- FX_API
ForEachMacros:
- fx_btree_foreach
- fx_queue_foreach
MacroBlockBegin: "FX_TYPE_.*_BEGIN"
MacroBlockEnd: "FX_TYPE_.*_END"
---
Language: ObjC
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: Right
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: true
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
IncludeBlocks: Regroup
SortIncludes: true
IndentRequires: true
NamespaceIndentation: Inner
ReflowComments: true
SpacesBeforeTrailingComments: 3
TabWidth: 8
UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyExcessCharacter: 5
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- FX_API
ForEachMacros:
- fx_btree_foreach
- fx_queue_foreach
MacroBlockBegin: "FX_TYPE_.*_BEGIN"
MacroBlockEnd: "FX_TYPE_.*_END"
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: Right
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: OnePerLine
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
IncludeBlocks: Regroup
SortIncludes: true
IndentRequires: true
NamespaceIndentation: Inner
ReflowComments: true
SpacesBeforeTrailingComments: 3
TabWidth: 8
UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyExcessCharacter: 9999999
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- FX_API
ForEachMacros:
- fx_btree_foreach
- fx_queue_foreach
MacroBlockBegin: "FX_TYPE_.*_BEGIN"
MacroBlockEnd: "FX_TYPE_.*_END"
+3
View File
@@ -4,3 +4,6 @@
[submodule "sys/ropkg"]
path = sys/ropkg
url = git@github.com:washh/ropkg.git
[submodule "lib/libfx"]
path = lib/libfx
url = https://g.wash.red/wash/fx.git
+2 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 4.0)
cmake_minimum_required(VERSION 3.31)
project(Rosetta C CXX ASM)
include(CheckPIESupported)
@@ -28,6 +28,7 @@ add_subdirectory(interface)
add_subdirectory(sys)
add_subdirectory(lib)
add_subdirectory(services)
add_subdirectory(runlevel)
add_subdirectory(programs)
sysroot_add_program(NAME ${kernel_name} BIN_DIR /boot)
+3 -1
View File
@@ -7,7 +7,7 @@ find_program(C_COMPILER x86_64-elf-gcc REQUIRED)
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
#find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
add_compile_definitions(__mango__=1)
add_compile_definitions(__mango__=1 __rosetta__=1)
set(CMAKE_C_COMPILER ${C_COMPILER})
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})
@@ -25,3 +25,5 @@ set(CMAKE_C_OUTPUT_EXTENSION .o)
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
link_libraries(-lgcc)
+11
View File
@@ -122,3 +122,14 @@ elseif (GDB)
DEPENDS ${image_cdrom})
endif ()
endif ()
add_custom_target(debug-kernel-monitor
COMMAND
${QEMU}
-kernel ${patched_kernel}
-initrd ${sys_dir}/${bsp_name}
${generic_flags}
-monitor stdio -s -S
USES_TERMINAL
DEPENDS ${patched_kernel} bsp)
+1 -1
View File
@@ -1,4 +1,4 @@
find_program(GRUB_MKRESCUE grub-mkrescue)
find_program(GRUB_MKRESCUE NAMES grub-mkrescue grub2-mkrescue)
if (GRUB_MKRESCUE)
message(STATUS "GRUB: Found grub-mkrescue. Bootable CD-ROM image creation is enabled")
+3 -5
View File
@@ -1,10 +1,8 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true
plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true
config_interface: textconfig
display_library: sdl2
memory: guest=128, host=128, block_size=128
romimage: file="/usr/local/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none, flash_data=none
vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest.bin"
boot: cdrom
floppy_bootsig_check: disabled=0
floppya: type=1_44
@@ -31,7 +29,7 @@ cpu: count=1:1:1, ips=4000000, quantum=16, model=core2_penryn_t9600, reset_on_tr
print_timestamps: enabled=0
debugger_log: -
magic_break: enabled=1 0x0
port_e9_hack: enabled=false, all_rings=false
port_e9_hack: enabled=true, all_rings=false
iodebug: all_rings=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
@@ -47,7 +45,7 @@ mouse: type=ps2, enabled=false, toggle=ctrl+mbutton
speaker: enabled=true, mode=system
parport1: enabled=true, file=none
parport2: enabled=false
com1: enabled=true, mode=null
com1: enabled=true, mode=file, dev=kernel.log
com2: enabled=false
com3: enabled=false
com4: enabled=false
+2 -5
View File
@@ -24,13 +24,10 @@ def successful_boot(boot_log, out):
log(out, "Kernel rebooted during test!")
return 1
nr_finish = boot_log.count("ld finished")
if nr_finish == 0:
nr_finish = boot_log.count("exiting (Inappropriate file type or format)")
if nr_finish != 2:
log(out, "Didn't reach end of boot sequence!")
return 1
if nr_finish > 1:
log(out, "Boot sequence performed multiple times!")
return 1
return 0
+3 -11
View File
@@ -34,15 +34,10 @@ initrd=$5
while true; do
log "Test $count"
result_file="$log_dir/$count.log"
$qemu \
-kernel $kernel \
-initrd $initrd \
-serial file:$result_file \
-cpu qemu64,+rdrand \
--append kernel.early-console=ttyS0 -s > /dev/null &
ninja run-cdrom-bochs > $result_file &
qemu_id=$!
sleep 1.2
sleep 5
$python $validation_script successful-boot $result_file $logfile
result=$?
@@ -54,12 +49,9 @@ while true; do
else
mv $result_file "$result_file.FAIL"
fail=$fail+1
lldb \
-o "file kernel/mango_kernel.debug" \
-o "gdb-remote localhost:1234"
fi
kill -INT $qemu_id
killall -9 bochs
log "---------------"
log "Total tests: $count"
+2 -5
View File
@@ -1,8 +1,5 @@
menuentry "Rosetta" {
multiboot /boot/mango_kernel
module /boot/rosetta-system.bsp
boot
}
set timeout_style=menu
set timeout=0
menuentry "Rosetta (Serial Log)" {
multiboot /boot/mango_kernel kernel.early-console=ttyS0
+64
View File
@@ -9,6 +9,36 @@ function(bsp_reset)
COMMAND_ERROR_IS_FATAL ANY)
endfunction(bsp_reset)
function(bsp_add_file)
set(options)
set(one_value_args ID SRC_PATH DEST_DIR)
set(multi_value_args)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(target_name ${arg_ID})
set(bsp_target_name _bsp-${target_name})
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
list(LENGTH bsp_targets nr_bsp_targets)
if (${nr_bsp_targets} GREATER 0)
math(EXPR serialiser_index "${nr_bsp_targets}-1")
list(GET bsp_targets ${serialiser_index} serialiser)
endif ()
add_custom_target(${bsp_target_name}
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}
${arg_DEST_DIR} ${arg_SRC_PATH}
COMMENT "Preparing bsp component: ${target_name}"
DEPENDS ${arg_SRC_PATH} ${serialiser})
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
endfunction(bsp_add_file)
function(bsp_add_library)
set(options)
set(one_value_args NAME HEADER_DIR LIB_DIR)
@@ -70,6 +100,40 @@ function(bsp_add_program)
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
endfunction(bsp_add_program)
function(bsp_add_service)
set(options)
set(one_value_args NAME BIN_DIR SVC_DIR)
set(multi_value_args)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(target_name ${arg_NAME})
set(bsp_target_name _bsp-${target_name})
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
get_property(cfg_file TARGET ${arg_NAME} PROPERTY service_cfg_path)
list(LENGTH bsp_targets nr_bsp_targets)
if (${nr_bsp_targets} GREATER 0)
math(EXPR serialiser_index "${nr_bsp_targets}-1")
list(GET bsp_targets ${serialiser_index} serialiser)
endif ()
add_custom_target(${bsp_target_name}
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}-cfg
${arg_SVC_DIR} ${cfg_file}
COMMENT "Preparing bsp component: ${target_name}"
DEPENDS ${target_name} ${serialiser})
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
endfunction(bsp_add_service)
function(bsp_finalise)
set(options)
set(one_value_args BOOTSTRAP_PROGRAM DEST_DIR BSP_NAME)
+34
View File
@@ -155,6 +155,40 @@ function(sysroot_add_program)
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
endfunction(sysroot_add_program)
function(sysroot_add_service)
set(options)
set(one_value_args NAME BIN_DIR SVC_DIR)
set(multi_value_args)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(target_name ${arg_NAME})
set(sysroot_target_name _sysroot-${target_name})
get_property(sysroot_targets GLOBAL PROPERTY sysroot_target_list)
get_property(cfg_file TARGET ${arg_NAME} PROPERTY service_cfg_path)
list(LENGTH sysroot_targets nr_sysroot_targets)
if (${nr_sysroot_targets} GREATER 0)
math(EXPR serialiser_index "${nr_sysroot_targets}-1")
list(GET sysroot_targets ${serialiser_index} serialiser)
endif ()
add_custom_target(${sysroot_target_name}
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
add-binary ${sysroot_manifest} ${target_name}
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
add-binary ${sysroot_manifest} ${target_name}-cfg
${arg_SVC_DIR} ${cfg_file}
COMMENT "Preparing sysroot component: ${target_name}"
DEPENDS ${target_name} ${serialiser})
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
endfunction(sysroot_add_service)
function(sysroot_add_file)
set(options)
set(one_value_args ID SRC_PATH DEST_DIR)
+23
View File
@@ -32,6 +32,29 @@ function(rosetta_add_executable)
DESTINATION ${arg_SYSROOT_PATH})
endfunction(rosetta_add_executable)
function(rosetta_add_service)
set(options)
set(one_value_args NAME CFG_FILE)
set(multi_value_args SOURCES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(exec_name ${arg_NAME})
get_property(programs GLOBAL PROPERTY rosetta_program_list)
set_property(GLOBAL PROPERTY rosetta_program_list ${programs} ${exec_name})
message(STATUS "Building service ${exec_name}")
add_executable(${exec_name} ${arg_SOURCES})
set_target_properties(${exec_name} PROPERTIES
POSITION_INDEPENDENT_CODE ON
service_cfg_path ${arg_CFG_FILE})
install(TARGETS ${exec_name}
DESTINATION ${arg_SYSROOT_PATH})
endfunction(rosetta_add_service)
function(rosetta_add_library)
set(options STATIC SHARED)
set(one_value_args NAME)
+3 -1
View File
@@ -3,9 +3,11 @@ 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 read[2](count: size) -> (err: int, data: buffer);
func write[3](data: buffer) -> (err: int, nr_written: size);
func seek[4](offset: offset, origin: int) -> (err: int, new_pos: offset);
func map[5](prot: int, flags: int) -> (err: int, vmo: handle);
func getdents[6]() -> (err: int, dents: buffer);
+1 -1
Submodule kernel updated: 110f625f04...278fe39c0d
+23
View File
@@ -1,5 +1,9 @@
file(GLOB items *)
set(fx_modules core ds serial)
set(fx_enable_floating_point 0)
set(fx_enable_tests 0)
add_subdirectory(
${CMAKE_SOURCE_DIR}/kernel/libmango
${CMAKE_CURRENT_BINARY_DIR}/libmango)
@@ -24,3 +28,22 @@ foreach(item ${items})
add_subdirectory(${item})
endforeach (item)
foreach (module ${fx_modules})
target_link_libraries(fx-${module} libc libpthread)
target_link_libraries(fx-${module}-s libc-core libc-pthread libmango)
target_link_options(fx-${module} PRIVATE -Wl,--soname,libfx-${module}.so)
rosetta_wrap_library(
NAME fx-${module}
PUBLIC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/libfx/${module}/include)
set_target_properties(fx-${module} fx-${module}-s PROPERTIES
PREFIX "lib")
sysroot_add_library(
NAME fx-${module}
HEADER_DIR /usr/include
LIB_DIR /usr/lib)
bsp_add_library(
NAME fx-${module}
LIB_DIR /usr/lib)
endforeach (module)
+2 -1
View File
@@ -26,7 +26,8 @@ bsp_add_library(
NAME libc
LIB_DIR /usr/lib)
target_link_libraries(libc PRIVATE libmango librosetta libxpc-static interface::fs)
target_link_libraries(libc PRIVATE librosetta libxpc-static interface::fs)
target_link_libraries(libc PUBLIC libmango)
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
add_subdirectory(pthread)
+1 -1
View File
@@ -1,4 +1,4 @@
set(source_dirs stdio string errno)
set(source_dirs assert stdio stdlib string errno ctype wctype)
foreach (dir ${source_dirs})
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
+10
View File
@@ -0,0 +1,10 @@
#include <stdlib.h>
extern void __libc_assert_failed(
const char *file,
int line,
const char *func,
const char *cond)
{
abort();
}
+16
View File
@@ -0,0 +1,16 @@
int isalnum(int c)
{
if (c >= 'a' && c <= 'z') {
return 1;
}
if (c >= 'A' && c <= 'A') {
return 1;
}
if (c >= '0' && c <= '9') {
return 1;
}
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
int isalpha(int c)
{
if (c >= 'a' && c <= 'z') {
return 1;
}
if (c >= 'A' && c <= 'A') {
return 1;
}
return 0;
}
+10
View File
@@ -0,0 +1,10 @@
#include <ctype.h>
int isdigit(int c)
{
if (c >= '0' && c <= '9') {
return 1;
}
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
#include <ctype.h>
int ispunct(int c)
{
if (c >= 0x21 && c <= 0x2E) {
return 1;
}
if (c >= 0x3A && c <= 0x40) {
return 1;
}
if (c >= 0x5B && c <= 0x60) {
return 1;
}
if (c >= 0x7B && c <= 0x7E) {
return 1;
}
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
#include <ctype.h>
int isspace(int c)
{
switch (c) {
case ' ':
case '\n':
case '\t':
return 1;
default:
return 0;
}
}
+8
View File
@@ -0,0 +1,8 @@
int isupper(int c)
{
if (c >= 'A' && c <= 'Z') {
return 1;
}
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
#include <ctype.h>
int isxdigit(int c)
{
if (c >= 'a' && c <= 'f') {
return 1;
}
if (c >= 'A' && c <= 'F') {
return 1;
}
if (c >= '0' && c <= '9') {
return 1;
}
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
int tolower(int c)
{
if (c >= 'A' && c <= 'Z') {
return (c - 'A') + 'a';
}
return c;
}
+8
View File
@@ -0,0 +1,8 @@
int toupper(int c)
{
if (c >= 'a' && c <= 'z') {
return (c - 'a') + 'A';
}
return c;
}
+1 -3
View File
@@ -1,12 +1,10 @@
#include <errno.h>
#include <mango/log.h>
#include <mango/status.h>
static int __errno = 32;
static int __errno = SUCCESS;
int __attribute__((weak)) * __errno_location(void)
{
kern_log("using builtin errno");
return &__errno;
}
+12 -11
View File
@@ -118,7 +118,7 @@
#endif
// output function type
typedef void (
typedef int (
*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);
// wrapper (used as buffer) for output function type
@@ -128,7 +128,7 @@ typedef struct {
} out_fct_wrap_type;
// internal buffer output
static inline void _out_buffer(
static inline int _out_buffer(
char character,
void *buffer,
size_t idx,
@@ -137,10 +137,12 @@ static inline void _out_buffer(
if (idx < maxlen) {
((char *)buffer)[idx] = character;
}
return 0;
}
// internal null output
static inline void _out_null(
static inline int _out_null(
char character,
void *buffer,
size_t idx,
@@ -150,10 +152,11 @@ static inline void _out_null(
(void)buffer;
(void)idx;
(void)maxlen;
return 0;
}
// internal output function wrapper
static inline void _out_fct(
static inline int _out_fct(
char character,
void *buffer,
size_t idx,
@@ -166,6 +169,8 @@ static inline void _out_fct(
((out_fct_wrap_type *)buffer)
->fct(character, ((out_fct_wrap_type *)buffer)->arg);
}
return 0;
}
// internal secure strlen
@@ -1195,21 +1200,17 @@ int vsnprintf(char *buffer, size_t count, const char *format, va_list va)
return _vsnprintf(_out_buffer, buffer, count, format, va);
}
int fctprintf(
int __libc_fctprintf(
void (*out)(char character, void *arg),
void *arg,
const char *format,
...)
va_list va)
{
va_list va;
va_start(va, format);
const out_fct_wrap_type out_fct_wrap = {out, arg};
const int ret = _vsnprintf(
return _vsnprintf(
_out_fct,
(char *)(uintptr_t)&out_fct_wrap,
(size_t)-1,
format,
va);
va_end(va);
return ret;
}
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
#include <mango/task.h>
void abort(void)
{
task_exit(-1);
}
+6
View File
@@ -0,0 +1,6 @@
int atexit(void (*func)(void))
{
/* TODO */
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
#include <mango/task.h>
void exit(int code)
{
task_exit(code);
}
+99
View File
@@ -0,0 +1,99 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
long strtol(const char *restrict ptr, char **restrict endptr, register int base)
{
const char *s = ptr;
long acc;
int c;
long cutoff;
int neg = 0, any, cutlim;
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+') {
c = *s++;
}
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0) {
base = c == '0' ? 8 : 10;
}
cutoff = (long)LONG_MAX / (long)base;
cutlim = (long)LONG_MAX % (long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
} else {
break;
}
if (c >= base) {
break;
}
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
} else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = LONG_MAX;
__set_errno(ERANGE);
} else if (neg) {
acc = -acc;
}
if (endptr != 0) {
*endptr = (char *)(any ? s - 1 : ptr);
}
return (acc);
}
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
long long strtoll(
const char *restrict ptr,
char **restrict endptr,
register int base)
{
const char *s = ptr;
long long acc;
int c;
long long cutoff;
int neg = 0, any, cutlim;
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+') {
c = *s++;
}
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0) {
base = c == '0' ? 8 : 10;
}
cutoff = (long long)LLONG_MAX / (long long)base;
cutlim = (long long)LLONG_MAX % (long long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
} else {
break;
}
if (c >= base) {
break;
}
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
} else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = LONG_MAX;
__set_errno(ERANGE);
} else if (neg) {
acc = -acc;
}
if (endptr != 0) {
*endptr = (char *)(any ? s - 1 : ptr);
}
return (acc);
}
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
unsigned long strtoul(
const char *restrict ptr,
char **restrict endptr,
register int base)
{
const char *s = ptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+') {
c = *s++;
}
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0) {
base = c == '0' ? 8 : 10;
}
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
} else {
break;
}
if (c >= base) {
break;
}
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
} else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
__set_errno(ERANGE);
} else if (neg) {
acc = -acc;
}
if (endptr != 0) {
*endptr = (char *)(any ? s - 1 : ptr);
}
return (acc);
}
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
unsigned long long strtoull(
const char *restrict ptr,
char **restrict endptr,
register int base)
{
const char *s = ptr;
unsigned long long acc;
int c;
unsigned long long cutoff;
int neg = 0, any, cutlim;
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+') {
c = *s++;
}
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0) {
base = c == '0' ? 8 : 10;
}
cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base;
cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
} else {
break;
}
if (c >= base) {
break;
}
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
} else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULLONG_MAX;
__set_errno(ERANGE);
} else if (neg) {
acc = -acc;
}
if (endptr != 0) {
*endptr = (char *)(any ? s - 1 : ptr);
}
return (acc);
}
+9
View File
@@ -0,0 +1,9 @@
#include <stddef.h>
int memcmp(const void *vl, const void *vr, size_t n)
{
const unsigned char *l = vl, *r = vr;
for (; n && *l == *r; n--, l++, r++)
;
return n ? *l - *r : 0;
}
+24
View File
@@ -0,0 +1,24 @@
#include <stdint.h>
#include <string.h>
static void *memcpy_r(void *dest, const void *src, size_t sz)
{
unsigned char *d = dest;
const unsigned char *s = src;
for (size_t i = 0; i < sz; i++) {
size_t b = sz - i - 1;
d[b] = s[b];
}
return dest;
}
void *memmove(void *dest, const void *src, size_t n)
{
if (dest < src) {
return memcpy(dest, src, n);
} else {
return memcpy_r(dest, src, n);
}
}
+16
View File
@@ -0,0 +1,16 @@
#include <stddef.h>
char *strchr(const char *str, int c)
{
while (1) {
if (*str == c) {
return (char *)str;
}
if (*str == 0) {
break;
}
}
return NULL;
}
+15
View File
@@ -0,0 +1,15 @@
#include <stddef.h>
size_t strcspn(const char *dest, const char *src)
{
size_t i = 0;
for (i = 0; dest[i]; i++) {
for (size_t ii = 0; src[ii]; i++) {
if (dest[i] == src[ii]) {
return i;
}
}
}
return i;
}
+2 -1
View File
@@ -1,6 +1,7 @@
#include <mango/log.h>
#include <rosetta/bootstrap.h>
#include <stdio.h>
#include <errno.h>
extern int main(int, const char **, const char **);
@@ -13,6 +14,6 @@ void *__attribute__((weak)) pthread_self(void)
int __libc_init(const struct rosetta_bootstrap *bsinfo)
{
(volatile void)pthread_self();
kern_logf("bsinfo = %p", bsinfo);
__set_errno(SUCCESS);
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
#include <wctype.h>
int iswnumber(wchar_t c)
{
/* TODO locale support */
return isdigit((int)c);
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
#include <wctype.h>
int iswpunct(wchar_t c)
{
/* TODO locale support */
return ispunct((int)c);
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
#include <wctype.h>
int iswspace(wchar_t c)
{
/* TODO locale support */
return isspace((int)c);
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
#include <wctype.h>
int iswxdigit(wchar_t c)
{
/* TODO locale support */
return isxdigit((int)c);
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef ASSERT_H_
#define ASSERT_H_
#define assert(cond) \
do { \
if (!(cond)) { \
__libc_assert_failed( \
__FILE__, \
__LINE__, \
__FUNCTION__, \
#cond); \
} \
} while (0)
extern void __libc_assert_failed(
const char *file,
int line,
const char *func,
const char *cond);
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef CTYPE_H_
#define CTYPE_H_
extern int isalpha(int c);
extern int isalnum(int c);
extern int isupper(int c);
extern int isspace(int c);
extern int ispunct(int c);
extern int isdigit(int c);
extern int isxdigit(int c);
extern int tolower(int c);
extern int toupper(int c);
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifndef DIRENT_H_
#define DIRENT_H_
#include <sys/types.h>
#define DT_UNKNOWN 0
#define DT_BLK 1
#define DT_CHR 2
#define DT_DIR 3
#define DT_FIFO 4
#define DT_LNK 5
#define DT_REG 6
#define DT_SOCK 7
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[256];
};
struct __opaque_dir;
typedef struct __opaque_dir DIR;
extern DIR *opendir(const char *name);
extern DIR *fdopendir(int fd);
extern int closedir(DIR *dirp);
extern struct dirent *readdir(DIR *dirp);
#endif
+192
View File
@@ -0,0 +1,192 @@
#ifndef INTTYPES_H_
#define INTTYPES_H_
#define __PRI_8_LENGTH_MODIFIER__ "hh"
#define __PRI_64_LENGTH_MODIFIER__ "ll"
#define __SCN_64_LENGTH_MODIFIER__ "ll"
#define __PRI_MAX_LENGTH_MODIFIER__ "j"
#define __SCN_MAX_LENGTH_MODIFIER__ "j"
#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d"
#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i"
#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o"
#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u"
#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x"
#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X"
#define PRId16 "hd"
#define PRIi16 "hi"
#define PRIo16 "ho"
#define PRIu16 "hu"
#define PRIx16 "hx"
#define PRIX16 "hX"
#define PRId32 "d"
#define PRIi32 "i"
#define PRIo32 "o"
#define PRIu32 "u"
#define PRIx32 "x"
#define PRIX32 "X"
#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d"
#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i"
#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o"
#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u"
#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x"
#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X"
#define PRIdLEAST8 PRId8
#define PRIiLEAST8 PRIi8
#define PRIoLEAST8 PRIo8
#define PRIuLEAST8 PRIu8
#define PRIxLEAST8 PRIx8
#define PRIXLEAST8 PRIX8
#define PRIdLEAST16 PRId16
#define PRIiLEAST16 PRIi16
#define PRIoLEAST16 PRIo16
#define PRIuLEAST16 PRIu16
#define PRIxLEAST16 PRIx16
#define PRIXLEAST16 PRIX16
#define PRIdLEAST32 PRId32
#define PRIiLEAST32 PRIi32
#define PRIoLEAST32 PRIo32
#define PRIuLEAST32 PRIu32
#define PRIxLEAST32 PRIx32
#define PRIXLEAST32 PRIX32
#define PRIdLEAST64 PRId64
#define PRIiLEAST64 PRIi64
#define PRIoLEAST64 PRIo64
#define PRIuLEAST64 PRIu64
#define PRIxLEAST64 PRIx64
#define PRIXLEAST64 PRIX64
#define PRIdFAST8 PRId8
#define PRIiFAST8 PRIi8
#define PRIoFAST8 PRIo8
#define PRIuFAST8 PRIu8
#define PRIxFAST8 PRIx8
#define PRIXFAST8 PRIX8
#define PRIdFAST16 PRId16
#define PRIiFAST16 PRIi16
#define PRIoFAST16 PRIo16
#define PRIuFAST16 PRIu16
#define PRIxFAST16 PRIx16
#define PRIXFAST16 PRIX16
#define PRIdFAST32 PRId32
#define PRIiFAST32 PRIi32
#define PRIoFAST32 PRIo32
#define PRIuFAST32 PRIu32
#define PRIxFAST32 PRIx32
#define PRIXFAST32 PRIX32
#define PRIdFAST64 PRId64
#define PRIiFAST64 PRIi64
#define PRIoFAST64 PRIo64
#define PRIuFAST64 PRIu64
#define PRIxFAST64 PRIx64
#define PRIXFAST64 PRIX64
#define PRIdPTR "ld"
#define PRIiPTR "li"
#define PRIoPTR "lo"
#define PRIuPTR "lu"
#define PRIxPTR "lx"
#define PRIXPTR "lX"
#define PRIdMAX __PRI_MAX_LENGTH_MODIFIER__ "d"
#define PRIiMAX __PRI_MAX_LENGTH_MODIFIER__ "i"
#define PRIoMAX __PRI_MAX_LENGTH_MODIFIER__ "o"
#define PRIuMAX __PRI_MAX_LENGTH_MODIFIER__ "u"
#define PRIxMAX __PRI_MAX_LENGTH_MODIFIER__ "x"
#define PRIXMAX __PRI_MAX_LENGTH_MODIFIER__ "X"
#define SCNd8 __PRI_8_LENGTH_MODIFIER__ "d"
#define SCNi8 __PRI_8_LENGTH_MODIFIER__ "i"
#define SCNo8 __PRI_8_LENGTH_MODIFIER__ "o"
#define SCNu8 __PRI_8_LENGTH_MODIFIER__ "u"
#define SCNx8 __PRI_8_LENGTH_MODIFIER__ "x"
#define SCNd16 "hd"
#define SCNi16 "hi"
#define SCNo16 "ho"
#define SCNu16 "hu"
#define SCNx16 "hx"
#define SCNd32 "d"
#define SCNi32 "i"
#define SCNo32 "o"
#define SCNu32 "u"
#define SCNx32 "x"
#define SCNd64 __SCN_64_LENGTH_MODIFIER__ "d"
#define SCNi64 __SCN_64_LENGTH_MODIFIER__ "i"
#define SCNo64 __SCN_64_LENGTH_MODIFIER__ "o"
#define SCNu64 __SCN_64_LENGTH_MODIFIER__ "u"
#define SCNx64 __SCN_64_LENGTH_MODIFIER__ "x"
#define SCNdLEAST8 SCNd8
#define SCNiLEAST8 SCNi8
#define SCNoLEAST8 SCNo8
#define SCNuLEAST8 SCNu8
#define SCNxLEAST8 SCNx8
#define SCNdLEAST16 SCNd16
#define SCNiLEAST16 SCNi16
#define SCNoLEAST16 SCNo16
#define SCNuLEAST16 SCNu16
#define SCNxLEAST16 SCNx16
#define SCNdLEAST32 SCNd32
#define SCNiLEAST32 SCNi32
#define SCNoLEAST32 SCNo32
#define SCNuLEAST32 SCNu32
#define SCNxLEAST32 SCNx32
#define SCNdLEAST64 SCNd64
#define SCNiLEAST64 SCNi64
#define SCNoLEAST64 SCNo64
#define SCNuLEAST64 SCNu64
#define SCNxLEAST64 SCNx64
#define SCNdFAST8 SCNd8
#define SCNiFAST8 SCNi8
#define SCNoFAST8 SCNo8
#define SCNuFAST8 SCNu8
#define SCNxFAST8 SCNx8
#define SCNdFAST16 SCNd16
#define SCNiFAST16 SCNi16
#define SCNoFAST16 SCNo16
#define SCNuFAST16 SCNu16
#define SCNxFAST16 SCNx16
#define SCNdFAST32 SCNd32
#define SCNiFAST32 SCNi32
#define SCNoFAST32 SCNo32
#define SCNuFAST32 SCNu32
#define SCNxFAST32 SCNx32
#define SCNdFAST64 SCNd64
#define SCNiFAST64 SCNi64
#define SCNoFAST64 SCNo64
#define SCNuFAST64 SCNu64
#define SCNxFAST64 SCNx64
#define SCNdPTR "ld"
#define SCNiPTR "li"
#define SCNoPTR "lo"
#define SCNuPTR "lu"
#define SCNxPTR "lx"
#define SCNdMAX __SCN_MAX_LENGTH_MODIFIER__ "d"
#define SCNiMAX __SCN_MAX_LENGTH_MODIFIER__ "i"
#define SCNoMAX __SCN_MAX_LENGTH_MODIFIER__ "o"
#define SCNuMAX __SCN_MAX_LENGTH_MODIFIER__ "u"
#define SCNxMAX __SCN_MAX_LENGTH_MODIFIER__ "x"
#endif
+59
View File
@@ -3,11 +3,28 @@
#include <stdarg.h>
#include <stddef.h>
#include <sys/types.h>
#define EOF -1
#define _IONBF 0
#define _IOFBF 1
#define _IOLBF 2
#ifdef __cplusplus
extern "C" {
#endif
struct __opaque_file;
typedef struct __opaque_file FILE;
#define stdin (__libc_file_stdin())
#define stdout (__libc_file_stdout())
#define stderr (__libc_file_stderr())
extern int printf(const char *format, ...);
extern int vprintf(const char *format, va_list arg);
extern int fprintf(FILE *stream, const char *format, ...);
extern int snprintf(char *buffer, size_t count, const char *format, ...);
extern int vsnprintf(
char *buffer,
@@ -15,6 +32,48 @@ extern int vsnprintf(
const char *format,
va_list va);
extern FILE *fopen(const char *path, const char *mode);
extern int fclose(FILE *stream);
extern int feof(FILE *stream);
extern int ferror(FILE *stream);
extern size_t fread(void *buf, size_t size, size_t count, FILE *stream);
extern size_t fwrite(const void *buf, size_t size, size_t count, FILE *stream);
extern int fgetc(FILE *stream);
static inline int getc(FILE *stream)
{
return fgetc(stream);
}
extern int fputc(int c, FILE *stream);
static inline int putc(int c, FILE *stream)
{
return fputc(c, stream);
}
extern char *fgets(char *restrict str, int count, FILE *restrict stream);
extern int fputs(const char *restrict str, FILE *restrict stream);
extern long ftell(FILE *stream);
extern int fseek(FILE *stream, long offset, int origin);
extern int sscanf(
const char *restrict buffer,
const char *restrict format,
...);
extern int setvbuf(
FILE *restrict stream,
char *restrict buf,
int mode,
size_t size);
extern FILE *__libc_file_stdin(void);
extern FILE *__libc_file_stdout(void);
extern FILE *__libc_file_stderr(void);
#ifdef __cplusplus
}
#endif
+17
View File
@@ -4,10 +4,27 @@
#include <stddef.h>
extern void abort(void);
extern void exit(int result);
extern int atexit(void (*func)(void));
extern void *malloc(size_t count);
extern void *calloc(size_t count, size_t size);
extern void *realloc(void *p, size_t count);
extern void free(void *p);
extern long strtol(const char *restrict str, char **restrict str_end, int base);
extern long long strtoll(
const char *restrict str,
char **restrict str_end,
int base);
extern unsigned long strtoul(
const char *restrict str,
char **restrict endptr,
int base);
extern unsigned long long strtoull(
const char *restrict str,
char **restrict str_end,
int base);
#endif
+6
View File
@@ -8,6 +8,10 @@ extern const char *strerror_code(int errnum);
extern size_t strlen(const char *s);
extern size_t strcspn(const char *dest, const char *src);
extern char *strchr(const char *str, int c);
extern int strcmp(const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, unsigned long n);
@@ -16,6 +20,8 @@ extern int strncpy(const char *s1, const char *s2, unsigned long n);
extern void *memset(void *str, int c, size_t n);
extern void *memcpy(void *dst, const void *src, size_t len);
extern int memcmp(const void *a, const void *b, size_t len);
extern void *memmove(void *dst, const void *src, size_t len);
extern char *strdup(char *s);
+9
View File
@@ -7,4 +7,13 @@
#define SEEK_CUR 1
#define SEEK_END 2
typedef size_t ino_t;
struct dentry {
unsigned long d_ino;
unsigned short d_reclen;
char d_type;
char d_name[];
};
#endif
+4
View File
@@ -0,0 +1,4 @@
#ifndef TIME_H_
#define TIME_H_
#endif
+2
View File
@@ -12,4 +12,6 @@ extern int write(int fd, const void *buf, size_t count);
extern off_t lseek(int fd, off_t offset, int whence);
extern long getdents(int fd, struct dentry *dirp, unsigned int count);
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef WCTYPE_H_
#define WCTYPE_H_
#include <stddef.h>
#include <stdint.h>
extern int iswnumber(wchar_t c);
extern int iswxdigit(wchar_t c);
extern int iswspace(wchar_t c);
extern int iswpunct(wchar_t c);
#endif
+19
View File
@@ -0,0 +1,19 @@
#include "dir.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int closedir(struct __opaque_dir *dirp)
{
close(dirp->d_fd);
if (dirp->d_buf) {
free(dirp->d_buf);
}
free(dirp);
return SUCCESS;
}
+81
View File
@@ -0,0 +1,81 @@
#include "dir.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_BUFFER_SIZE 4096
static void dirent_convert(const struct dentry *in, struct dirent *out)
{
out->d_ino = in->d_ino;
out->d_type = in->d_type;
out->d_reclen = in->d_reclen;
strncpy(out->d_name, in->d_name, sizeof out->d_name - 1);
out->d_name[sizeof out->d_name - 1] = 0;
}
int __libc_dir_refill(struct __opaque_dir *d)
{
if (d->d_fd < 0) {
return EBADF;
}
if (d->d_flags & DIR_ERR) {
return EIO;
}
if (d->d_flags & DIR_EOF) {
return SUCCESS;
}
if (!d->d_buf) {
d->d_buf_max = DEFAULT_BUFFER_SIZE;
d->d_buf = malloc(d->d_buf_max);
if (!d->d_buf) {
d->d_buf_max = 0;
return ENOMEM;
}
}
long r = getdents(d->d_fd, (struct dentry *)d->d_buf, d->d_buf_max);
if (r < 0) {
return -r;
}
d->d_buf_datalen = r;
if (r > 0) {
struct dentry *dent
= (struct dentry *)(d->d_buf + d->d_buf_readptr);
dirent_convert(dent, &d->d_current);
}
return SUCCESS;
}
int __libc_dir_move_next(struct __opaque_dir *d)
{
if (d->d_fd < 0) {
return -EBADF;
}
if (d->d_flags & DIR_ERR) {
return -EIO;
}
if (d->d_flags & DIR_EOF) {
return -SUCCESS;
}
d->d_buf_readptr += d->d_current.d_reclen;
if (d->d_buf_readptr >= d->d_buf_datalen) {
return 0;
}
struct dentry *dent = (struct dentry *)(d->d_buf + d->d_buf_readptr);
dirent_convert(dent, &d->d_current);
return 1;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef _LIBC_IO_DIR_H_
#define _LIBC_IO_DIR_H_
#include <dirent.h>
#include <stddef.h>
enum dir_flags {
DIR_EOF = 0x01u,
DIR_ERR = 0x02u,
};
struct __opaque_dir {
enum dir_flags d_flags;
int d_fd;
char *d_buf;
struct dirent d_current;
size_t d_buf_datalen, d_buf_max;
size_t d_buf_readptr;
};
extern int __libc_dir_refill(struct __opaque_dir *d);
extern int __libc_dir_move_next(struct __opaque_dir *d);
#endif
+27
View File
@@ -0,0 +1,27 @@
#include "file.h"
#include <errno.h>
#include <fcntl.h>
#include <mango/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int fclose(struct __opaque_file *stream)
{
if (stream->f_fd < 0) {
return __set_errno(EBADF);
}
close(stream->f_fd);
if (stream->f_buf.buf_ptr) {
free(stream->f_buf.buf_ptr);
}
if (!(stream->f_flags & FILE_STATIC)) {
free(stream);
}
return SUCCESS;
}
View File
+6
View File
@@ -0,0 +1,6 @@
#include "file.h"
int feof(struct __opaque_file *stream)
{
return (stream->f_flags & FILE_EOF) != 0;
}
+6
View File
@@ -0,0 +1,6 @@
#include "file.h"
int ferror(struct __opaque_file *stream)
{
return (stream->f_flags & FILE_ERR) != 0;
}
+27
View File
@@ -0,0 +1,27 @@
#include "file.h"
#include <errno.h>
#include <stdio.h>
int __fgetc(struct __opaque_file *stream)
{
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
return EOF;
}
char c = 0;
int ret = __libc_file_read(stream, &c, 1);
if (ret < 1) {
return EOF;
}
return c;
}
int fgetc(struct __opaque_file *stream)
{
__libc_file_lock(stream);
int ret = __fgetc(stream);
__libc_file_unlock(stream);
return ret;
}
+45
View File
@@ -0,0 +1,45 @@
#include "file.h"
#include <stdio.h>
char *fgets(
char *restrict str,
int count,
struct __opaque_file *restrict stream)
{
__libc_file_lock(stream);
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
__libc_file_unlock(stream);
return NULL;
}
size_t i = 0;
while (1) {
int c = fgetc(stream);
if (c == EOF) {
str[i] = 0;
break;
}
str[i++] = c;
if (c == '\n') {
str[i] = 0;
break;
}
}
if (ferror(stream)) {
__libc_file_unlock(stream);
return NULL;
}
if (feof(stream) && i == 0) {
__libc_file_unlock(stream);
return NULL;
}
__libc_file_unlock(stream);
return str;
}
+329
View File
@@ -0,0 +1,329 @@
#include "file.h"
#include <errno.h>
#include <mango/futex.h>
#include <mango/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define OP_READ 1
#define OP_WRITE 2
#define FILE_UNUSABLE(f) (((f)->f_flags & (FILE_EOF | FILE_ERR)) != 0)
static long clear_buf(struct __opaque_file *f)
{
__libc_ringbuf_clear(&f->f_buf);
lseek(f->f_fd, f->f_seek, SEEK_SET);
return 0;
}
static long refill_buf(struct __opaque_file *f)
{
kern_tracef("refill");
char *buf = NULL;
size_t available = 0;
long r = 0;
size_t nr_read = 0;
while (1) {
__libc_ringbuf_get_write_buffer(&f->f_buf, &buf, &available);
if (available == 0) {
__libc_ringbuf_put_write_buffer(
&f->f_buf,
&buf,
&available);
break;
}
kern_tracef("read(%d, %p, %zu)", f->f_fd, buf, available);
r = read(f->f_fd, buf, available);
if (r <= 0) {
break;
}
available = r;
nr_read += r;
__libc_ringbuf_put_write_buffer(&f->f_buf, &buf, &available);
}
if (nr_read > 0) {
return nr_read;
}
if (r < 0) {
return -errno;
}
return nr_read;
}
static long flush_buf(struct __opaque_file *f)
{
const char *buf = NULL;
size_t available = 0;
long r = 0;
size_t nr_written = 0;
while (1) {
__libc_ringbuf_get_read_buffer(&f->f_buf, &buf, &available);
if (available == 0) {
__libc_ringbuf_put_read_buffer(
&f->f_buf,
&buf,
&available);
break;
}
r = write(f->f_fd, buf, available);
kern_tracef(
"write(%d, %p, %zu) = %ld",
f->f_fd,
buf,
available,
r);
if (r < 0) {
break;
}
available = r;
nr_written += r;
__libc_ringbuf_put_read_buffer(&f->f_buf, &buf, &available);
}
if (nr_written > 0) {
return nr_written;
}
if (r < 0) {
return -errno;
}
return 0;
}
void __libc_file_lock(struct __opaque_file *f)
{
kern_futex_t expected = 0;
while (1) {
kern_tracef("lock=%u (%p)", f->f_lock, f);
expected = 0;
if (__atomic_compare_exchange_n(
&f->f_lock,
&expected,
1,
0,
__ATOMIC_ACQUIRE,
__ATOMIC_ACQUIRE)) {
kern_tracef("locked=%u (%p)", f->f_lock, f);
return;
}
kern_tracef("wait=%u (%p)", expected, f);
futex_wait(&f->f_lock, 1, FUTEX_PRIVATE);
}
}
void __libc_file_unlock(struct __opaque_file *f)
{
f->f_lock = 0;
futex_wake(&f->f_lock, 1, FUTEX_PRIVATE);
kern_tracef("unlocked=%u (%p)", f->f_lock, f);
}
static long read_buf(struct __opaque_file *f, void *out, size_t count)
{
kern_tracef("read_buf(%p, %zu)", out, count);
char *dest = out;
size_t nr_read = 0;
long r = 0;
while (nr_read < count) {
r = __libc_ringbuf_read(
&f->f_buf,
dest + nr_read,
count - nr_read);
if (r < 0) {
break;
}
nr_read += r;
if (r == 0) {
r = refill_buf(f);
if (r <= 0) {
break;
}
}
}
if (r < 0) {
return r;
}
return nr_read;
}
static long read_nobuf(struct __opaque_file *f, void *out, size_t count)
{
kern_tracef("read_nobuf");
return read(f->f_fd, out, count);
}
long __libc_file_read(struct __opaque_file *f, void *out, size_t count)
{
long ret = 0;
if (f->f_prev != OP_READ) {
ret = flush_buf(f);
clear_buf(f);
}
if (ret != 0) {
return __set_errno(ret);
}
switch (f->f_buffer_mode) {
case _IOFBF:
case _IOLBF:
ret = read_buf(f, out, count);
break;
case _IONBF:
ret = read_nobuf(f, out, count);
break;
default:
ret = -EINVAL;
break;
}
f->f_prev = OP_READ;
if (ret < 0) {
f->f_flags |= FILE_ERR;
return __set_errno(-ret);
}
if (ret == 0) {
f->f_flags |= FILE_EOF;
}
f->f_seek += ret;
return ret;
}
static long write_fullbuf(struct __opaque_file *f, const void *p, size_t count)
{
const char *src = p;
size_t nr_written = 0;
long r = 0;
while (nr_written < count) {
r = __libc_ringbuf_write(
&f->f_buf,
src + nr_written,
count - nr_written);
if (r < 0) {
break;
}
nr_written += r;
if (r == 0) {
r = flush_buf(f);
if (r <= 0) {
break;
}
}
}
if (r < 0) {
return r;
}
return nr_written;
}
static long write_linebuf(
struct __opaque_file *f,
const void *out,
size_t count)
{
const char *s = out;
size_t nr_written = 0;
long r = 0;
while (nr_written < count) {
char c = s[nr_written];
r = __libc_ringbuf_write(&f->f_buf, &c, 1);
if (r < 0) {
break;
}
nr_written += r;
if (r == 0 || c == '\n') {
r = flush_buf(f);
if (r < 0) {
break;
}
}
}
if (r < 0) {
return r;
}
return nr_written;
}
static long write_nobuf(struct __opaque_file *f, const void *out, size_t count)
{
return write(f->f_fd, out, count);
}
long __libc_file_write(struct __opaque_file *f, const void *buf, size_t count)
{
if (f->f_lock != 1) {
kern_tracef("file is not locked!!!");
}
long ret = 0;
if (f->f_prev != OP_WRITE) {
ret = clear_buf(f);
}
if (ret != 0) {
return __set_errno(ret);
}
switch (f->f_buffer_mode) {
case _IOFBF:
ret = write_fullbuf(f, buf, count);
break;
case _IOLBF:
ret = write_linebuf(f, buf, count);
break;
case _IONBF:
ret = write_nobuf(f, buf, count);
break;
default:
ret = -EINVAL;
break;
}
f->f_prev = OP_WRITE;
if (ret < 0) {
f->f_flags |= FILE_ERR;
return __set_errno(-ret);
}
if (ret == 0) {
f->f_flags |= FILE_EOF;
}
f->f_seek += ret;
return ret;
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef _LIBC_IO_FILE_H_
#define _LIBC_IO_FILE_H_
#include "ringbuf.h"
#include <mango/types.h>
#include <stddef.h>
enum file_flags {
FILE_EOF = 0x01u,
FILE_ERR = 0x02u,
FILE_BIN = 0x04u,
FILE_STATIC = 0x08u,
};
struct __opaque_file {
enum file_flags f_flags;
kern_futex_t f_lock;
int f_prev;
int f_buffer_mode;
int f_fd;
char f_unget;
/* the current seek position of the buffered data (i.e. the offset of
* the data that would be returned by reading f_buf). */
size_t f_seek;
struct ringbuf f_buf;
};
extern void __libc_file_lock(struct __opaque_file *f);
extern void __libc_file_unlock(struct __opaque_file *f);
extern long __libc_file_read(struct __opaque_file *f, void *p, size_t count);
extern long __libc_file_write(
struct __opaque_file *f,
const void *p,
size_t count);
#endif
+157
View File
@@ -0,0 +1,157 @@
#include "file.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
enum mode {
MODE_R = 0x01u,
MODE_W = 0x02u,
MODE_A = 0x04u,
MODE_B = 0x08u,
MODE_X = 0x10u,
MODE_PLUS = 0x20u,
};
static int flags_from_mode(
const char *mode_string,
int *out_sysflags,
enum file_flags *out_fflags)
{
enum mode mode = 0;
int sysflags = 0;
enum file_flags fflags = 0;
for (int i = 0; mode_string[i]; i++) {
switch (mode_string[i]) {
case 'r':
if (mode & (MODE_R | MODE_W | MODE_A | MODE_X)) {
return -1;
}
mode |= MODE_R;
break;
case 'w':
if (mode & (MODE_R | MODE_W | MODE_A)) {
return -1;
}
mode |= MODE_W;
break;
case 'a':
if (mode & (MODE_R | MODE_W | MODE_A | MODE_X)) {
return -1;
}
break;
case '+':
if (mode & MODE_PLUS) {
return -1;
}
mode |= MODE_PLUS;
break;
case 'b':
if (mode & MODE_B) {
return -1;
}
mode |= MODE_B;
break;
case 'x':
if (mode & (MODE_R | MODE_A | MODE_X)) {
return -1;
}
mode |= MODE_X;
break;
default:
return -1;
}
}
switch ((int)mode) {
case MODE_R | MODE_B:
fflags = FILE_BIN;
case MODE_R:
sysflags = O_RDONLY;
break;
case MODE_W | MODE_B:
fflags = FILE_BIN;
case MODE_W:
sysflags = O_WRONLY | O_TRUNC | O_CREAT;
break;
case MODE_A | MODE_B:
fflags = FILE_BIN;
case MODE_A:
sysflags = O_WRONLY | O_APPEND | O_CREAT;
break;
case MODE_R | MODE_PLUS | MODE_B:
fflags = FILE_BIN;
case MODE_R | MODE_PLUS:
sysflags = O_RDWR;
break;
case MODE_W | MODE_PLUS | MODE_B:
fflags = FILE_BIN;
case MODE_W | MODE_PLUS:
sysflags = O_RDWR | O_TRUNC | O_CREAT;
break;
case MODE_W | MODE_PLUS | MODE_X | MODE_B:
fflags = FILE_BIN;
case MODE_W | MODE_PLUS | MODE_X:
sysflags = O_RDWR | O_TRUNC | O_CREAT | O_EXCL;
break;
case MODE_A | MODE_PLUS | MODE_B:
fflags = FILE_BIN;
case MODE_A | MODE_PLUS:
sysflags = O_RDWR | O_APPEND | O_CREAT;
break;
default:
return -1;
}
return 0;
}
struct __opaque_file *fopen(const char *path, const char *mode)
{
int sysflags = 0;
enum file_flags fflags = 0;
if (flags_from_mode(mode, &sysflags, &fflags) != 0) {
__set_errno(EINVAL);
return NULL;
}
struct __opaque_file *out = malloc(sizeof *out);
if (!out) {
__set_errno(ENOMEM);
return NULL;
}
memset(out, 0x0, sizeof *out);
int fd = open(path, sysflags);
if (fd < 0) {
free(out);
__set_errno(-fd);
return NULL;
}
if (fflags & FILE_BIN) {
out->f_buffer_mode = _IOFBF;
} else {
out->f_buffer_mode = _IOLBF;
}
out->f_fd = fd;
out->f_flags = fflags;
__set_errno(SUCCESS);
return out;
}
+6
View File
@@ -0,0 +1,6 @@
#include "file.h"
int fprintf(struct __opaque_file *stream, const char *format, ...)
{
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
#include "file.h"
#include <errno.h>
#include <stdio.h>
int __fputc(int c, struct __opaque_file *stream)
{
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
return EOF;
}
char cv = c;
int ret = __libc_file_write(stream, &cv, 1);
if (ret < 1) {
return EOF;
}
__set_errno(SUCCESS);
return c;
}
int fputc(int c, struct __opaque_file *stream)
{
__libc_file_lock(stream);
int ret = __fputc(c, stream);
__libc_file_unlock(stream);
return ret;
}
+31
View File
@@ -0,0 +1,31 @@
#include "file.h"
#include <stdio.h>
extern int __fputc(int c, struct __opaque_file *stream);
int fputs(const char *restrict str, struct __opaque_file *restrict stream)
{
__libc_file_lock(stream);
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
__libc_file_unlock(stream);
return EOF;
}
size_t i = 0;
int err = 0;
for (i = 0; str[i]; i++) {
err = __fputc(str[i], stream);
if (err < 0) {
break;
}
}
__libc_file_unlock(stream);
if (i > 0) {
return i;
}
return err;
}
+26
View File
@@ -0,0 +1,26 @@
#include "file.h"
#include <unistd.h>
size_t fread(void *buf, size_t size, size_t count, struct __opaque_file *stream)
{
__libc_file_lock(stream);
size_t total = size * count;
if (total == 0) {
__libc_file_unlock(stream);
return 0;
}
long ret = __libc_file_read(stream, buf, total);
if (ret == 0) {
stream->f_flags |= FILE_EOF;
}
if (ret < 0) {
stream->f_flags |= FILE_ERR;
ret = 0;
}
__libc_file_unlock(stream);
return ret;
}
+8
View File
@@ -0,0 +1,8 @@
#include "file.h"
#include <unistd.h>
int fseek(struct __opaque_file *stream, long offset, int origin)
{
return lseek(stream->f_fd, offset, origin);
}
+8
View File
@@ -0,0 +1,8 @@
#include "file.h"
#include <unistd.h>
long ftell(struct __opaque_file *stream)
{
return lseek(stream->f_fd, 0, SEEK_CUR);
}
+29
View File
@@ -0,0 +1,29 @@
#include "file.h"
#include <unistd.h>
size_t fwrite(
const void *buf,
size_t size,
size_t count,
struct __opaque_file *stream)
{
__libc_file_lock(stream);
size_t total = size * count;
if (total == 0) {
return 0;
}
long ret = __libc_file_write(stream, buf, total);
if (ret == 0) {
stream->f_flags |= FILE_EOF;
}
if (ret < 0) {
stream->f_flags |= FILE_ERR;
ret = 0;
}
__libc_file_unlock(stream);
return ret;
}
+30
View File
@@ -0,0 +1,30 @@
#include "dir.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern struct __opaque_dir *opendir(const char *name)
{
struct __opaque_dir *out = malloc(sizeof *out);
if (!out) {
__set_errno(ENOMEM);
return NULL;
}
memset(out, 0x0, sizeof *out);
int fd = open(name, O_RDONLY | O_DIRECTORY);
if (fd < 0) {
free(out);
return NULL;
}
out->d_flags = 0;
out->d_fd = fd;
return out;
}
+12
View File
@@ -0,0 +1,12 @@
#include <stddef.h>
#include <stdio.h>
int printf(const char *format, ...)
{
va_list arg;
va_start(arg, format);
int ret = vprintf(format, arg);
va_end(arg);
return ret;
}
+35
View File
@@ -0,0 +1,35 @@
#include "dir.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct dirent *readdir(struct __opaque_dir *dirp)
{
int result = __libc_dir_move_next(dirp);
if (result < 0) {
dirp->d_flags |= DIR_ERR;
__set_errno(-result);
return NULL;
}
if (result > 0) {
return &dirp->d_current;
}
result = __libc_dir_refill(dirp);
if (result < 0) {
dirp->d_flags |= DIR_ERR;
__set_errno(-result);
return NULL;
}
if (!dirp->d_buf_datalen) {
return NULL;
}
return &dirp->d_current;
}
+271
View File
@@ -0,0 +1,271 @@
#include "file.h"
#include <errno.h>
#include <mango/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_BUFFER_SIZE 4096
static int ringbuf_init(struct ringbuf *buf)
{
if (buf->buf_ptr) {
return SUCCESS;
}
if (!buf->buf_max) {
buf->buf_max = DEFAULT_BUFFER_SIZE;
}
buf->buf_ptr = malloc(buf->buf_max);
if (!buf->buf_ptr) {
return ENOMEM;
}
memset(buf->buf_ptr, 0x0, buf->buf_max);
return SUCCESS;
}
int __libc_ringbuf_get_read_buffer(
struct ringbuf *buf,
const char **out_bufp,
size_t *out_len)
{
int r = ringbuf_init(buf);
if (r != SUCCESS) {
return r;
}
size_t contiguous_capacity = 0;
if (buf->buf_readp > buf->buf_writep) {
contiguous_capacity = buf->buf_max - buf->buf_readp;
} else {
contiguous_capacity = buf->buf_writep - buf->buf_readp;
}
kern_tracef(
"OPEN READ: readp=%zu, writep=%zu, max=%zu -> %p cap=%zu",
buf->buf_readp,
buf->buf_writep,
buf->buf_max,
buf->buf_ptr + buf->buf_readp,
contiguous_capacity);
*out_len = contiguous_capacity;
if (contiguous_capacity == 0) {
*out_bufp = NULL;
} else {
*out_bufp = buf->buf_ptr + buf->buf_readp;
}
return SUCCESS;
}
void __libc_ringbuf_put_read_buffer(
struct ringbuf *buf,
const char **bufp,
size_t *len)
{
buf->buf_readp += *len;
if (buf->buf_readp == buf->buf_writep) {
buf->buf_readp = buf->buf_writep = 0;
}
kern_tracef("CLOSE READ: %p r=%zu", *bufp, *len);
*bufp = NULL;
*len = 0;
}
int __libc_ringbuf_get_write_buffer(
struct ringbuf *buf,
char **out_bufp,
size_t *out_len)
{
int r = ringbuf_init(buf);
if (r != SUCCESS) {
return r;
}
size_t contiguous_capacity = 0;
if (buf->buf_writep >= buf->buf_readp) {
contiguous_capacity = buf->buf_max - buf->buf_writep - 1;
if (buf->buf_readp > 0) {
contiguous_capacity++;
}
} else {
contiguous_capacity = buf->buf_readp - buf->buf_writep - 1;
}
kern_tracef(
"OPEN WRITE: readp=%zu, writep=%zu, max=%zu -> %p cap=%zu",
buf->buf_readp,
buf->buf_writep,
buf->buf_max,
buf->buf_ptr + buf->buf_readp,
contiguous_capacity);
*out_len = contiguous_capacity;
if (contiguous_capacity == 0) {
*out_bufp = NULL;
} else {
*out_bufp = buf->buf_ptr + buf->buf_writep;
}
return SUCCESS;
}
void __libc_ringbuf_put_write_buffer(
struct ringbuf *buf,
char **bufp,
size_t *len)
{
buf->buf_writep += *len;
if (buf->buf_readp == buf->buf_writep) {
buf->buf_readp = buf->buf_writep = 0;
}
kern_tracef(
"CLOSE WRITE: %p r=%zu (%c)",
*bufp,
*len,
*(char *)(*bufp));
*bufp = NULL;
*len = 0;
}
long __libc_ringbuf_read(struct ringbuf *buf, void *p, size_t count)
{
size_t nr_read = 0;
long r = 0;
while (nr_read < count) {
const char *src = NULL;
size_t available = 0;
r = __libc_ringbuf_get_read_buffer(buf, &src, &available);
if (r < 0) {
break;
}
char *dest = p + nr_read;
size_t to_copy = count - nr_read;
if (available == 0) {
__libc_ringbuf_put_read_buffer(buf, &src, &available);
break;
}
if (to_copy > available) {
to_copy = available;
}
memcpy(dest, src, to_copy);
nr_read += available;
__libc_ringbuf_put_read_buffer(buf, &src, &to_copy);
}
if (r < 0) {
return r;
}
return nr_read;
}
long __libc_ringbuf_write(struct ringbuf *buf, const void *p, size_t count)
{
size_t nr_written = 0;
long r = 0;
while (nr_written < count) {
char *dest = NULL;
size_t available = 0;
r = __libc_ringbuf_get_write_buffer(buf, &dest, &available);
if (r < 0) {
break;
}
const char *src = p + nr_written;
size_t to_copy = count - nr_written;
if (available == 0) {
__libc_ringbuf_put_write_buffer(buf, &dest, &available);
break;
}
if (to_copy > available) {
to_copy = available;
}
memcpy(dest, src, to_copy);
nr_written += available;
__libc_ringbuf_put_write_buffer(buf, &dest, &to_copy);
}
if (r < 0) {
return r;
}
return nr_written;
}
int __libc_ringbuf_clear(struct ringbuf *buf)
{
buf->buf_readp = buf->buf_writep = 0;
return 0;
}
int __libc_ringbuf_resize(struct ringbuf *buf, size_t max)
{
if (!(buf->buf_flags & RINGBUF_STATIC)) {
free(buf->buf_ptr);
buf->buf_ptr = NULL;
}
buf->buf_readp = buf->buf_writep = 0;
buf->buf_flags &= ~RINGBUF_STATIC;
buf->buf_max = max;
return 0;
}
int __libc_ringbuf_resize_static(struct ringbuf *buf, void *p, size_t max)
{
if (!(buf->buf_flags & RINGBUF_STATIC)) {
free(buf->buf_ptr);
buf->buf_ptr = NULL;
}
buf->buf_readp = buf->buf_writep = 0;
buf->buf_flags |= RINGBUF_STATIC;
buf->buf_ptr = p;
buf->buf_max = max;
return 0;
}
size_t __libc_ringbuf_available(const struct ringbuf *buf)
{
if (buf->buf_readp < buf->buf_writep) {
return buf->buf_writep - buf->buf_readp;
} else if (buf->buf_readp > buf->buf_writep) {
return buf->buf_max - buf->buf_readp + buf->buf_writep;
} else {
return 0;
}
}
size_t __libc_ringbuf_capacity(const struct ringbuf *buf)
{
if (buf->buf_readp > buf->buf_writep) {
return buf->buf_readp - buf->buf_writep - 1;
} else {
return buf->buf_max - buf->buf_writep + buf->buf_readp - 1;
}
}
+53
View File
@@ -0,0 +1,53 @@
#ifndef _LIBC_IO_RINGBUF_H_
#define _LIBC_IO_RINGBUF_H_
#include <stddef.h>
enum ringbuf_flags {
RINGBUF_NONE = 0,
RINGBUF_STATIC,
};
struct ringbuf {
enum ringbuf_flags buf_flags;
char *buf_ptr;
size_t buf_max;
size_t buf_readp, buf_writep;
};
extern int __libc_ringbuf_get_read_buffer(
struct ringbuf *buf,
const char **out_bufp,
size_t *out_len);
extern void __libc_ringbuf_put_read_buffer(
struct ringbuf *buf,
const char **bufp,
size_t *len);
extern int __libc_ringbuf_get_write_buffer(
struct ringbuf *buf,
char **out_bufp,
size_t *out_len);
extern void __libc_ringbuf_put_write_buffer(
struct ringbuf *buf,
char **bufp,
size_t *len);
extern long __libc_ringbuf_read(struct ringbuf *buf, void *p, size_t count);
extern long __libc_ringbuf_write(
struct ringbuf *buf,
const void *p,
size_t count);
extern int __libc_ringbuf_clear(struct ringbuf *buf);
extern int __libc_ringbuf_resize(struct ringbuf *buf, size_t max);
extern int __libc_ringbuf_resize_static(
struct ringbuf *buf,
void *p,
size_t max);
extern size_t __libc_ringbuf_available(const struct ringbuf *buf);
extern size_t __libc_ringbuf_capacity(const struct ringbuf *buf);
#endif
+39
View File
@@ -0,0 +1,39 @@
#include "file.h"
#include <errno.h>
#include <stdio.h>
extern int setvbuf(
struct __opaque_file *restrict stream,
char *restrict buf,
int mode,
size_t size)
{
switch (mode) {
case _IOFBF:
case _IOLBF:
case _IONBF:
break;
default:
return __set_errno(EINVAL);
}
if (stream->f_prev != 0) {
return __set_errno(EINVAL);
}
int err = SUCCESS;
if (buf) {
err = __libc_ringbuf_resize_static(&stream->f_buf, buf, size);
} else {
err = __libc_ringbuf_resize(&stream->f_buf, size);
}
if (err != SUCCESS) {
return __set_errno(err);
}
stream->f_buffer_mode = mode;
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
#include "file.h"
#include <stdio.h>
static struct __opaque_file __stderr = {
.f_fd = 2,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IONBF,
};
extern struct __opaque_file *__libc_file_stderr(void)
{
return &__stderr;
}
+14
View File
@@ -0,0 +1,14 @@
#include "file.h"
#include <stdio.h>
static struct __opaque_file __stdin = {
.f_fd = 0,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IOLBF,
};
extern struct __opaque_file *__libc_file_stdin(void)
{
return &__stdin;
}
+14
View File
@@ -0,0 +1,14 @@
#include "file.h"
#include <stdio.h>
static struct __opaque_file __stdout = {
.f_fd = 1,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IOLBF,
};
extern struct __opaque_file *__libc_file_stdout(void)
{
return &__stdout;
}
+35
View File
@@ -0,0 +1,35 @@
#include "file.h"
#include <stddef.h>
#include <errno.h>
#include <stdio.h>
extern int __libc_fctprintf(
int (*out)(char character, void *arg),
void *arg,
const char *format,
va_list va);
extern int __fputc(int c, struct __opaque_file *stream);
static inline int _out_file(char character, void *arg)
{
FILE *fp = arg;
return __fputc(character, fp);
}
int vprintf(const char *format, va_list arg)
{
__libc_file_lock(stdout);
int ret = __libc_fctprintf(_out_file, stdout, format, arg);
if (errno != SUCCESS) {
ret = -1;
}
if (ferror(stdout)) {
ret = -1;
}
__libc_file_unlock(stdout);
return ret;
}
+22
View File
@@ -0,0 +1,22 @@
#include <errno.h>
#include <mango/handle.h>
#include <mango/msg.h>
#include <rosetta/fs.h>
#include <sys/remote.h>
#include <sys/types.h>
int getdents(int fd, struct dentry *dirp, unsigned int count)
{
int err;
size_t nr_read = 0;
kern_status_t status = fs_getdents(fd, &err, dirp, count, &nr_read);
if (status != KERN_OK) {
return __set_errno(__errno_from_kern_status(status));
}
if (err != SUCCESS) {
return __set_errno(err);
}
return nr_read;
}
+18
View File
@@ -25,6 +25,21 @@ static vm_prot_t vm_prot_from_mmap_prot(int prot)
return vm_prot;
}
static vm_flags_t vm_flags_from_mmap_flags(int flags)
{
vm_flags_t out = 0;
if (flags & MAP_PRIVATE) {
out |= VM_PRIVATE;
}
if (flags & (MAP_SHARED | MAP_SHARED_VALIDATE)) {
out |= VM_SHARED;
}
return out;
}
static int get_vmo_anon(
int fd,
int prot,
@@ -109,6 +124,7 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
kern_status_t status = KERN_OK;
kern_handle_t self = KERN_HANDLE_INVALID,
address_space = KERN_HANDLE_INVALID;
vm_flags_t vm_flags = vm_flags_from_mmap_flags(flags);
status = task_self(&self);
if (status != KERN_OK) {
@@ -146,6 +162,7 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
vmo,
offset,
length,
vm_flags,
vm_prot,
&map_address);
} else {
@@ -155,6 +172,7 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
vmo,
offset,
length,
vm_flags,
vm_prot,
&map_address);
}
+1 -1
View File
@@ -8,7 +8,7 @@ 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);
kern_status_t status = fs_read(fd, count, &err, buf, count, &nr_read);
if (status != KERN_OK) {
return __set_errno(__errno_from_kern_status(status));
}
+21
View 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 write(int fd, const void *buf, size_t count)
{
int err;
size_t nr_written;
kern_status_t status = fs_write(fd, buf, count, &err, &nr_written);
if (status != KERN_OK) {
return __set_errno(__errno_from_kern_status(status));
}
if (err != SUCCESS) {
return __set_errno(err);
}
return nr_written;
}
+1
View File
@@ -79,6 +79,7 @@ static kern_status_t expand_heap(heap_t *heap)
vmo,
0,
HEAP_EXPAND_INCREMENT,
VM_PRIVATE,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
&base);
+6
View File
@@ -1,6 +1,8 @@
#ifndef PTHREAD_H_
#define PTHREAD_H_
#include <mango/types.h>
#define __PTHREAD_ATTR_SIZE__ 32
typedef struct __pthread *pthread_t;
@@ -10,6 +12,10 @@ typedef struct __pthread_attr {
char __opaque[__PTHREAD_ATTR_SIZE__];
} pthread_attr_t;
typedef struct __pthread_mutex {
kern_futex_t __v;
} pthread_mutex_t;
extern int __pthread_init(void);
extern int pthread_create(
@@ -23,7 +23,7 @@ __pthread_unmap_exit:
syscall
/* next, close the handle to the address space */
mov $SYS_THREAD_EXIT, %rax
mov $SYS_KERN_HANDLE_CLOSE, %rax
mov %rbx, %rdi
syscall
-3
View File
@@ -1,12 +1,9 @@
#include "pthread.h"
#include <mango/log.h>
#include <pthread.h>
#include <stdio.h>
int *__errno_location(void)
{
struct __pthread *self = pthread_self();
kern_logf("using pthread errno %p", &self->thr_errno);
return &self->thr_errno;
}
+4
View File
@@ -23,6 +23,10 @@ sysroot_add_library(
HEADER_DIR /usr/include
LIB_DIR /usr/lib)
bsp_add_library(
NAME libfs
LIB_DIR /usr/lib)
target_link_libraries(libfs libmango interface::fs libc libxpc)
target_link_libraries(libfs-static libmango interface::fs libc-core libxpc-static)
+170 -12
View File
@@ -73,6 +73,7 @@ struct fs_context *fs_context_create(struct fs_allocator *alloc)
ctx->ctx_temp_object,
0,
TEMP_OBJECT_SIZE,
VM_PRIVATE,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
&temp_buffer);
kern_handle_close(address_space);
@@ -92,6 +93,7 @@ struct fs_context *fs_context_create(struct fs_allocator *alloc)
ctx->ctx_vtable.write = fs_msg_write;
ctx->ctx_vtable.seek = fs_msg_seek;
ctx->ctx_vtable.map = fs_msg_map;
ctx->ctx_vtable.getdents = fs_msg_getdents;
return ctx;
}
@@ -140,6 +142,30 @@ kern_handle_t fs_context_get_vm_controller(const struct fs_context *ctx)
return ctx->ctx_vm_controller;
}
static enum fs_status handle_event(struct fs_context *ctx, xpc_msg_t *msg)
{
switch (msg->msg_event) {
case KERN_MSG_EVENT_CONNECTION:
kern_tracef("received connection");
break;
case KERN_MSG_EVENT_DISCONNECTION: {
kern_tracef("received disconnect");
struct fs_file *f
= fs_context_get_file(ctx, msg->msg_sender.e_port);
if (f) {
fs_context_close_file(ctx, f);
fs_context_unref_file(ctx, f);
}
break;
}
default:
kern_logf("received unknown event");
break;
}
return FS_SUCCESS;
}
static enum fs_status handle_msg(struct fs_context *ctx)
{
xpc_msg_t msg;
@@ -153,6 +179,10 @@ static enum fs_status handle_msg(struct fs_context *ctx)
return FS_ERR_INTERNAL_FAILURE;
}
if (msg.msg_type != KERN_MSG_TYPE_DATA) {
return handle_event(ctx, &msg);
}
switch (msg.msg_header.hdr_interface) {
case INTERFACE_FS:
status = fs_context_dispatch_msg(ctx, &msg);
@@ -168,18 +198,53 @@ static enum fs_status handle_msg(struct fs_context *ctx)
return FS_SUCCESS;
}
static enum fs_status handle_page_request(struct fs_context *ctx)
static enum fs_status handle_vm_request_detach(
struct fs_context *ctx,
equeue_packet_vm_request_t *packet,
struct file_mapping *mapping)
{
equeue_packet_page_request_t packet;
vm_controller_recv(ctx->ctx_vm_controller, &packet);
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
if (!mapping) {
kern_logf(
"received DETACH request from VMO with no associated "
"mapping");
return FS_ERR_INTERNAL_FAILURE;
}
kern_tracef(
"received page request [%zx-%zx] for file %s",
packet.req_offset,
packet.req_offset + packet.req_length,
"received vm request (detach) for file %s",
mapping->m_file->f_dent->d_name);
size_t length = packet.req_length;
struct fs_file *f = mapping->m_file;
switch (mapping->m_type) {
case FILE_MAPPING_PRIVATE:
queue_delete(&f->f_mappings, &mapping->m_entry);
break;
default:
break;
}
kern_handle_close(mapping->m_vmo);
fs_context_free(ctx, mapping);
fs_context_unref_file(ctx, f);
return FS_SUCCESS;
}
static enum fs_status handle_vm_request_read(
struct fs_context *ctx,
equeue_packet_vm_request_t *packet,
struct file_mapping *mapping)
{
kern_tracef(
"received vm request (read) [%zx-%zx] for file %s",
packet->req_offset,
packet->req_offset + packet->req_length,
mapping ? mapping->m_file->f_dent->d_name : "NULL");
if (!mapping) {
return FS_ERR_INTERNAL_FAILURE;
}
size_t length = packet->req_length;
if (length > TEMP_OBJECT_SIZE) {
length = TEMP_OBJECT_SIZE;
}
@@ -189,7 +254,7 @@ static enum fs_status handle_page_request(struct fs_context *ctx)
enum fs_status status = fs_file_read_at(
mapping->m_file,
&buf,
packet.req_offset,
packet->req_offset,
length);
if (status != FS_SUCCESS) {
kern_tracef("map-read failed with code %d", status);
@@ -199,10 +264,85 @@ static enum fs_status handle_page_request(struct fs_context *ctx)
vm_controller_supply_pages(
ctx->ctx_vm_controller,
mapping->m_vmo,
packet.req_offset,
packet->req_offset,
ctx->ctx_temp_object,
0,
packet.req_length);
packet->req_length);
return FS_SUCCESS;
}
static enum fs_status handle_vm_request_attach(
struct fs_context *ctx,
equeue_packet_vm_request_t *packet)
{
struct file_mapping *src_mapping
= (struct file_mapping *)packet->req_src_vmo;
kern_logf(
"received attach request [%zx] for cow-duplicate of %s",
packet->req_id,
src_mapping->m_file->f_dent->d_name);
if (src_mapping->m_type == FILE_MAPPING_SHARED) {
kern_logf("cannot attach another shared mapping to file");
return FS_ERR_INVALID_ARGUMENT;
}
kern_handle_t new_vmo = KERN_HANDLE_INVALID;
kern_status_t status = vm_controller_prepare_attach(
ctx->ctx_vm_controller,
packet->req_id,
&new_vmo);
if (status != KERN_OK) {
kern_logf("vm_controller_prepare_attach failed (%d)", status);
return FS_ERR_INTERNAL_FAILURE;
}
struct file_mapping *new_mapping
= fs_context_alloc(ctx, sizeof *new_mapping);
if (!new_mapping) {
return FS_ERR_NO_MEMORY;
}
memset(new_mapping, 0x0, sizeof *new_mapping);
new_mapping->m_vmo = new_vmo;
new_mapping->m_type = src_mapping->m_type;
new_mapping->m_file = src_mapping->m_file;
queue_push_back(
&new_mapping->m_file->f_mappings,
&new_mapping->m_entry);
vm_controller_finish_attach(
ctx->ctx_vm_controller,
packet->req_id,
(equeue_key_t)new_mapping);
return FS_SUCCESS;
}
static enum fs_status handle_vm_request(struct fs_context *ctx)
{
equeue_packet_vm_request_t packet;
kern_status_t status
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
if (status != KERN_OK) {
return FS_ERR_INTERNAL_FAILURE;
}
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
switch (packet.req_type) {
case VM_REQUEST_READ:
return handle_vm_request_read(ctx, &packet, mapping);
case VM_REQUEST_DETACH:
return handle_vm_request_detach(ctx, &packet, mapping);
case VM_REQUEST_ATTACH:
return handle_vm_request_attach(ctx, &packet);
default:
kern_logf("unknown vm request type %zx", packet.req_type);
break;
}
return FS_SUCCESS;
}
@@ -230,7 +370,7 @@ enum fs_status fs_context_handle_request(struct fs_context *ctx)
}
if (waiters[1].w_observed & VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED) {
return handle_page_request(ctx);
return handle_vm_request(ctx);
}
return FS_SUCCESS;
@@ -259,8 +399,26 @@ struct fs_file *fs_context_get_file(struct fs_context *ctx, unsigned long id)
return get_file(&ctx->ctx_filelist, id);
}
void fs_context_unref_file(struct fs_context *ctx, struct fs_file *f)
{
if (f->f_ref > 1) {
kern_tracef(
"reference to file '%s' has been closed",
f->f_dent->d_name);
f->f_ref--;
return;
}
kern_tracef("file '%s' has been closed", f->f_dent->d_name);
fs_context_free(ctx, f);
}
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
{
if (f->f_id) {
btree_delete(&ctx->ctx_filelist, &f->f_node);
f->f_id = 0;
}
}
static size_t get_first_path_component(const char *in, char *out, size_t max)
+17
View File
@@ -1,5 +1,10 @@
#include "file.h"
void fs_file_set_ops(struct fs_file *f, const struct fs_file_ops *ops)
{
f->f_ops = ops;
}
struct fs_inode *fs_file_get_inode(const struct fs_file *f)
{
return f->f_inode;
@@ -52,3 +57,15 @@ enum fs_status fs_file_write(
f->f_seek = seek;
return status;
}
enum fs_status fs_file_readdir(struct fs_file *f, struct xpc_buffer *buf)
{
if (!f->f_ops || !f->f_ops->f_readdir) {
return FS_ERR_NOT_IMPLEMENTED;
}
off_t seek = f->f_seek;
enum fs_status status = f->f_ops->f_readdir(f, buf, &seek);
f->f_seek = seek;
return status;
}
+3
View File
@@ -9,6 +9,9 @@
#include <fs/inode.h>
struct fs_file {
/* reference count includes the file descriptor, and any vm-objects
* attached to the file */
unsigned int f_ref;
/* id of the open file, equal to the koid of the port being used to
* access the file */
unsigned long f_id;
+1
View File
@@ -42,6 +42,7 @@ extern struct fs_file *fs_context_open_file(
extern struct fs_file *fs_context_get_file(
struct fs_context *ctx,
unsigned long id);
extern void fs_context_unref_file(struct fs_context *ctx, struct fs_file *f);
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
extern enum fs_status fs_context_resolve_path(

Some files were not shown because too many files have changed in this diff Show More