Compare commits
61 Commits
b975256cb9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1674c8dbb2 | |||
| 538904b7e4 | |||
| 58e99b046d | |||
| 55f755e7d9 | |||
| 1c6ece7b55 | |||
| 70e990a885 | |||
| 4fbc6b9027 | |||
| 4beab43728 | |||
| f290ebcd84 | |||
| 7aea4e0206 | |||
| a15ebef9c7 | |||
| 89c8f96829 | |||
| 809f19ebe7 | |||
| 6c80d375f2 | |||
| 109ee7b79c | |||
| b5b95c661e | |||
| 5dcc190f02 | |||
| 19683dbaa8 | |||
| f5c3d885ec | |||
| c64abb9bbc | |||
| a11188b6bf | |||
| 5b996585d4 | |||
| 466af317b2 | |||
| 0d97fe2340 | |||
| 902537ad52 | |||
| 07d5b4852c | |||
| b07acb3cdf | |||
| 0e3f010713 | |||
| 92aaa5439b | |||
| 648a7e2dfb | |||
| 4b6099584b | |||
| 30dd0e753d | |||
| fdd83287fc | |||
| 5a0e7bf14f | |||
| 15ebe38b69 | |||
| 0ef481c30f | |||
| b82e8012d6 | |||
| cc026e0f61 | |||
| 6a928ec0ab | |||
| 3be9c022e0 | |||
| d2e0fa79fa | |||
| 70d32cd592 | |||
| 2f01138416 | |||
| f70d64759f | |||
| 8ebf44dca9 | |||
| f2e6e7785d | |||
| f6993553cd | |||
| 3a9539adbc | |||
| 28d986c628 | |||
| 3bd5899ece | |||
| 548387c43a | |||
| f2e650d368 | |||
| c6ca934852 | |||
| 0a231d2179 | |||
| 40682810ab | |||
| 36a486cca6 | |||
| 0d16c300e7 | |||
| 4057e77512 | |||
| d53bbbb460 | |||
| 6787f28728 | |||
| 96784f611f |
+176
@@ -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"
|
||||||
@@ -4,3 +4,6 @@
|
|||||||
[submodule "sys/ropkg"]
|
[submodule "sys/ropkg"]
|
||||||
path = sys/ropkg
|
path = sys/ropkg
|
||||||
url = git@github.com:washh/ropkg.git
|
url = git@github.com:washh/ropkg.git
|
||||||
|
[submodule "lib/libfx"]
|
||||||
|
path = lib/libfx
|
||||||
|
url = https://g.wash.red/wash/fx.git
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 4.0)
|
cmake_minimum_required(VERSION 3.31)
|
||||||
project(Rosetta C CXX ASM)
|
project(Rosetta C CXX ASM)
|
||||||
|
|
||||||
include(CheckPIESupported)
|
include(CheckPIESupported)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ find_program(C_COMPILER x86_64-elf-gcc REQUIRED)
|
|||||||
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
||||||
#find_program(ASM_COMPILER x86_64-elf-as 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_C_COMPILER ${C_COMPILER})
|
||||||
set(CMAKE_CXX_COMPILER ${CXX_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_CXX_OUTPUT_EXTENSION .o)
|
||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||||
|
|
||||||
|
link_libraries(-lgcc)
|
||||||
|
|||||||
@@ -122,3 +122,14 @@ elseif (GDB)
|
|||||||
DEPENDS ${image_cdrom})
|
DEPENDS ${image_cdrom})
|
||||||
endif ()
|
endif ()
|
||||||
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,4 +1,4 @@
|
|||||||
find_program(GRUB_MKRESCUE grub-mkrescue)
|
find_program(GRUB_MKRESCUE NAMES grub-mkrescue grub2-mkrescue)
|
||||||
|
|
||||||
if (GRUB_MKRESCUE)
|
if (GRUB_MKRESCUE)
|
||||||
message(STATUS "GRUB: Found grub-mkrescue. Bootable CD-ROM image creation is enabled")
|
message(STATUS "GRUB: Found grub-mkrescue. Bootable CD-ROM image creation is enabled")
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
# configuration file generated by Bochs
|
# 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
|
config_interface: textconfig
|
||||||
display_library: sdl2
|
display_library: sdl2
|
||||||
memory: guest=128, host=128, block_size=128
|
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
|
boot: cdrom
|
||||||
floppy_bootsig_check: disabled=0
|
floppy_bootsig_check: disabled=0
|
||||||
floppya: type=1_44
|
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
|
print_timestamps: enabled=0
|
||||||
debugger_log: -
|
debugger_log: -
|
||||||
magic_break: enabled=1 0x0
|
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
|
iodebug: all_rings=0
|
||||||
private_colormap: enabled=0
|
private_colormap: enabled=0
|
||||||
clock: sync=none, time0=local, rtc_sync=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
|
speaker: enabled=true, mode=system
|
||||||
parport1: enabled=true, file=none
|
parport1: enabled=true, file=none
|
||||||
parport2: enabled=false
|
parport2: enabled=false
|
||||||
com1: enabled=true, mode=null
|
com1: enabled=true, mode=file, dev=kernel.log
|
||||||
com2: enabled=false
|
com2: enabled=false
|
||||||
com3: enabled=false
|
com3: enabled=false
|
||||||
com4: enabled=false
|
com4: enabled=false
|
||||||
|
|||||||
@@ -24,13 +24,10 @@ def successful_boot(boot_log, out):
|
|||||||
log(out, "Kernel rebooted during test!")
|
log(out, "Kernel rebooted during test!")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
nr_finish = boot_log.count("ld finished")
|
nr_finish = boot_log.count("exiting (Inappropriate file type or format)")
|
||||||
if nr_finish == 0:
|
if nr_finish != 2:
|
||||||
log(out, "Didn't reach end of boot sequence!")
|
log(out, "Didn't reach end of boot sequence!")
|
||||||
return 1
|
return 1
|
||||||
if nr_finish > 1:
|
|
||||||
log(out, "Boot sequence performed multiple times!")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -34,15 +34,10 @@ initrd=$5
|
|||||||
while true; do
|
while true; do
|
||||||
log "Test $count"
|
log "Test $count"
|
||||||
result_file="$log_dir/$count.log"
|
result_file="$log_dir/$count.log"
|
||||||
$qemu \
|
ninja run-cdrom-bochs > $result_file &
|
||||||
-kernel $kernel \
|
|
||||||
-initrd $initrd \
|
|
||||||
-serial file:$result_file \
|
|
||||||
-cpu qemu64,+rdrand \
|
|
||||||
--append kernel.early-console=ttyS0 -s > /dev/null &
|
|
||||||
qemu_id=$!
|
qemu_id=$!
|
||||||
|
|
||||||
sleep 1.2
|
sleep 5
|
||||||
|
|
||||||
$python $validation_script successful-boot $result_file $logfile
|
$python $validation_script successful-boot $result_file $logfile
|
||||||
result=$?
|
result=$?
|
||||||
@@ -54,12 +49,9 @@ while true; do
|
|||||||
else
|
else
|
||||||
mv $result_file "$result_file.FAIL"
|
mv $result_file "$result_file.FAIL"
|
||||||
fail=$fail+1
|
fail=$fail+1
|
||||||
lldb \
|
|
||||||
-o "file kernel/mango_kernel.debug" \
|
|
||||||
-o "gdb-remote localhost:1234"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
kill -INT $qemu_id
|
killall -9 bochs
|
||||||
|
|
||||||
log "---------------"
|
log "---------------"
|
||||||
log "Total tests: $count"
|
log "Total tests: $count"
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
menuentry "Rosetta" {
|
set timeout_style=menu
|
||||||
multiboot /boot/mango_kernel
|
set timeout=0
|
||||||
module /boot/rosetta-system.bsp
|
|
||||||
boot
|
|
||||||
}
|
|
||||||
|
|
||||||
menuentry "Rosetta (Serial Log)" {
|
menuentry "Rosetta (Serial Log)" {
|
||||||
multiboot /boot/mango_kernel kernel.early-console=ttyS0
|
multiboot /boot/mango_kernel kernel.early-console=ttyS0
|
||||||
|
|||||||
+1
-1
Submodule kernel updated: a0a6a061a4...278fe39c0d
@@ -1,5 +1,9 @@
|
|||||||
file(GLOB items *)
|
file(GLOB items *)
|
||||||
|
|
||||||
|
set(fx_modules core ds serial)
|
||||||
|
set(fx_enable_floating_point 0)
|
||||||
|
set(fx_enable_tests 0)
|
||||||
|
|
||||||
add_subdirectory(
|
add_subdirectory(
|
||||||
${CMAKE_SOURCE_DIR}/kernel/libmango
|
${CMAKE_SOURCE_DIR}/kernel/libmango
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/libmango)
|
${CMAKE_CURRENT_BINARY_DIR}/libmango)
|
||||||
@@ -24,3 +28,22 @@ foreach(item ${items})
|
|||||||
|
|
||||||
add_subdirectory(${item})
|
add_subdirectory(${item})
|
||||||
endforeach (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)
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ bsp_add_library(
|
|||||||
NAME libc
|
NAME libc
|
||||||
LIB_DIR /usr/lib)
|
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)
|
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
||||||
|
|
||||||
add_subdirectory(pthread)
|
add_subdirectory(pthread)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs stdio string errno)
|
set(source_dirs assert stdio stdlib string errno ctype wctype)
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern void __libc_assert_failed(
|
||||||
|
const char *file,
|
||||||
|
int line,
|
||||||
|
const char *func,
|
||||||
|
const char *cond)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
int isalpha(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c >= 'A' && c <= 'A') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
int isdigit(int c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
int isspace(int c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case ' ':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
int isupper(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
int tolower(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
return (c - 'A') + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
int toupper(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
return (c - 'a') + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <mango/status.h>
|
#include <mango/status.h>
|
||||||
|
|
||||||
static int __errno = 32;
|
static int __errno = SUCCESS;
|
||||||
|
|
||||||
int __attribute__((weak)) * __errno_location(void)
|
int __attribute__((weak)) * __errno_location(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -118,7 +118,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// output function type
|
// output function type
|
||||||
typedef void (
|
typedef int (
|
||||||
*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);
|
*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);
|
||||||
|
|
||||||
// wrapper (used as buffer) for output function type
|
// wrapper (used as buffer) for output function type
|
||||||
@@ -128,7 +128,7 @@ typedef struct {
|
|||||||
} out_fct_wrap_type;
|
} out_fct_wrap_type;
|
||||||
|
|
||||||
// internal buffer output
|
// internal buffer output
|
||||||
static inline void _out_buffer(
|
static inline int _out_buffer(
|
||||||
char character,
|
char character,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t idx,
|
size_t idx,
|
||||||
@@ -137,10 +137,12 @@ static inline void _out_buffer(
|
|||||||
if (idx < maxlen) {
|
if (idx < maxlen) {
|
||||||
((char *)buffer)[idx] = character;
|
((char *)buffer)[idx] = character;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal null output
|
// internal null output
|
||||||
static inline void _out_null(
|
static inline int _out_null(
|
||||||
char character,
|
char character,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t idx,
|
size_t idx,
|
||||||
@@ -150,10 +152,11 @@ static inline void _out_null(
|
|||||||
(void)buffer;
|
(void)buffer;
|
||||||
(void)idx;
|
(void)idx;
|
||||||
(void)maxlen;
|
(void)maxlen;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal output function wrapper
|
// internal output function wrapper
|
||||||
static inline void _out_fct(
|
static inline int _out_fct(
|
||||||
char character,
|
char character,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
size_t idx,
|
size_t idx,
|
||||||
@@ -166,6 +169,8 @@ static inline void _out_fct(
|
|||||||
((out_fct_wrap_type *)buffer)
|
((out_fct_wrap_type *)buffer)
|
||||||
->fct(character, ((out_fct_wrap_type *)buffer)->arg);
|
->fct(character, ((out_fct_wrap_type *)buffer)->arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal secure strlen
|
// 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);
|
return _vsnprintf(_out_buffer, buffer, count, format, va);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fctprintf(
|
int __libc_fctprintf(
|
||||||
void (*out)(char character, void *arg),
|
void (*out)(char character, void *arg),
|
||||||
void *arg,
|
void *arg,
|
||||||
const char *format,
|
const char *format,
|
||||||
...)
|
va_list va)
|
||||||
{
|
{
|
||||||
va_list va;
|
|
||||||
va_start(va, format);
|
|
||||||
const out_fct_wrap_type out_fct_wrap = {out, arg};
|
const out_fct_wrap_type out_fct_wrap = {out, arg};
|
||||||
const int ret = _vsnprintf(
|
return _vsnprintf(
|
||||||
_out_fct,
|
_out_fct,
|
||||||
(char *)(uintptr_t)&out_fct_wrap,
|
(char *)(uintptr_t)&out_fct_wrap,
|
||||||
(size_t)-1,
|
(size_t)-1,
|
||||||
format,
|
format,
|
||||||
va);
|
va);
|
||||||
va_end(va);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
|||||||
|
#include <mango/task.h>
|
||||||
|
|
||||||
|
void abort(void)
|
||||||
|
{
|
||||||
|
task_exit(-1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
int atexit(void (*func)(void))
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include <mango/task.h>
|
||||||
|
|
||||||
|
void exit(int code)
|
||||||
|
{
|
||||||
|
task_exit(code);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <mango/log.h>
|
#include <mango/log.h>
|
||||||
#include <rosetta/bootstrap.h>
|
#include <rosetta/bootstrap.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
extern int main(int, const char **, const char **);
|
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)
|
int __libc_init(const struct rosetta_bootstrap *bsinfo)
|
||||||
{
|
{
|
||||||
(volatile void)pthread_self();
|
(volatile void)pthread_self();
|
||||||
kern_logf("bsinfo = %p", bsinfo);
|
__set_errno(SUCCESS);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
int iswnumber(wchar_t c)
|
||||||
|
{
|
||||||
|
/* TODO locale support */
|
||||||
|
return isdigit((int)c);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
int iswpunct(wchar_t c)
|
||||||
|
{
|
||||||
|
/* TODO locale support */
|
||||||
|
return ispunct((int)c);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
int iswspace(wchar_t c)
|
||||||
|
{
|
||||||
|
/* TODO locale support */
|
||||||
|
return isspace((int)c);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
int iswxdigit(wchar_t c)
|
||||||
|
{
|
||||||
|
/* TODO locale support */
|
||||||
|
return isxdigit((int)c);
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef DIRENT_H_
|
#ifndef DIRENT_H_
|
||||||
#define DIRENT_H_
|
#define DIRENT_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define DT_UNKNOWN 0
|
#define DT_UNKNOWN 0
|
||||||
#define DT_BLK 1
|
#define DT_BLK 1
|
||||||
#define DT_CHR 2
|
#define DT_CHR 2
|
||||||
@@ -10,4 +12,22 @@
|
|||||||
#define DT_REG 6
|
#define DT_REG 6
|
||||||
#define DT_SOCK 7
|
#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
|
#endif
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -3,11 +3,28 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define EOF -1
|
||||||
|
|
||||||
|
#define _IONBF 0
|
||||||
|
#define _IOFBF 1
|
||||||
|
#define _IOLBF 2
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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 snprintf(char *buffer, size_t count, const char *format, ...);
|
||||||
extern int vsnprintf(
|
extern int vsnprintf(
|
||||||
char *buffer,
|
char *buffer,
|
||||||
@@ -15,6 +32,48 @@ extern int vsnprintf(
|
|||||||
const char *format,
|
const char *format,
|
||||||
va_list va);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,10 +4,27 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
extern void abort(void);
|
extern void abort(void);
|
||||||
|
extern void exit(int result);
|
||||||
|
extern int atexit(void (*func)(void));
|
||||||
|
|
||||||
extern void *malloc(size_t count);
|
extern void *malloc(size_t count);
|
||||||
extern void *calloc(size_t count, size_t size);
|
extern void *calloc(size_t count, size_t size);
|
||||||
extern void *realloc(void *p, size_t count);
|
extern void *realloc(void *p, size_t count);
|
||||||
extern void free(void *p);
|
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
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ extern const char *strerror_code(int errnum);
|
|||||||
|
|
||||||
extern size_t strlen(const char *s);
|
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 strcmp(const char *s1, const char *s2);
|
||||||
extern int strncmp(const char *s1, const char *s2, unsigned long n);
|
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 *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 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);
|
extern char *strdup(char *s);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#define SEEK_CUR 1
|
#define SEEK_CUR 1
|
||||||
#define SEEK_END 2
|
#define SEEK_END 2
|
||||||
|
|
||||||
|
typedef size_t ino_t;
|
||||||
|
|
||||||
struct dentry {
|
struct dentry {
|
||||||
unsigned long d_ino;
|
unsigned long d_ino;
|
||||||
unsigned short d_reclen;
|
unsigned short d_reclen;
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef TIME_H_
|
||||||
|
#define TIME_H_
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
int feof(struct __opaque_file *stream)
|
||||||
|
{
|
||||||
|
return (stream->f_flags & FILE_EOF) != 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
int ferror(struct __opaque_file *stream)
|
||||||
|
{
|
||||||
|
return (stream->f_flags & FILE_ERR) != 0;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
int fprintf(struct __opaque_file *stream, const char *format, ...)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
long ftell(struct __opaque_file *stream)
|
||||||
|
{
|
||||||
|
return lseek(stream->f_fd, 0, SEEK_CUR);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -25,6 +25,21 @@ static vm_prot_t vm_prot_from_mmap_prot(int prot)
|
|||||||
return vm_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(
|
static int get_vmo_anon(
|
||||||
int fd,
|
int fd,
|
||||||
int prot,
|
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_status_t status = KERN_OK;
|
||||||
kern_handle_t self = KERN_HANDLE_INVALID,
|
kern_handle_t self = KERN_HANDLE_INVALID,
|
||||||
address_space = KERN_HANDLE_INVALID;
|
address_space = KERN_HANDLE_INVALID;
|
||||||
|
vm_flags_t vm_flags = vm_flags_from_mmap_flags(flags);
|
||||||
|
|
||||||
status = task_self(&self);
|
status = task_self(&self);
|
||||||
if (status != KERN_OK) {
|
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,
|
vmo,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
|
vm_flags,
|
||||||
vm_prot,
|
vm_prot,
|
||||||
&map_address);
|
&map_address);
|
||||||
} else {
|
} else {
|
||||||
@@ -155,6 +172,7 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
|
|||||||
vmo,
|
vmo,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
|
vm_flags,
|
||||||
vm_prot,
|
vm_prot,
|
||||||
&map_address);
|
&map_address);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ static kern_status_t expand_heap(heap_t *heap)
|
|||||||
vmo,
|
vmo,
|
||||||
0,
|
0,
|
||||||
HEAP_EXPAND_INCREMENT,
|
HEAP_EXPAND_INCREMENT,
|
||||||
|
VM_PRIVATE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&base);
|
&base);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef PTHREAD_H_
|
#ifndef PTHREAD_H_
|
||||||
#define PTHREAD_H_
|
#define PTHREAD_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
#define __PTHREAD_ATTR_SIZE__ 32
|
#define __PTHREAD_ATTR_SIZE__ 32
|
||||||
|
|
||||||
typedef struct __pthread *pthread_t;
|
typedef struct __pthread *pthread_t;
|
||||||
@@ -10,6 +12,10 @@ typedef struct __pthread_attr {
|
|||||||
char __opaque[__PTHREAD_ATTR_SIZE__];
|
char __opaque[__PTHREAD_ATTR_SIZE__];
|
||||||
} pthread_attr_t;
|
} pthread_attr_t;
|
||||||
|
|
||||||
|
typedef struct __pthread_mutex {
|
||||||
|
kern_futex_t __v;
|
||||||
|
} pthread_mutex_t;
|
||||||
|
|
||||||
extern int __pthread_init(void);
|
extern int __pthread_init(void);
|
||||||
|
|
||||||
extern int pthread_create(
|
extern int pthread_create(
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ __pthread_unmap_exit:
|
|||||||
syscall
|
syscall
|
||||||
|
|
||||||
/* next, close the handle to the address space */
|
/* next, close the handle to the address space */
|
||||||
mov $SYS_THREAD_EXIT, %rax
|
mov $SYS_KERN_HANDLE_CLOSE, %rax
|
||||||
mov %rbx, %rdi
|
mov %rbx, %rdi
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
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 libmango interface::fs libc libxpc)
|
||||||
target_link_libraries(libfs-static libmango interface::fs libc-core libxpc-static)
|
target_link_libraries(libfs-static libmango interface::fs libc-core libxpc-static)
|
||||||
|
|
||||||
|
|||||||
+93
-21
@@ -73,6 +73,7 @@ struct fs_context *fs_context_create(struct fs_allocator *alloc)
|
|||||||
ctx->ctx_temp_object,
|
ctx->ctx_temp_object,
|
||||||
0,
|
0,
|
||||||
TEMP_OBJECT_SIZE,
|
TEMP_OBJECT_SIZE,
|
||||||
|
VM_PRIVATE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&temp_buffer);
|
&temp_buffer);
|
||||||
kern_handle_close(address_space);
|
kern_handle_close(address_space);
|
||||||
@@ -145,13 +146,15 @@ static enum fs_status handle_event(struct fs_context *ctx, xpc_msg_t *msg)
|
|||||||
{
|
{
|
||||||
switch (msg->msg_event) {
|
switch (msg->msg_event) {
|
||||||
case KERN_MSG_EVENT_CONNECTION:
|
case KERN_MSG_EVENT_CONNECTION:
|
||||||
kern_logf("received connection");
|
kern_tracef("received connection");
|
||||||
break;
|
break;
|
||||||
case KERN_MSG_EVENT_DISCONNECTION: {
|
case KERN_MSG_EVENT_DISCONNECTION: {
|
||||||
|
kern_tracef("received disconnect");
|
||||||
struct fs_file *f
|
struct fs_file *f
|
||||||
= fs_context_get_file(ctx, msg->msg_sender.e_port);
|
= fs_context_get_file(ctx, msg->msg_sender.e_port);
|
||||||
if (f) {
|
if (f) {
|
||||||
fs_context_close_file(ctx, f);
|
fs_context_close_file(ctx, f);
|
||||||
|
fs_context_unref_file(ctx, f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -195,13 +198,20 @@ static enum fs_status handle_msg(struct fs_context *ctx)
|
|||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fs_status handle_page_request_detach(
|
static enum fs_status handle_vm_request_detach(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
equeue_packet_page_request_t *packet,
|
equeue_packet_vm_request_t *packet,
|
||||||
struct file_mapping *mapping)
|
struct file_mapping *mapping)
|
||||||
{
|
{
|
||||||
|
if (!mapping) {
|
||||||
kern_logf(
|
kern_logf(
|
||||||
"received page request (detach) for file %s",
|
"received DETACH request from VMO with no associated "
|
||||||
|
"mapping");
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_tracef(
|
||||||
|
"received vm request (detach) for file %s",
|
||||||
mapping->m_file->f_dent->d_name);
|
mapping->m_file->f_dent->d_name);
|
||||||
|
|
||||||
struct fs_file *f = mapping->m_file;
|
struct fs_file *f = mapping->m_file;
|
||||||
@@ -216,20 +226,23 @@ static enum fs_status handle_page_request_detach(
|
|||||||
kern_handle_close(mapping->m_vmo);
|
kern_handle_close(mapping->m_vmo);
|
||||||
fs_context_free(ctx, mapping);
|
fs_context_free(ctx, mapping);
|
||||||
|
|
||||||
fs_context_close_file(ctx, f);
|
fs_context_unref_file(ctx, f);
|
||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fs_status handle_page_request_read(
|
static enum fs_status handle_vm_request_read(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
equeue_packet_page_request_t *packet,
|
equeue_packet_vm_request_t *packet,
|
||||||
struct file_mapping *mapping)
|
struct file_mapping *mapping)
|
||||||
{
|
{
|
||||||
kern_tracef(
|
kern_tracef(
|
||||||
"received page request (read) [%zx-%zx] for file %s",
|
"received vm request (read) [%zx-%zx] for file %s",
|
||||||
packet->req_offset,
|
packet->req_offset,
|
||||||
packet->req_offset + packet->req_length,
|
packet->req_offset + packet->req_length,
|
||||||
mapping->m_file->f_dent->d_name);
|
mapping ? mapping->m_file->f_dent->d_name : "NULL");
|
||||||
|
if (!mapping) {
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
size_t length = packet->req_length;
|
size_t length = packet->req_length;
|
||||||
if (length > TEMP_OBJECT_SIZE) {
|
if (length > TEMP_OBJECT_SIZE) {
|
||||||
@@ -258,25 +271,76 @@ static enum fs_status handle_page_request_read(
|
|||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fs_status handle_page_request(struct fs_context *ctx)
|
static enum fs_status handle_vm_request_attach(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
equeue_packet_vm_request_t *packet)
|
||||||
{
|
{
|
||||||
equeue_packet_page_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
|
kern_status_t status
|
||||||
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
|
= vm_controller_recv(ctx->ctx_vm_controller, &packet);
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
return KERN_BAD_STATE;
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
|
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
|
||||||
|
|
||||||
switch (packet.req_type) {
|
switch (packet.req_type) {
|
||||||
case PAGE_REQUEST_READ:
|
case VM_REQUEST_READ:
|
||||||
return handle_page_request_read(ctx, &packet, mapping);
|
return handle_vm_request_read(ctx, &packet, mapping);
|
||||||
case PAGE_REQUEST_DETACH:
|
case VM_REQUEST_DETACH:
|
||||||
return handle_page_request_detach(ctx, &packet, mapping);
|
return handle_vm_request_detach(ctx, &packet, mapping);
|
||||||
|
case VM_REQUEST_ATTACH:
|
||||||
|
return handle_vm_request_attach(ctx, &packet);
|
||||||
default:
|
default:
|
||||||
kern_logf("unknown page request type %zx", packet.req_type);
|
kern_logf("unknown vm request type %zx", packet.req_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
@@ -306,7 +370,7 @@ enum fs_status fs_context_handle_request(struct fs_context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (waiters[1].w_observed & VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED) {
|
if (waiters[1].w_observed & VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED) {
|
||||||
return handle_page_request(ctx);
|
return handle_vm_request(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FS_SUCCESS;
|
return FS_SUCCESS;
|
||||||
@@ -335,18 +399,26 @@ struct fs_file *fs_context_get_file(struct fs_context *ctx, unsigned long id)
|
|||||||
return get_file(&ctx->ctx_filelist, id);
|
return get_file(&ctx->ctx_filelist, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
void fs_context_unref_file(struct fs_context *ctx, struct fs_file *f)
|
||||||
{
|
{
|
||||||
if (f->f_ref > 1) {
|
if (f->f_ref > 1) {
|
||||||
kern_logf(
|
kern_tracef(
|
||||||
"reference to file '%s' has been closed",
|
"reference to file '%s' has been closed",
|
||||||
f->f_dent->d_name);
|
f->f_dent->d_name);
|
||||||
f->f_ref--;
|
f->f_ref--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_logf("file '%s' has been closed", f->f_dent->d_name);
|
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);
|
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)
|
static size_t get_first_path_component(const char *in, char *out, size_t max)
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
#include "file.h"
|
#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)
|
struct fs_inode *fs_file_get_inode(const struct fs_file *f)
|
||||||
{
|
{
|
||||||
return f->f_inode;
|
return f->f_inode;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ extern struct fs_file *fs_context_open_file(
|
|||||||
extern struct fs_file *fs_context_get_file(
|
extern struct fs_file *fs_context_get_file(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
unsigned long id);
|
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 void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
||||||
|
|
||||||
extern enum fs_status fs_context_resolve_path(
|
extern enum fs_status fs_context_resolve_path(
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ struct fs_file_ops {
|
|||||||
*f_readdir)(struct fs_file *, struct xpc_buffer *, off_t *);
|
*f_readdir)(struct fs_file *, struct xpc_buffer *, off_t *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void fs_file_set_ops(struct fs_file *f, const struct fs_file_ops *ops);
|
||||||
extern struct fs_inode *fs_file_get_inode(const struct fs_file *f);
|
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 size_t fs_file_get_cursor(const struct fs_file *f);
|
||||||
extern enum fs_status fs_file_read(
|
extern enum fs_status fs_file_read(
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <mango/handle.h>
|
#include <mango/handle.h>
|
||||||
#include <mango/log.h>
|
#include <mango/log.h>
|
||||||
#include <mango/vm.h>
|
#include <mango/vm.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
static int create_file_mapping(
|
static int create_file_mapping(
|
||||||
@@ -104,7 +103,13 @@ extern kern_status_t fs_msg_map(
|
|||||||
mapping->m_vmo);
|
mapping->m_vmo);
|
||||||
|
|
||||||
kern_handle_t vmo;
|
kern_handle_t vmo;
|
||||||
kern_handle_duplicate(mapping->m_vmo, &vmo);
|
kern_handle_transfer(
|
||||||
|
KERN_HANDLE_INVALID,
|
||||||
|
mapping->m_vmo,
|
||||||
|
KERN_HANDLE_INVALID,
|
||||||
|
KERN_HANDLE_INVALID,
|
||||||
|
HANDLE_TRANSFER_COPY,
|
||||||
|
&vmo);
|
||||||
f->f_ref++;
|
f->f_ref++;
|
||||||
|
|
||||||
*out_err = SUCCESS;
|
*out_err = SUCCESS;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ extern kern_status_t fs_msg_seek(
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_offset > f->f_inode->i_size) {
|
if (f->f_inode && new_offset > f->f_inode->i_size) {
|
||||||
*out_err = EINVAL;
|
*out_err = EINVAL;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule
+1
Submodule lib/libfx added at cb39baa233
@@ -8,7 +8,7 @@ set(public_include_dirs
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
rosetta_add_library(
|
rosetta_add_library(
|
||||||
NAME liblaunch STATIC
|
NAME liblaunch SHARED STATIC
|
||||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
SOURCES ${sources}
|
SOURCES ${sources}
|
||||||
HEADERS ${headers})
|
HEADERS ${headers})
|
||||||
@@ -17,5 +17,9 @@ sysroot_add_library(
|
|||||||
NAME liblaunch
|
NAME liblaunch
|
||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
bsp_add_library(
|
||||||
|
NAME liblaunch
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(liblaunch PRIVATE librosetta libmango libc-core)
|
target_link_libraries(liblaunch-static PRIVATE librosetta libmango libc-core)
|
||||||
|
target_link_libraries(liblaunch PRIVATE librosetta libmango libc)
|
||||||
|
|||||||
+7
-3
@@ -233,13 +233,15 @@ static enum launch_status map_executable(struct elf_image *image)
|
|||||||
|
|
||||||
kern_handle_t vmo = image->e_image;
|
kern_handle_t vmo = image->e_image;
|
||||||
vm_prot_t prot = VM_PROT_USER;
|
vm_prot_t prot = VM_PROT_USER;
|
||||||
|
vm_flags_t flags = VM_SHARED;
|
||||||
size_t offset = phdr.p_offset;
|
size_t offset = phdr.p_offset;
|
||||||
|
|
||||||
phdr.p_flags &PF_R && (prot |= VM_PROT_READ);
|
phdr.p_flags & PF_R && (prot |= VM_PROT_READ);
|
||||||
phdr.p_flags &PF_W && (prot |= VM_PROT_WRITE);
|
phdr.p_flags & PF_W && (prot |= VM_PROT_WRITE);
|
||||||
phdr.p_flags &PF_X && (prot |= VM_PROT_EXEC);
|
phdr.p_flags & PF_X && (prot |= VM_PROT_EXEC);
|
||||||
if (phdr.p_flags & PF_W) {
|
if (phdr.p_flags & PF_W) {
|
||||||
vmo = image->e_data;
|
vmo = image->e_data;
|
||||||
|
flags = VM_PRIVATE;
|
||||||
offset = data_offset;
|
offset = data_offset;
|
||||||
size_t tmp = 0;
|
size_t tmp = 0;
|
||||||
|
|
||||||
@@ -267,6 +269,7 @@ static enum launch_status map_executable(struct elf_image *image)
|
|||||||
vmo,
|
vmo,
|
||||||
offset,
|
offset,
|
||||||
phdr.p_memsz,
|
phdr.p_memsz,
|
||||||
|
flags,
|
||||||
prot,
|
prot,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
@@ -282,6 +285,7 @@ static enum launch_status map_executable(struct elf_image *image)
|
|||||||
vmo,
|
vmo,
|
||||||
offset,
|
offset,
|
||||||
phdr.p_memsz,
|
phdr.p_memsz,
|
||||||
|
flags,
|
||||||
prot,
|
prot,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ struct launch_parameters {
|
|||||||
size_t p_channel_count;
|
size_t p_channel_count;
|
||||||
|
|
||||||
void *p_resolver_arg;
|
void *p_resolver_arg;
|
||||||
|
|
||||||
|
kern_handle_t p_stdio[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct launch_result {
|
struct launch_result {
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ enum launch_status launch_ctx_execute(
|
|||||||
stack_vmo,
|
stack_vmo,
|
||||||
0,
|
0,
|
||||||
STACK_SIZE,
|
STACK_SIZE,
|
||||||
|
VM_PRIVATE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&remote_stack_buf);
|
&remote_stack_buf);
|
||||||
kstatus = address_space_map(
|
kstatus = address_space_map(
|
||||||
@@ -191,6 +192,7 @@ enum launch_status launch_ctx_execute(
|
|||||||
stack_vmo,
|
stack_vmo,
|
||||||
0,
|
0,
|
||||||
STACK_SIZE,
|
STACK_SIZE,
|
||||||
|
VM_PRIVATE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&local_stack_buf);
|
&local_stack_buf);
|
||||||
kern_handle_close(stack_vmo);
|
kern_handle_close(stack_vmo);
|
||||||
@@ -209,6 +211,20 @@ enum launch_status launch_ctx_execute(
|
|||||||
remote_stack_buf + STACK_SIZE);
|
remote_stack_buf + STACK_SIZE);
|
||||||
virt_addr_t bsdata = write_bootstrap_data(&stack, interp_path, params);
|
virt_addr_t bsdata = write_bootstrap_data(&stack, interp_path, params);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (params->p_stdio[i] == KERN_HANDLE_INVALID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_transfer(
|
||||||
|
KERN_HANDLE_INVALID,
|
||||||
|
params->p_stdio[i],
|
||||||
|
remote_task,
|
||||||
|
i,
|
||||||
|
HANDLE_TRANSFER_MOVE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
||||||
|
|
||||||
kern_handle_t thread;
|
kern_handle_t thread;
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ void *stack_writer_put_string(
|
|||||||
w->w_local_sp -= (len + 1);
|
w->w_local_sp -= (len + 1);
|
||||||
w->w_remote_sp -= (len + 1);
|
w->w_remote_sp -= (len + 1);
|
||||||
|
|
||||||
|
w->w_local_sp &= ~0x0F;
|
||||||
|
w->w_remote_sp &= ~0x0F;
|
||||||
|
|
||||||
char *local_ptr = (char *)w->w_local_sp;
|
char *local_ptr = (char *)w->w_local_sp;
|
||||||
virt_addr_t remote_ptr = w->w_remote_sp;
|
virt_addr_t remote_ptr = w->w_remote_sp;
|
||||||
|
|
||||||
@@ -46,6 +49,9 @@ void *stack_writer_put(
|
|||||||
w->w_local_sp -= len;
|
w->w_local_sp -= len;
|
||||||
w->w_remote_sp -= len;
|
w->w_remote_sp -= len;
|
||||||
|
|
||||||
|
w->w_local_sp &= ~0x0F;
|
||||||
|
w->w_remote_sp &= ~0x0F;
|
||||||
|
|
||||||
void *local_ptr = (char *)w->w_local_sp;
|
void *local_ptr = (char *)w->w_local_sp;
|
||||||
virt_addr_t remote_ptr = w->w_remote_sp;
|
virt_addr_t remote_ptr = w->w_remote_sp;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user