mirror of
https://github.com/wiiu-env/libcurlwrapper.git
synced 2024-11-27 07:04:17 +01:00
first commit
This commit is contained in:
commit
77d06110aa
67
.clang-format
Normal file
67
.clang-format
Normal file
@ -0,0 +1,67 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
26
.github/workflows/pr.yml
vendored
Normal file
26
.github/workflows/pr.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: CI-PR
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
||||
build-lib:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: build lib
|
||||
run: |
|
||||
docker build . -t tmp
|
||||
docker build . -f Dockerfile.buildlocal -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: lib
|
||||
path: "lib/*.a"
|
33
.github/workflows/push_image.yml
vendored
Normal file
33
.github/workflows/push_image.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: Publish Docker Image
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Get release version
|
||||
id: get_release_tag
|
||||
run: |
|
||||
echo RELEASE_VERSION=$(echo $(date '+%Y%m%d')) >> $GITHUB_ENV
|
||||
echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//" | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
echo REPOSITORY_OWNER=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $1}' | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
- name: Publish to Registry
|
||||
uses: elgohr/Publish-Docker-Github-Action@master
|
||||
with:
|
||||
name: ${{ env.REPOSITORY_OWNER }}/${{ env.REPOSITORY_NAME }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
snapshot: true
|
||||
cache: true
|
||||
tags: "latest, ${{ env.RELEASE_VERSION }}"
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/*.a
|
||||
/build
|
||||
*.bz2
|
||||
release/
|
||||
lib/
|
||||
CMakeLists.txt
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
share/libfunctionpatcher.ld
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@ -0,0 +1,9 @@
|
||||
FROM wiiuenv/devkitppc:20221228
|
||||
|
||||
WORKDIR tmp_build
|
||||
COPY . .
|
||||
RUN make clean && make && mkdir -p /artifacts/wums && cp -r lib /artifacts/wums
|
||||
WORKDIR /artifacts
|
||||
|
||||
FROM scratch
|
||||
COPY --from=0 /artifacts /artifacts
|
3
Dockerfile.buildlocal
Normal file
3
Dockerfile.buildlocal
Normal file
@ -0,0 +1,3 @@
|
||||
FROM wiiuenv/devkitppc:20221228
|
||||
|
||||
WORKDIR project
|
155
LICENSE
Normal file
155
LICENSE
Normal file
@ -0,0 +1,155 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates the terms
|
||||
and conditions of version 3 of the GNU General Public License, supplemented
|
||||
by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, “this License” refers to version 3 of the GNU Lesser General
|
||||
Public License, and the “GNU GPL” refers to version 3 of the
|
||||
GNU General Public License.
|
||||
|
||||
“The Library” refers to a covered work governed by this License, other than
|
||||
an Application or a Combined Work as defined below.
|
||||
|
||||
An “Application” is any work that makes use of an interface provided by the
|
||||
Library, but which is not otherwise based on the Library. Defining a subclass
|
||||
of a class defined by the Library is deemed a mode of using an interface
|
||||
provided by the Library.
|
||||
|
||||
A “Combined Work” is a work produced by combining or linking an Application
|
||||
with the Library. The particular version of the Library with which the
|
||||
Combined Work was made is also called the “Linked Version”.
|
||||
|
||||
The “Minimal Corresponding Source” for a Combined Work means the Corresponding
|
||||
Source for the Combined Work, excluding any source code for portions of the
|
||||
Combined Work that, considered in isolation, are based on the Application,
|
||||
and not on the Linked Version.
|
||||
|
||||
The “Corresponding Application Code” for a Combined Work means the object code
|
||||
and/or source code for the Application, including any data and utility programs
|
||||
needed for reproducing the Combined Work from the Application, but excluding
|
||||
the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License without
|
||||
being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a facility
|
||||
refers to a function or data to be supplied by an Application that uses the
|
||||
facility (other than as an argument passed when the facility is invoked),
|
||||
then you may convey a copy of the modified version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the function or
|
||||
data, the facility still operates, and performs whatever part of its
|
||||
purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of this
|
||||
License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from a header
|
||||
file that is part of the Library. You may convey such object code under terms
|
||||
of your choice, provided that, if the incorporated material is not limited to
|
||||
numerical parameters, data structure layouts and accessors, or small macros,
|
||||
inline functions and templates (ten or fewer lines in length),
|
||||
you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL
|
||||
and this license document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that, taken together,
|
||||
effectively do not restrict modification of the portions of the Library
|
||||
contained in the Combined Work and reverse engineering for debugging such
|
||||
modifications, if you also do each of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that the
|
||||
Library is used in it and that the Library and its use are covered
|
||||
by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and
|
||||
this license document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during execution,
|
||||
include the copyright notice for the Library among these notices, as well
|
||||
as a reference directing the user to the copies of the GNU GPL
|
||||
and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form suitable
|
||||
for, and under terms that permit, the user to recombine or relink
|
||||
the Application with a modified version of the Linked Version to
|
||||
produce a modified Combined Work, in the manner specified by section 6
|
||||
of the GNU GPL for conveying Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time a
|
||||
copy of the Library already present on the user's computer system,
|
||||
and (b) will operate properly with a modified version of the Library
|
||||
that is interface-compatible with the Linked Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise be
|
||||
required to provide such information under section 6 of the GNU GPL, and
|
||||
only to the extent that such information is necessary to install and
|
||||
execute a modified version of the Combined Work produced by recombining
|
||||
or relinking the Application with a modified version of the Linked Version.
|
||||
(If you use option 4d0, the Installation Information must accompany the
|
||||
Minimal Corresponding Source and Corresponding Application Code. If you
|
||||
use option 4d1, you must provide the Installation Information in the
|
||||
manner specified by section 6 of the GNU GPL for
|
||||
conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the Library side by
|
||||
side in a single library together with other library facilities that are not
|
||||
Applications and are not covered by this License, and convey such a combined
|
||||
library under terms of your choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on
|
||||
the Library, uncombined with any other library facilities, conveyed under
|
||||
the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it is a
|
||||
work based on the Library, and explaining where to find the accompanying
|
||||
uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of the
|
||||
GNU Lesser General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library as you
|
||||
received it specifies that a certain numbered version of the GNU Lesser
|
||||
General Public License “or any later version” applies to it, you have the
|
||||
option of following the terms and conditions either of that published version
|
||||
or of any later version published by the Free Software Foundation. If the
|
||||
Library as you received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser General
|
||||
Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide whether
|
||||
future versions of the GNU Lesser General Public License shall apply, that
|
||||
proxy's public statement of acceptance of any version is permanent
|
||||
authorization for you to choose that version for the Library.
|
161
Makefile
Normal file
161
Makefile
Normal file
@ -0,0 +1,161 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
include $(DEVKITPRO)/wut/share/wut_rules
|
||||
|
||||
export VER_MAJOR := 1
|
||||
export VER_MINOR := 0
|
||||
export VER_PATCH := 0
|
||||
|
||||
VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#-------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := source
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
CFLAGS := -Wall -Werror -save-temps \
|
||||
-ffunction-sections -fdata-sections \
|
||||
$(MACHDEP) \
|
||||
$(BUILD_CFLAGS)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++20
|
||||
|
||||
ASFLAGS := $(MACHDEP)
|
||||
|
||||
LDFLAGS = $(ARCH) -Wl,--gc-sections
|
||||
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUT_ROOT)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(DEFFILES:.def=.o) $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I.
|
||||
|
||||
.PHONY: all dist-bin dist-src dist install clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: lib/libcurlwrapper.a
|
||||
|
||||
dist-bin: all
|
||||
@tar --exclude=*~ -cjf libcurlwrapper-$(VERSION).tar.bz2 lib
|
||||
|
||||
dist-src:
|
||||
@tar --exclude=*~ -cjf libcurlwrapper-src-$(VERSION).tar.bz2 source Makefile
|
||||
|
||||
dist: dist-src dist-bin
|
||||
|
||||
install: dist-bin
|
||||
mkdir -p $(DESTDIR)$(DEVKITPRO)/wums
|
||||
bzip2 -cd libcurlwrapper-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wums
|
||||
|
||||
lib:
|
||||
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||
|
||||
release:
|
||||
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||
|
||||
share/libcurlwrapper.ld :$(SOURCES) $(INCLUDES) | share release
|
||||
mv $(CURDIR)/release/*.ld $(CURDIR)/$@
|
||||
|
||||
lib/libcurlwrapper.a :$(SOURCES) $(INCLUDES) | lib release
|
||||
@$(shell [ ! -d lib ] && mkdir -p lib)
|
||||
@$(shell [ ! -d release ] && mkdir -p release)
|
||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
||||
BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \
|
||||
DEPSDIR=$(CURDIR)/release \
|
||||
--no-print-directory -C release \
|
||||
-f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -rf release lib
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
100
README.md
Normal file
100
README.md
Normal file
@ -0,0 +1,100 @@
|
||||
[![Publish Docker Image](https://github.com/wiiu-env/libcurlwrapper/actions/workflows/push_image.yml/badge.svg)](https://github.com/wiiu-env/libcurlwrapper/actions/workflows/push_image.yml)
|
||||
|
||||
# libcurlwrapper
|
||||
|
||||
This library loads CURL from an Aroma Module instead of statically linking it to the binary. This results in a much smaller binary size (saves about 750KiB).
|
||||
|
||||
- Requires the [CURLWrapperModule](https://github.com/wiiu-env/CURLWrapperModule) to be running via [WUMSLoader](https://github.com/wiiu-env/WUMSLoader).
|
||||
- Requires [wut](https://github.com/devkitPro/wut) for building.
|
||||
- Use with curl 7.84.0 headers, other versions might not be compatible.
|
||||
- See important changes in the Usage section.
|
||||
|
||||
Install via `make install`.
|
||||
|
||||
## Usage
|
||||
|
||||
Make sure to define this in your Makefile:
|
||||
|
||||
```
|
||||
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||
```
|
||||
|
||||
Use the normal curl headers, but link against `-lcurlwrapper` instead. For example replace `-lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lz` with `-lcurlwrapper`.
|
||||
|
||||
**If the CURLWrapperModule is not loaded `curl_global_init` will return a negative value.**
|
||||
|
||||
## Changes compared to normal CURL
|
||||
|
||||
libcurlwrapper tries to be a drop-in replacement for libcurl, but some things need to be considered.
|
||||
|
||||
### All function are only available between calling `curl_global_init` and `curl_global_cleanup`.
|
||||
|
||||
Even functions like `curl_version` only work after calling `curl_global_init`.
|
||||
|
||||
### Calling `curl_easy_init` will automatically add CA certificates.
|
||||
|
||||
It `curl_easy_init` returns success, `curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);` with current CA certificates will be called.
|
||||
These CA certificates are coming from the modules and can be updated in the future.
|
||||
|
||||
### CURLOPT_SOCKOPTFUNCTION
|
||||
|
||||
- The `CURLOPT_SOCKOPTFUNCTION` callback requires a workaround to work properly.
|
||||
- This is caused by `setsockopt` not being compatible with the sockets from the CURLWrapperModule.
|
||||
|
||||
Currently, there are two options to get the correct `setsockopt` function:
|
||||
|
||||
#### Option 1: CURLOPT_SOCKOPTDATA
|
||||
|
||||
- To get a pointer to the correct `setsockopt` function, you have to set the `CURLOPT_SOCKOPTDATA` to 0x13371337.
|
||||
- The `0x13371337` will be replaced with a pointer to the correct `setsockopt` function.
|
||||
|
||||
Example:
|
||||
|
||||
```C
|
||||
static int initSocket(void *ptr, curl_socket_t socket, curlsocktype type) {
|
||||
int r;
|
||||
// If ptr is not our magic value, it got replaced with a pointer to a valid setsockopt function.
|
||||
if ((uint32_t) ptr != 0x13371337) {
|
||||
r = reinterpret_cast<decltype(&setsockopt)>(ptr)(socket, SOL_SOCKET, SO_WINSCALE, &o, sizeof(o));
|
||||
} else {
|
||||
r = setsockopt(socket, SOL_SOCKET, SO_WINSCALE, &o, sizeof(o));
|
||||
}
|
||||
return r == 0 ? CURL_SOCKOPT_OK : CURL_SOCKOPT_ERROR;
|
||||
}
|
||||
[...]
|
||||
// Set socktopt data to a magic value to get a pointer to the correct setsockopt function.
|
||||
curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, 0x13371337);
|
||||
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, initSocket);
|
||||
```
|
||||
|
||||
Downside of this option: the data pointer of `CURLOPT_SOCKOPTFUNCTION` can not be used.
|
||||
|
||||
#### Option 2: curlwrapper_setsockopt
|
||||
|
||||
This lib exposes the function `curlwrapper_setsockopt` which will call the correct function. Because this lib had no headers, you have to
|
||||
declare it in your app like this:
|
||||
|
||||
````C
|
||||
int curlwrapper_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
````
|
||||
|
||||
When using C++, you have to add `extern "C"` at the start.
|
||||
|
||||
Downside of this option: Linking to the original libcurl fails because `curlwrapper_setsockopt` is only defined in this wrapper lib.
|
||||
|
||||
## Use this lib in Dockerfiles.
|
||||
|
||||
A prebuilt version of this lib can found on dockerhub. To use it for your projects, add this to your Dockerfile.
|
||||
|
||||
```
|
||||
[...]
|
||||
COPY --from=wiiuenv/libcurlwrapper:[tag] /artifacts $DEVKITPRO
|
||||
[...]
|
||||
```
|
||||
|
||||
Replace [tag] with a tag you want to use, a list of tags can be found [here](https://hub.docker.com/r/wiiuenv/libcurlwrapper/tags).
|
||||
It's highly recommended to pin the version to the **latest date** instead of using `latest`.
|
||||
|
||||
## Format the code via docker
|
||||
|
||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source -i`
|
23
source/logger.h
Normal file
23
source/logger.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <coreinit/debug.h>
|
||||
#include <cstring>
|
||||
|
||||
#define __FILENAME__ ({ \
|
||||
const char *__filename = __FILE__; \
|
||||
const char *__pos = strrchr(__filename, '/'); \
|
||||
if (!__pos) __pos = strrchr(__filename, '\\'); \
|
||||
__pos ? __pos + 1 : __filename; \
|
||||
})
|
||||
|
||||
#define LOG_APP_TYPE "L"
|
||||
#define LOG_APP_NAME "libcurlwrapper"
|
||||
|
||||
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
|
||||
do { \
|
||||
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##WARNING## ", "\n", FMT, ##ARGS)
|
103
source/macro_magic.h
Normal file
103
source/macro_magic.h
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
struct curl_blob {
|
||||
void *data;
|
||||
size_t len;
|
||||
unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
|
||||
left zeroes */
|
||||
};
|
||||
|
||||
#define MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
if (WUT_PP_CAT(s_, function_name) == nullptr) { \
|
||||
if (sModuleHandle == nullptr || OSDynLoad_FindExport(sModuleHandle, FALSE, #function_name, (void **) &WUT_PP_CAT(s_, function_name)) != OS_DYNLOAD_OK) { \
|
||||
DEBUG_FUNCTION_LINE_ERR("FindExport " #function_name " failed."); \
|
||||
return error_return; \
|
||||
} else { \
|
||||
functionHandles.push_front((uint32_t *) &WUT_PP_CAT(s_, function_name)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG8(res, function_name, error_return, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2, void *param3, void *param4, void *param5, void *param6, void *param7, void *param8) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2, param3, param4, param5, param6, param7, param8); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG7(res, function_name, error_return, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2, void *param3, void *param4, void *param5, void *param6, void *param7) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2, param3, param4, param5, param6, param7); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG6(res, function_name, error_return, arg1, arg2, arg3, arg4, arg5, arg6) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2, void *param3, void *param4, void *param5, void *param6) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2, param3, param4, param5, param6); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG5(res, function_name, error_return, arg1, arg2, arg3, arg4, arg5) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2, void *param3, void *param4, void *param5) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2, param3, param4, param5); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG4(res, function_name, error_return, arg1, arg2, arg3, arg4) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2, void *param3, void *param4) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2, param3, param4); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG3(res, function_name, error_return, arg1, arg2, arg3) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2, void *param3) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2, param3); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG2(res, function_name, error_return, arg1, arg2) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1, void *param2) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1, param2); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG1(res, function_name, error_return, arg1) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name(void *param1) { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(param1); \
|
||||
}
|
||||
|
||||
#define MAGIC_FUNCTION_ARG0(res, function_name, error_return) \
|
||||
static void *(*WUT_PP_CAT(s_, function_name))(void) = nullptr; \
|
||||
extern "C" res function_name() { \
|
||||
MAGIC_CHECK_FUNCTION_PTR(function_name, error_return) \
|
||||
return reinterpret_cast<decltype(&function_name)>(WUT_PP_CAT(s_, function_name))(); \
|
||||
}
|
||||
|
||||
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, MACRO_NAME, ...) MACRO_NAME
|
||||
#define MAGIC_FUNCTION(res, function_name, error_return, ...) \
|
||||
GET_MACRO(__VA_ARGS__, \
|
||||
MAGIC_FUNCTION_ARG8, \
|
||||
MAGIC_FUNCTION_ARG7, \
|
||||
MAGIC_FUNCTION_ARG6, \
|
||||
MAGIC_FUNCTION_ARG5, \
|
||||
MAGIC_FUNCTION_ARG4, \
|
||||
MAGIC_FUNCTION_ARG3, \
|
||||
MAGIC_FUNCTION_ARG2, \
|
||||
MAGIC_FUNCTION_ARG1) \
|
||||
(res, function_name, error_return, __VA_ARGS__)
|
||||
|
||||
#define RETURN_VOID
|
||||
|
||||
#define CURLE_FAILED_INIT 2
|
||||
#define CURLHE_NOT_BUILT_IN 7
|
||||
#define CURLUE_BAD_HANDLE 1
|
||||
#define CURLSSLSET_NO_BACKENDS 3
|
||||
#define CURLSHE_NOT_BUILT_IN 5
|
||||
#define CURLM_INTERNAL_ERROR 4
|
268
source/main.cpp
Normal file
268
source/main.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
#include "logger.h"
|
||||
#include "macro_magic.h"
|
||||
#include <cerrno>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <cstdarg>
|
||||
#include <forward_list>
|
||||
#include <string_view>
|
||||
#include <sys/socket.h>
|
||||
|
||||
static void *(*s_setsockopt)() = nullptr;
|
||||
|
||||
static bool sInitDone = false;
|
||||
static OSDynLoad_Module sModuleHandle = nullptr;
|
||||
static uint8_t *s_cacert_pem = nullptr;
|
||||
static uint32_t *s_cacert_pem_size = nullptr;
|
||||
|
||||
std::forward_list<uint32_t *> functionHandles;
|
||||
|
||||
extern "C" int curl_global_init() {
|
||||
if (sInitDone) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (OSDynLoad_Acquire("homebrew_curlwrapper", &sModuleHandle) != OS_DYNLOAD_OK) {
|
||||
DEBUG_FUNCTION_LINE_ERR("OSDynLoad_Acquire failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "setsockopt", (void **) &s_setsockopt) != OS_DYNLOAD_OK) {
|
||||
DEBUG_FUNCTION_LINE_ERR("FindExport setsockopt failed.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (OSDynLoad_FindExport(sModuleHandle, true, "cacert_pem", (void **) &s_cacert_pem) != OS_DYNLOAD_OK) {
|
||||
DEBUG_FUNCTION_LINE_WARN("FindExport cacert_pem failed.");
|
||||
}
|
||||
|
||||
if (OSDynLoad_FindExport(sModuleHandle, true, "cacert_pem_size", (void **) &s_cacert_pem_size) != OS_DYNLOAD_OK) {
|
||||
DEBUG_FUNCTION_LINE_WARN("FindExport cacert_pem_size failed.");
|
||||
}
|
||||
|
||||
char *(*s_curl_version_tmp)() = nullptr;
|
||||
if (OSDynLoad_FindExport(sModuleHandle, false, "curl_version", (void **) &s_curl_version_tmp) == OS_DYNLOAD_OK) {
|
||||
const char *expectedCURLVersion = "libcurl/7.84.0";
|
||||
if (!std::string_view(s_curl_version_tmp()).starts_with(expectedCURLVersion)) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Unexpected libcurl version: %s (expected %s)", s_curl_version_tmp(), expectedCURLVersion);
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to check curl_version");
|
||||
}
|
||||
|
||||
sInitDone = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void curl_global_cleanup() {
|
||||
if (!sInitDone) { return; }
|
||||
OSDynLoad_Release(sModuleHandle);
|
||||
sModuleHandle = nullptr;
|
||||
sInitDone = false;
|
||||
s_setsockopt = nullptr;
|
||||
s_cacert_pem = nullptr;
|
||||
s_cacert_pem_size = nullptr;
|
||||
for (auto &handle : functionHandles) {
|
||||
*handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int curlwrapper_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
||||
if (s_setsockopt == nullptr) {
|
||||
if (curl_global_init() != 0 || s_setsockopt == nullptr) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
}
|
||||
return reinterpret_cast<decltype(&setsockopt)>(s_setsockopt)(sockfd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
// Variadic function in curl header, but always has 3 args
|
||||
static void *(*s_curl_easy_setopt)() = nullptr;
|
||||
extern "C" int curl_easy_setopt(void *param1, void *param2, void *param3) {
|
||||
if (s_curl_easy_setopt == nullptr) {
|
||||
if (sModuleHandle == nullptr || OSDynLoad_FindExport(sModuleHandle, 0, "curl_easy_setopt", (void **) &s_curl_easy_setopt) != OS_DYNLOAD_OK) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to find export curl_easy_setopt");
|
||||
return CURLE_FAILED_INIT;
|
||||
} else {
|
||||
functionHandles.push_front((uint32_t *) &s_curl_easy_setopt);
|
||||
}
|
||||
}
|
||||
if ((uint32_t) param2 == 10000 + 149) { // CURLOPT_SOCKOPTDATA
|
||||
if (s_setsockopt != nullptr && (uint32_t) param3 == 0x13371337) {
|
||||
param3 = (void *) s_setsockopt;
|
||||
}
|
||||
}
|
||||
|
||||
return reinterpret_cast<decltype(&curl_easy_setopt)>(s_curl_easy_setopt)(param1, param2, param3);
|
||||
}
|
||||
|
||||
// Variadic function in curl header, but always has 3 args
|
||||
static void *(*s_curl_easy_init)() = nullptr;
|
||||
extern "C" void *curl_easy_init() {
|
||||
if (s_curl_easy_init == nullptr) {
|
||||
if (sModuleHandle == nullptr || OSDynLoad_FindExport(sModuleHandle, 0, "curl_easy_init", (void **) &s_curl_easy_init) != OS_DYNLOAD_OK) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to find export curl_easy_init");
|
||||
return nullptr;
|
||||
} else {
|
||||
functionHandles.push_front((uint32_t *) &s_curl_easy_init);
|
||||
}
|
||||
}
|
||||
|
||||
auto result = reinterpret_cast<decltype(&curl_easy_init)>(s_curl_easy_init)();
|
||||
if (result != nullptr && s_cacert_pem != nullptr && s_cacert_pem_size != nullptr) {
|
||||
struct curl_blob blob {};
|
||||
blob.data = (void *) s_cacert_pem;
|
||||
blob.len = *s_cacert_pem_size;
|
||||
blob.flags = 1; /*CURL_BLOB_COPY*/
|
||||
|
||||
// Use the certificate bundle in the data
|
||||
if (curl_easy_setopt(result, reinterpret_cast<void *>(40000 + 309) /*CURLOPT_CAINFO_BLOB*/, &blob) != 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to set ca_certs");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MAGIC_FUNCTION(int, curl_easy_perform, CURLE_FAILED_INIT, arg1);
|
||||
MAGIC_FUNCTION(void, curl_easy_cleanup, RETURN_VOID, arg1);
|
||||
MAGIC_FUNCTION(int, curl_easy_getinfo, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(void *, curl_easy_duphandle, nullptr, arg1);
|
||||
MAGIC_FUNCTION(void, curl_easy_reset, RETURN_VOID, arg1);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_easy_recv, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(int, curl_easy_send, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(int, curl_easy_upkeep, CURLE_FAILED_INIT, arg1);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_easy_header, CURLHE_NOT_BUILT_IN, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
MAGIC_FUNCTION(void *, curl_easy_nextheader, nullptr, arg1, arg2, arg3, arg4);
|
||||
|
||||
MAGIC_FUNCTION(void *, curl_easy_option_by_name, nullptr, arg1);
|
||||
MAGIC_FUNCTION(void *, curl_easy_option_by_id, nullptr, arg1);
|
||||
MAGIC_FUNCTION(void *, curl_easy_option_next, nullptr, arg1);
|
||||
|
||||
MAGIC_FUNCTION_ARG0(void *, curl_url, nullptr);
|
||||
MAGIC_FUNCTION(void, curl_url_cleanup, RETURN_VOID, arg1);
|
||||
MAGIC_FUNCTION(void *, curl_url_dup, nullptr, arg1);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_url_get, CURLUE_BAD_HANDLE, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(int, curl_url_set, CURLUE_BAD_HANDLE, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(const char *, curl_url_strerror, "[ERROR]", arg1);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_strequal, 0, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_strnequal, 0, arg1, arg2, arg3);
|
||||
|
||||
MAGIC_FUNCTION(void *, curl_mime_init, nullptr, arg1);
|
||||
MAGIC_FUNCTION(void, curl_mime_free, RETURN_VOID, arg1);
|
||||
MAGIC_FUNCTION(void *, curl_mime_addpart, nullptr, arg1);
|
||||
MAGIC_FUNCTION(int, curl_mime_name, CURLE_FAILED_INIT, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mime_filename, CURLE_FAILED_INIT, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mime_type, CURLE_FAILED_INIT, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mime_encoder, CURLE_FAILED_INIT, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mime_data, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(int, curl_mime_filedata, CURLE_FAILED_INIT, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mime_data_cb, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
MAGIC_FUNCTION(int, curl_mime_subparts, CURLE_FAILED_INIT, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mime_headers, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_formadd, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
MAGIC_FUNCTION(int, curl_formget, CURLE_FAILED_INIT, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(void, curl_formfree, RETURN_VOID, arg1);
|
||||
MAGIC_FUNCTION(char *, curl_getenv, nullptr, arg1);
|
||||
MAGIC_FUNCTION_ARG0(const char *, curl_version, "[ERROR]");
|
||||
MAGIC_FUNCTION(char *, curl_easy_escape, nullptr, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(char *, curl_escape, nullptr, arg1, arg2);
|
||||
MAGIC_FUNCTION(char *, curl_easy_unescape, nullptr, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(char *, curl_unescape, nullptr, arg1, arg2);
|
||||
MAGIC_FUNCTION(void, curl_free, RETURN_VOID, arg1);
|
||||
MAGIC_FUNCTION(int, curl_global_init_mem, CURLE_FAILED_INIT, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_global_sslset, CURLSSLSET_NO_BACKENDS, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(void *, curl_slist_append, nullptr, arg1, arg2);
|
||||
MAGIC_FUNCTION(void, curl_slist_free_all, RETURN_VOID, arg1);
|
||||
MAGIC_FUNCTION(time_t, curl_getdate, 0, arg1, arg2);
|
||||
|
||||
MAGIC_FUNCTION_ARG0(void *, curl_share_init, nullptr);
|
||||
// Variadic function in curl header, but always has 3 args
|
||||
MAGIC_FUNCTION(int, curl_share_setopt, CURLSHE_NOT_BUILT_IN, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(int, curl_share_cleanup, CURLSHE_NOT_BUILT_IN, arg1);
|
||||
|
||||
MAGIC_FUNCTION(void *, curl_version_info, nullptr, arg1);
|
||||
|
||||
MAGIC_FUNCTION(const char *, curl_easy_strerror, "[ERROR]", arg1);
|
||||
MAGIC_FUNCTION(const char *, curl_share_strerror, "[ERROR]", arg1);
|
||||
MAGIC_FUNCTION(int, curl_easy_pause, CURLE_FAILED_INIT, arg1, arg2);
|
||||
|
||||
MAGIC_FUNCTION_ARG0(void *, curl_multi_init, nullptr);
|
||||
MAGIC_FUNCTION(int, curl_multi_add_handle, CURLM_INTERNAL_ERROR, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_multi_remove_handle, CURLM_INTERNAL_ERROR, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_multi_fdset, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
||||
MAGIC_FUNCTION(int, curl_multi_wait, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
||||
MAGIC_FUNCTION(int, curl_multi_poll, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4, arg5);
|
||||
MAGIC_FUNCTION(int, curl_multi_wakeup, CURLM_INTERNAL_ERROR, arg1);
|
||||
MAGIC_FUNCTION(int, curl_multi_perform, CURLM_INTERNAL_ERROR, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_multi_cleanup, CURLM_INTERNAL_ERROR, arg1);
|
||||
MAGIC_FUNCTION(void *, curl_multi_info_read, nullptr, arg1, arg2);
|
||||
MAGIC_FUNCTION(const char *, curl_multi_strerror, "[ERROR]", arg1);
|
||||
|
||||
MAGIC_FUNCTION(int, curl_multi_socket, CURLM_INTERNAL_ERROR, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(int, curl_multi_socket_action, CURLM_INTERNAL_ERROR, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(int, curl_multi_socket_all, CURLM_INTERNAL_ERROR, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_multi_timeout, CURLM_INTERNAL_ERROR, arg1, arg2);
|
||||
// Variadic function in curl header, but always has 3 args
|
||||
MAGIC_FUNCTION(int, curl_multi_setopt, CURLM_INTERNAL_ERROR, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(int, curl_multi_assign, CURLM_INTERNAL_ERROR, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(char *, curl_pushheader_bynum, nullptr, arg1, arg2);
|
||||
MAGIC_FUNCTION(char *, curl_pushheader_byname, nullptr, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mvprintf, 0, arg1, arg2);
|
||||
MAGIC_FUNCTION(int, curl_mvfprintf, 0, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(int, curl_mvsprintf, 0, arg1, arg2, arg3);
|
||||
MAGIC_FUNCTION(int, curl_mvsnprintf, 0, arg1, arg2, arg3, arg4);
|
||||
MAGIC_FUNCTION(char *, curl_mvaprintf, nullptr, arg1, arg2);
|
||||
|
||||
extern "C" int curl_mprintf(const char *format, ...) {
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
auto res = curl_mvprintf((void *) format, (void *) va);
|
||||
va_end(va);
|
||||
|
||||
return res;
|
||||
}
|
||||
extern "C" int curl_mfprintf(FILE *fd, const char *format, ...) {
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
auto res = curl_mvfprintf((void *) fd, (void *) format, (void *) va);
|
||||
va_end(va);
|
||||
|
||||
return res;
|
||||
}
|
||||
extern "C" int curl_msprintf(char *buffer, const char *format, ...) {
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
auto res = curl_mvsprintf((void *) buffer, (void *) format, (void *) va);
|
||||
va_end(va);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) {
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
auto res = curl_mvsnprintf((void *) buffer, (void *) maxlength, (void *) format, (void *) va);
|
||||
va_end(va);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" char *curl_maprintf(const char *format, ...) {
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
auto res = curl_mvaprintf((void *) format, (void *) va);
|
||||
va_end(va);
|
||||
|
||||
return res;
|
||||
}
|
Loading…
Reference in New Issue
Block a user