From f374231363349e506be5507b6d01c51b34e5831b Mon Sep 17 00:00:00 2001 From: Lightmann Date: Sun, 14 Aug 2022 13:42:40 -0400 Subject: [PATCH 1/6] Remove SpringBoard.zip --- SpringBoard.zip | Bin 58955 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 SpringBoard.zip diff --git a/SpringBoard.zip b/SpringBoard.zip deleted file mode 100644 index 7257c6d568ccf2b05a331b5456cc6482f85c6107..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58955 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 From 8a4f8c87c232f985f6a8c76e463ba3c646955c8f Mon Sep 17 00:00:00 2001 From: Lightmann Date: Sun, 14 Aug 2022 13:45:04 -0400 Subject: [PATCH 2/6] Switch rbs to local files from git module --- .gitmodules | 4 - rocketbootstrap/.gitignore | 7 - rocketbootstrap/.gitmodules | 6 - .../LightMessaging/LightMessaging.h | 530 ------------------ rocketbootstrap/LightMessaging/README | 2 - rocketbootstrap/LightMessaging/bootstrap.h | 358 ------------ rocketbootstrap/LightMessaging/sandbox.h | 181 ------ rocketbootstrap/Makefile | 32 -- rocketbootstrap/Shims.x | 125 ----- rocketbootstrap/Tweak.x | 437 --------------- rocketbootstrap/bootstrap.h | 358 ------------ rocketbootstrap/framework | 1 - rocketbootstrap/layout/DEBIAN/control | 14 - rocketbootstrap/layout/DEBIAN/postinst | 5 - rocketbootstrap/layout/DEBIAN/prerm | 3 - .../com.rpetrich.rocketbootstrapd.plist | 26 - .../DynamicLibraries/RocketBootstrap.dylib | 1 - .../DynamicLibraries/RocketBootstrap.plist | 17 - rocketbootstrap/overlayheaders | 1 - rocketbootstrap/rocketbootstrap.h | 40 +- rocketbootstrap/rocketbootstrap_dynamic.h | 93 ++- rocketbootstrap/rocketbootstrap_internal.h | 36 -- rocketbootstrap/rocketd.c | 67 --- rocketbootstrap/sandbox.h | 181 ------ rocketbootstrap/tests/Makefile | 18 - rocketbootstrap/tests/control | 11 - rocketbootstrap/tests/framework | 1 - rocketbootstrap/tests/tests.m | 43 -- 28 files changed, 107 insertions(+), 2491 deletions(-) delete mode 100644 rocketbootstrap/.gitignore delete mode 100644 rocketbootstrap/.gitmodules delete mode 100644 rocketbootstrap/LightMessaging/LightMessaging.h delete mode 100644 rocketbootstrap/LightMessaging/README delete mode 100644 rocketbootstrap/LightMessaging/bootstrap.h delete mode 100644 rocketbootstrap/LightMessaging/sandbox.h delete mode 100644 rocketbootstrap/Makefile delete mode 100644 rocketbootstrap/Shims.x delete mode 100644 rocketbootstrap/Tweak.x delete mode 100644 rocketbootstrap/bootstrap.h delete mode 120000 rocketbootstrap/framework delete mode 100644 rocketbootstrap/layout/DEBIAN/control delete mode 100755 rocketbootstrap/layout/DEBIAN/postinst delete mode 100755 rocketbootstrap/layout/DEBIAN/prerm delete mode 100644 rocketbootstrap/layout/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist delete mode 120000 rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib delete mode 100644 rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist delete mode 120000 rocketbootstrap/overlayheaders delete mode 100644 rocketbootstrap/rocketbootstrap_internal.h delete mode 100644 rocketbootstrap/rocketd.c delete mode 100644 rocketbootstrap/sandbox.h delete mode 100644 rocketbootstrap/tests/Makefile delete mode 100644 rocketbootstrap/tests/control delete mode 120000 rocketbootstrap/tests/framework delete mode 100644 rocketbootstrap/tests/tests.m diff --git a/.gitmodules b/.gitmodules index 2f9e2c3..fd3783a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,6 @@ [submodule "LightMessaging"] path = LightMessaging url = https://github.com/rpetrich/LightMessaging.git -[submodule "rocketbootstrap"] - path = rocketbootstrap - url = https://github.com/rpetrich/rocketbootstrap.git - branch = ios9 [submodule "CaptainHook"] path = CaptainHook url = https://github.com/rpetrich/CaptainHook.git diff --git a/rocketbootstrap/.gitignore b/rocketbootstrap/.gitignore deleted file mode 100644 index 9bcaccc..0000000 --- a/rocketbootstrap/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -._* -*.deb -.debmake -_ -obj -.theos -.DS_Store diff --git a/rocketbootstrap/.gitmodules b/rocketbootstrap/.gitmodules deleted file mode 100644 index be62880..0000000 --- a/rocketbootstrap/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "framework"] - path = framework - url = git://github.com/rpetrich/theos.git -[submodule "LightMessaging"] - path = LightMessaging - url = git://github.com/rpetrich/LightMessaging.git diff --git a/rocketbootstrap/LightMessaging/LightMessaging.h b/rocketbootstrap/LightMessaging/LightMessaging.h deleted file mode 100644 index 773bd36..0000000 --- a/rocketbootstrap/LightMessaging/LightMessaging.h +++ /dev/null @@ -1,530 +0,0 @@ -#ifndef __APPLE_API_PRIVATE -#define __APPLE_API_PRIVATE -#include "sandbox.h" -#undef __APPLE_API_PRIVATE -#else -#include "sandbox.h" -#endif - -#ifndef LIGHTMESSAGING_USE_ROCKETBOOTSTRAP -#define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 1 -#endif - -#ifndef LIGHTMESSAGING_TIMEOUT -#define LIGHTMESSAGING_TIMEOUT MACH_MSG_TIMEOUT_NONE -#define _LIGHTMESSAGING_TIMEOUT_FLAGS 0 -#else -#define _LIGHTMESSAGING_TIMEOUT_FLAGS (MACH_SEND_TIMEOUT | MACH_RCV_TIMEOUT) -#endif - -#import -#import -#include -#include -#if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP -#include "../rocketbootstrap/rocketbootstrap.h" -#else -#include "bootstrap.h" -#endif - -#ifdef __OBJC__ -#ifndef __has_feature - #define __has_feature(x) 0 -#endif - -#if __has_feature(objc_arc) -#define LMBridgedCast_(a, b) (__bridge a)(b) -#else -#define LMBridgedCast_(a, b) (a)(b) -#endif -#endif - -typedef struct { - mach_port_t serverPort; - name_t serverName; -} LMConnection; -typedef LMConnection *LMConnectionRef; - -#define __LMMaxInlineSize 4096 + sizeof(LMMessage) -typedef struct __LMMessage { - mach_msg_header_t head; - mach_msg_body_t body; - union { - struct { - mach_msg_ool_descriptor_t descriptor; - } out_of_line; - struct { - uint32_t length; - uint8_t bytes[0]; - } in_line; - } data; -} LMMessage; - -typedef struct __LMResponseBuffer { - LMMessage message; - uint8_t slack[__LMMaxInlineSize - sizeof(LMMessage) + MAX_TRAILER_SIZE]; -} LMResponseBuffer; - -static inline uint32_t LMBufferSizeForLength(uint32_t length) -{ - if (length + sizeof(LMMessage) > __LMMaxInlineSize) - return sizeof(LMMessage); - else - return ((sizeof(LMMessage) + length) + 3) & ~0x3; -} - -static inline void LMMessageCopyInline(LMMessage *message, const void *data, uint32_t length) -{ - message->data.in_line.length = length; - if (data) { - memcpy(message->data.in_line.bytes, data, length); - } -} - -static inline void LMMessageAssignOutOfLine(LMMessage *message, const void *data, uint32_t length) -{ - message->head.msgh_bits |= MACH_MSGH_BITS_COMPLEX; - message->body.msgh_descriptor_count = 1; - message->data.out_of_line.descriptor.type = MACH_MSG_OOL_DESCRIPTOR; - message->data.out_of_line.descriptor.copy = MACH_MSG_VIRTUAL_COPY; - message->data.out_of_line.descriptor.deallocate = false; - message->data.out_of_line.descriptor.address = (void *)data; - message->data.out_of_line.descriptor.size = length; -} - -static inline void LMMessageAssignData(LMMessage *message, const void *data, uint32_t length) -{ - if (length == 0) { - message->body.msgh_descriptor_count = 0; - message->data.in_line.length = length; - } else if (message->head.msgh_size != sizeof(LMMessage)) { - message->body.msgh_descriptor_count = 0; - message->data.in_line.length = length; - memcpy(message->data.in_line.bytes, data, length); - } else { - LMMessageAssignOutOfLine(message, data, length); - } -} - -static inline void *LMMessageGetData(LMMessage *message) -{ - if (message->body.msgh_descriptor_count) - return message->data.out_of_line.descriptor.address; - if (message->data.in_line.length == 0) - return NULL; - return &message->data.in_line.bytes; -} - -static inline uint32_t LMMessageGetDataLength(LMMessage *message) -{ - if (message->body.msgh_descriptor_count) - return message->data.out_of_line.descriptor.size; - uint32_t result = message->data.in_line.length; - // Clip to the maximum size of a message buffer, prevents clients from forcing reads outside the region - if (result > __LMMaxInlineSize - offsetof(LMMessage, data.in_line.bytes)) - return __LMMaxInlineSize - offsetof(LMMessage, data.in_line.bytes); - // Client specified the right size, yay! - return result; -} - -static inline mach_msg_return_t LMMachMsg(LMConnection *connection, mach_msg_header_t *msg, mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size, mach_port_name_t rcv_name, mach_msg_timeout_t timeout, mach_port_name_t notify) -{ - for (;;) { - kern_return_t err; - if (connection->serverPort == MACH_PORT_NULL) { - mach_port_t selfTask = mach_task_self(); - if ((kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_5_0) && (kCFCoreFoundationVersionNumber < 800.0)) { - int sandbox_result = sandbox_check(getpid(), "mach-lookup", (enum sandbox_filter_type)(SANDBOX_FILTER_LOCAL_NAME | SANDBOX_CHECK_NO_REPORT), connection->serverName); - if (sandbox_result) { - return sandbox_result; - } - } - // Lookup remote port - mach_port_t bootstrap = MACH_PORT_NULL; - task_get_bootstrap_port(selfTask, &bootstrap); -#if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP - err = rocketbootstrap_look_up(bootstrap, connection->serverName, &connection->serverPort); -#else - err = bootstrap_look_up(bootstrap, connection->serverName, &connection->serverPort); -#endif - if (err) - return err; - } - msg->msgh_remote_port = connection->serverPort; - err = mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify); - if (err != MACH_SEND_INVALID_DEST) - return err; - mach_port_deallocate(mach_task_self(), msg->msgh_remote_port); - connection->serverPort = MACH_PORT_NULL; - } -} - -static inline kern_return_t LMConnectionSendOneWay(LMConnectionRef connection, SInt32 messageId, const void *data, uint32_t length) -{ - // Send message - uint32_t size = LMBufferSizeForLength(length); - uint8_t buffer[size]; - LMMessage *message = (LMMessage *)&buffer[0]; - memset(message, 0, sizeof(LMMessage)); - message->head.msgh_id = messageId; - message->head.msgh_size = size; - message->head.msgh_local_port = MACH_PORT_NULL; - message->head.msgh_reserved = 0; - message->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); - LMMessageAssignData(message, data, length); - return LMMachMsg(connection, &message->head, MACH_SEND_MSG, size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); -} - -static inline kern_return_t LMConnectionSendEmptyOneWay(LMConnectionRef connection, SInt32 messageId) -{ - // TODO: Optimize so we don't use the additional stack space - uint32_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t); - LMMessage message; - memset(&message, 0, size); - message.head.msgh_id = messageId; - message.head.msgh_size = size; - message.head.msgh_local_port = MACH_PORT_NULL; - message.head.msgh_reserved = 0; - message.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); - return LMMachMsg(connection, &message.head, MACH_SEND_MSG, size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); -} - -static inline kern_return_t LMConnectionSendTwoWay(LMConnectionRef connection, SInt32 messageId, const void *data, uint32_t length, LMResponseBuffer *responseBuffer) -{ - // Create a reply port - mach_port_t selfTask = mach_task_self(); - mach_port_name_t replyPort = MACH_PORT_NULL; - int err = mach_port_allocate(selfTask, MACH_PORT_RIGHT_RECEIVE, &replyPort); - if (err) { - responseBuffer->message.body.msgh_descriptor_count = 0; - return err; - } - // Send message - uint32_t size = LMBufferSizeForLength(length); - LMMessage *message = &responseBuffer->message; - memset(message, 0, sizeof(LMMessage)); - message->head.msgh_id = messageId; - message->head.msgh_size = size; - message->head.msgh_local_port = replyPort; - message->head.msgh_reserved = 0; - message->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); - LMMessageAssignData(message, data, length); - err = LMMachMsg(connection, &message->head, MACH_SEND_MSG | MACH_RCV_MSG | _LIGHTMESSAGING_TIMEOUT_FLAGS, size, sizeof(LMResponseBuffer), replyPort, LIGHTMESSAGING_TIMEOUT, MACH_PORT_NULL); - if (err) - responseBuffer->message.body.msgh_descriptor_count = 0; - // Cleanup - mach_port_mod_refs(selfTask, replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - return err; -} - -static inline void LMResponseBufferFree(LMResponseBuffer *responseBuffer) -{ - if (responseBuffer->message.body.msgh_descriptor_count != 0 && responseBuffer->message.data.out_of_line.descriptor.type == MACH_MSG_OOL_DESCRIPTOR) { - vm_deallocate(mach_task_self(), (vm_address_t)responseBuffer->message.data.out_of_line.descriptor.address, responseBuffer->message.data.out_of_line.descriptor.size); - responseBuffer->message.body.msgh_descriptor_count = 0; - } -} - -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -static inline kern_return_t LMStartServiceWithUserInfo(name_t serverName, CFRunLoopRef runLoop, CFMachPortCallBack callback, void *userInfo) -{ - // TODO: Figure out what the real interface is, implement service stopping, handle failures correctly - mach_port_t bootstrap = MACH_PORT_NULL; - task_get_bootstrap_port(mach_task_self(), &bootstrap); - CFMachPortContext context = { 0, userInfo, NULL, NULL, NULL }; - CFMachPortRef machPort = CFMachPortCreate(kCFAllocatorDefault, callback, &context, NULL); - CFRunLoopSourceRef machPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, machPort, 0); - CFRunLoopAddSource(runLoop, machPortSource, kCFRunLoopCommonModes); - mach_port_t port = CFMachPortGetPort(machPort); -#if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP - rocketbootstrap_unlock(serverName); -#endif - return bootstrap_register(bootstrap, serverName, port); -} -#pragma GCC diagnostic warning "-Wdeprecated-declarations" - -static inline kern_return_t LMStartService(name_t serverName, CFRunLoopRef runLoop, CFMachPortCallBack callback) -{ - return LMStartServiceWithUserInfo(serverName, runLoop, callback, NULL); -} - -static inline kern_return_t LMCheckInService(name_t serverName, CFRunLoopRef runLoop, CFMachPortCallBack callback, void *userInfo) -{ - // TODO: Figure out what the real interface is, implement service stopping, handle failures correctly - mach_port_t bootstrap = MACH_PORT_NULL; - task_get_bootstrap_port(mach_task_self(), &bootstrap); - CFMachPortContext context = { 0, userInfo, NULL, NULL, NULL }; - mach_port_t port = MACH_PORT_NULL; - kern_return_t result = bootstrap_check_in(bootstrap, serverName, &port); - if (result) - return result; - CFMachPortRef machPort = CFMachPortCreateWithPort(kCFAllocatorDefault, port, callback, &context, NULL); - CFRunLoopSourceRef machPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, machPort, 0); - CFRunLoopAddSource(runLoop, machPortSource, kCFRunLoopCommonModes); -#if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP - rocketbootstrap_unlock(serverName); -#endif - return 0; -} - -static inline bool LMDataWithSizeIsValidMessage(const void *data, CFIndex size) -{ - if (size < sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t)) - return false; - const LMMessage *message = (const LMMessage *)data; - if (message->body.msgh_descriptor_count) - return size >= sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + sizeof(mach_msg_ool_descriptor_t); - if (size < sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + sizeof(uint32_t)) - return false; - if (size < sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + sizeof(uint32_t) + message->data.in_line.length) - return false; - return true; -} - -static inline kern_return_t LMSendReply(mach_port_t replyPort, const void *data, uint32_t length) -{ - if (replyPort == MACH_PORT_NULL) - return 0; - uint32_t size = LMBufferSizeForLength(length); - uint8_t buffer[size]; - memset(buffer, 0, sizeof(LMMessage)); - LMMessage *response = (LMMessage *)&buffer[0]; - response->head.msgh_id = 0; - response->head.msgh_size = size; - response->head.msgh_remote_port = replyPort; - response->head.msgh_local_port = MACH_PORT_NULL; - response->head.msgh_reserved = 0; - response->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); - LMMessageAssignData(response, data, length); - // Send message - kern_return_t err = mach_msg(&response->head, MACH_SEND_MSG, size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (err) { - // Cleanup leaked SEND_ONCE - mach_port_mod_refs(mach_task_self(), replyPort, MACH_PORT_RIGHT_SEND_ONCE, -1); - } - return err; -} - -static inline kern_return_t LMSendIntegerReply(mach_port_t replyPort, int integer) -{ - return LMSendReply(replyPort, &integer, sizeof(integer)); -} - -static inline kern_return_t LMSendCFDataReply(mach_port_t replyPort, CFDataRef data) -{ - if (data) { - return LMSendReply(replyPort, CFDataGetBytePtr(data), CFDataGetLength(data)); - } else { - return LMSendReply(replyPort, NULL, 0); - } -} - -#ifdef __OBJC__ - -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -static inline id LMPropertyListForData(NSData *data) -{ - if ([NSPropertyListSerialization respondsToSelector:@selector(propertyListWithData:options:format:error:)]) - return [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:NULL]; - - return [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:NULL errorDescription:NULL]; -} - -static inline NSData *LMDataForPropertyList(id propertyList) -{ - if ([NSPropertyListSerialization respondsToSelector:@selector(dataWithPropertyList:options:format:error:)]) - return [NSPropertyListSerialization dataWithPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL]; - - return [NSPropertyListSerialization dataFromPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 errorDescription:NULL]; -} -#pragma GCC diagnostic warning "-Wdeprecated-declarations" - -static inline kern_return_t LMSendNSDataReply(mach_port_t replyPort, NSData *data) -{ - return LMSendReply(replyPort, [data bytes], [data length]); -} - -static inline kern_return_t LMSendPropertyListReply(mach_port_t replyPort, id propertyList) -{ - if (propertyList) - return LMSendNSDataReply(replyPort, LMDataForPropertyList(propertyList)); - else - return LMSendReply(replyPort, NULL, 0); -} - -#endif - -// Remote functions - -static inline bool LMConnectionSendOneWayData(LMConnectionRef connection, SInt32 messageId, CFDataRef data) -{ - if (data) - return LMConnectionSendOneWay(connection, messageId, CFDataGetBytePtr(data), CFDataGetLength(data)) == 0; - else - return LMConnectionSendOneWay(connection, messageId, NULL, 0) == 0; -} - -static inline kern_return_t LMConnectionSendTwoWayData(LMConnectionRef connection, SInt32 messageId, CFDataRef data, LMResponseBuffer *buffer) -{ - if (data) - return LMConnectionSendTwoWay(connection, messageId, CFDataGetBytePtr(data), CFDataGetLength(data), buffer); - else - return LMConnectionSendTwoWay(connection, messageId, NULL, 0, buffer); -} - -static inline int32_t LMResponseConsumeInteger(LMResponseBuffer *buffer) -{ - int32_t result = LMMessageGetDataLength(&buffer->message) == sizeof(int32_t) ? *(int32_t *)buffer->message.data.in_line.bytes : 0; - LMResponseBufferFree(buffer); - return result; -} - -#ifdef __OBJC__ - -static inline kern_return_t LMConnectionSendTwoWayPropertyList(LMConnectionRef connection, SInt32 messageId, id propertyList, LMResponseBuffer *buffer) -{ - return LMConnectionSendTwoWayData(connection, messageId, propertyList ? LMBridgedCast_(CFDataRef, LMDataForPropertyList(propertyList)) : NULL, buffer); -} - -static inline id LMResponseConsumePropertyList(LMResponseBuffer *buffer) -{ - uint32_t length = LMMessageGetDataLength(&buffer->message); - id result; - if (length) { - CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)LMMessageGetData(&buffer->message), length, kCFAllocatorNull); - result = LMPropertyListForData(LMBridgedCast_(NSData *, data)); - CFRelease(data); - } else { - result = nil; - } - LMResponseBufferFree(buffer); - return result; -} - -#ifdef UIKIT_EXTERN -#import - -typedef struct __attribute__((aligned(0x1))) __attribute__((packed)) { - uint32_t width; - uint32_t height; - uint32_t bitsPerComponent; - uint32_t bitsPerPixel; - uint32_t bytesPerRow; - CGBitmapInfo bitmapInfo; - float scale; - UIImageOrientation orientation; -} LMImageHeader; - -typedef struct { - LMMessage response; - LMImageHeader imageHeader; -} LMImageMessage; - -static void LMCGDataProviderReleaseCallback(void *info, const void *data, size_t size) -{ - vm_deallocate(mach_task_self(), (vm_address_t)data, size); -} - -static inline UIImage *LMResponseConsumeImage(LMResponseBuffer *buffer) -{ - if (buffer->message.body.msgh_descriptor_count != 0 && buffer->message.data.out_of_line.descriptor.type == MACH_MSG_OOL_DESCRIPTOR) { - const void *bytes = buffer->message.data.out_of_line.descriptor.address; - const LMImageMessage *message = (const LMImageMessage *)buffer; - const LMImageHeader *header = &message->imageHeader; - CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bytes, buffer->message.data.out_of_line.descriptor.size, LMCGDataProviderReleaseCallback); - if (provider) { - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGImageRef cgImage = CGImageCreate(header->width, header->height, header->bitsPerComponent, header->bitsPerPixel, header->bytesPerRow, colorSpace, header->bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault); - CGColorSpaceRelease(colorSpace); - CGDataProviderRelease(provider); - if (cgImage) { - UIImage *image; - if ([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) { - image = [UIImage imageWithCGImage:cgImage scale:header->scale orientation:header->orientation]; - } else { - image = [UIImage imageWithCGImage:cgImage]; - } - CGImageRelease(cgImage); - return image; - } - return nil; - } - } - LMResponseBufferFree(buffer); - return nil; -} - -typedef struct CGAccessSession *CGAccessSessionRef; - -CGAccessSessionRef CGAccessSessionCreate(CGDataProviderRef provider); -void *CGAccessSessionGetBytePointer(CGAccessSessionRef session); -size_t CGAccessSessionGetBytes(CGAccessSessionRef session,void *buffer,size_t bytes); -void CGAccessSessionRelease(CGAccessSessionRef session); - -static inline kern_return_t LMSendImageReply(mach_port_t replyPort, UIImage *image) -{ - if (replyPort == MACH_PORT_NULL) - return 0; - LMImageMessage buffer; - memset(&buffer, 0, sizeof(buffer)); - buffer.response.head.msgh_id = 0; - buffer.response.head.msgh_size = sizeof(buffer); - buffer.response.head.msgh_remote_port = replyPort; - buffer.response.head.msgh_local_port = MACH_PORT_NULL; - buffer.response.head.msgh_reserved = 0; - buffer.response.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); - CFDataRef imageData = NULL; - CGAccessSessionRef accessSession = NULL; - if (image) { - CGImageRef cgImage = image.CGImage; - if (cgImage) { - buffer.imageHeader.width = CGImageGetWidth(cgImage); - buffer.imageHeader.height = CGImageGetHeight(cgImage); - buffer.imageHeader.bitsPerComponent = CGImageGetBitsPerComponent(cgImage); - buffer.imageHeader.bitsPerPixel = CGImageGetBitsPerPixel(cgImage); - buffer.imageHeader.bytesPerRow = CGImageGetBytesPerRow(cgImage); - buffer.imageHeader.bitmapInfo = CGImageGetBitmapInfo(cgImage); - buffer.imageHeader.scale = [image respondsToSelector:@selector(scale)] ? [image scale] : 1.0f; - buffer.imageHeader.orientation = image.imageOrientation; - CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage); - bool hasLoadedData = false; - if (&CGAccessSessionCreate != NULL) { - accessSession = CGAccessSessionCreate(dataProvider); - if (accessSession) { - void *pointer = CGAccessSessionGetBytePointer(accessSession); - if (pointer) { - LMMessageAssignOutOfLine(&buffer.response, pointer, buffer.imageHeader.bytesPerRow * buffer.imageHeader.height); - hasLoadedData = true; - } - } - } - if (!hasLoadedData) { - if (accessSession) { - CGAccessSessionRelease(accessSession); - accessSession = NULL; - } - imageData = CGDataProviderCopyData(dataProvider); - if (imageData) { - LMMessageAssignOutOfLine(&buffer.response, CFDataGetBytePtr(imageData), CFDataGetLength(imageData)); - } - } - } - } - // Send message - kern_return_t err = mach_msg(&buffer.response.head, MACH_SEND_MSG, sizeof(buffer), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (err) { - // Cleanup leaked SEND_ONCE - mach_port_mod_refs(mach_task_self(), replyPort, MACH_PORT_RIGHT_SEND_ONCE, -1); - } - if (imageData) { - CFRelease(imageData); - } - if (accessSession) { - CGAccessSessionRelease(accessSession); - } - return err; -} - -#endif - -#endif diff --git a/rocketbootstrap/LightMessaging/README b/rocketbootstrap/LightMessaging/README deleted file mode 100644 index 4a8ba3a..0000000 --- a/rocketbootstrap/LightMessaging/README +++ /dev/null @@ -1,2 +0,0 @@ -Simple low-level replacement for CFMessagePort -Now stable and with RocketBootstrap integration by default diff --git a/rocketbootstrap/LightMessaging/bootstrap.h b/rocketbootstrap/LightMessaging/bootstrap.h deleted file mode 100644 index 8cb5a2d..0000000 --- a/rocketbootstrap/LightMessaging/bootstrap.h +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef __BOOTSTRAP_H__ -#define __BOOTSTRAP_H__ -/* - * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_APACHE_LICENSE_HEADER_START@ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @APPLE_APACHE_LICENSE_HEADER_END@ - */ - -/* - * bootstrap -- fundamental service initiator and port server - * Mike DeMoney, NeXT, Inc. - * Copyright, 1990. All rights reserved. - */ - -/* - * Interface: Bootstrap server - * - * The bootstrap server is the first user-mode task initiated by the Mach - * kernel at system boot time. The bootstrap server provides two services, - * it initiates other system tasks, and manages a table of name-port bindings - * for fundamental system services (e.g. lookupd, Window Manager, etc...). - * - * Name-port bindings can be established with the bootstrap server by either - * of two mechanisms: - * - * 1. The binding can be indicated, in advance of the service that backs it - * being available, via a "service create" request. In this case, bootstrap - * will immediately create a port and bind the indicated name with that port. - * At a later time, a service may "checkin" for the name-port - * binding and will be returned receive rights for the bound port. Lookup's - * on bindings created by this mechanism will return send rights to the port, - * even if no service has "checked-in". In this case, requests sent to the - * bound port will be queued until a server has checked-in and can satisfy the - * request. - * - * 2. Bindings can be established dynamically via a "register" request. In - * this case, the register request provides bootstrap with a name and send - * rights for a port. Bootstrap will provide send rights for the bound port - * to any requestor via the lookup request. - * - * Bootstrap provides its service port to descendant tasks via the Mach - * "bootstrap" special task port. All direct descendants of bootstrap receive - * a "privileged" bootstrap service port. System services that initiate - * untrusted tasks should replace the Mach bootstrap task special port with - * a subset bootstrap port to prevent them from infecting the namespace. - * - * The bootstrap server creates a "backup" port for each service that it - * creates. This is used to detect when a checked out service is no longer - * being served. The bootstrap server regains all rights to the port and - * it is marked available for check-out again. This allows crashed servers to - * resume service to previous clients. Lookup's on this named port will - * continue to be serviced by bootstrap while holding receive rights for the - * bound port. A client may detect that the service is inactive via the - * bootstrap status request. If an inactive service re-registers rather - * than "checking-in" the original bound port is destroyed. - * - * The status of a named service may be obtained via the "status" request. - * A service is "active" if a name-port binding exists and receive rights - * to the bound port are held by a task other than bootstrap. - * - * The bootstrap server may also (re)start server processes associated with - * with a set of services. The definition of the server process is done - * through the "create server" request. The server will be launched in the - * same bootstrap context in which it was registered. - */ -#include -#include -#include -#include -#include -#include - -__BEGIN_DECLS - -#pragma GCC visibility push(default) - -#define BOOTSTRAP_MAX_NAME_LEN 128 -#define BOOTSTRAP_MAX_CMD_LEN 512 - -typedef char name_t[BOOTSTRAP_MAX_NAME_LEN]; -typedef char cmd_t[BOOTSTRAP_MAX_CMD_LEN]; -typedef name_t *name_array_t; -typedef int bootstrap_status_t; -typedef bootstrap_status_t *bootstrap_status_array_t; -typedef unsigned int bootstrap_property_t; -typedef bootstrap_property_t * bootstrap_property_array_t; - -typedef boolean_t *bool_array_t; - -#define BOOTSTRAP_MAX_LOOKUP_COUNT 20 - -#define BOOTSTRAP_SUCCESS 0 -#define BOOTSTRAP_NOT_PRIVILEGED 1100 -#define BOOTSTRAP_NAME_IN_USE 1101 -#define BOOTSTRAP_UNKNOWN_SERVICE 1102 -#define BOOTSTRAP_SERVICE_ACTIVE 1103 -#define BOOTSTRAP_BAD_COUNT 1104 -#define BOOTSTRAP_NO_MEMORY 1105 -#define BOOTSTRAP_NO_CHILDREN 1106 - -#define BOOTSTRAP_STATUS_INACTIVE 0 -#define BOOTSTRAP_STATUS_ACTIVE 1 -#define BOOTSTRAP_STATUS_ON_DEMAND 2 - -/* - * After main() starts, it is safe to assume that this variable is always set. - */ -extern mach_port_t bootstrap_port; - -/* - * bootstrap_create_server() - * - * Declares a server that mach_init will re-spawn within the specified - * bootstrap context. The server is considered already "active" - * (i.e. will not be re-spawned) until the returned server_port is - * deallocated. - * - * In the meantime, services can be declared against the server, - * by using the server_port as the privileged bootstrap target of - * subsequent bootstrap_create_service() calls. - * - * When mach_init re-spawns the server, its task bootstrap port - * is set to the privileged sever_port. Through this special - * bootstrap port, it can access all of parent bootstrap's context - * (and all services are created in the parent's namespace). But - * all additional service declarations (and declaration removals) - * will be associated with this particular server. - * - * Only a holder of the server_port privilege bootstrap port can - * check in or register over those services. - * - * When all services associated with a server are deleted, and the server - * exits, it will automatically be deleted itself. - * - * If the server is declared "on_demand," then a non-running server - * will be re-launched on first use of one of the service ports - * registered against it. Otherwise, it will be re-launched - * immediately upon exiting (whether any client is actively using - * any of the service ports or not). - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_NOT_PRIVILEGED, bootstrap or uid invalid. - */ -kern_return_t bootstrap_create_server( - mach_port_t bp, - cmd_t server_cmd, - uid_t server_uid, - boolean_t on_demand, - mach_port_t *server_port); - -/* - * bootstrap_subset() - * - * Returns a new port to use as a bootstrap port. This port behaves - * exactly like the previous bootstrap_port, except that ports dynamically - * registered via bootstrap_register() are available only to users of this - * specific subset_port. Lookups on the subset_port will return ports - * registered with this port specifically, and ports registered with - * ancestors of this subset_port. Duplications of services already - * registered with an ancestor port may be registered with the subset port - * are allowed. Services already advertised may then be effectively removed - * by registering PORT_NULL for the service. - * When it is detected that the requestor_port is destroyed the subset - * port and all services advertized by it are destroyed as well. - * - * Errors: Returns appropriate kernel errors on rpc failure. - */ -kern_return_t bootstrap_subset( - mach_port_t bp, - mach_port_t requestor_port, - mach_port_t *subset_port); - -/* - * bootstrap_unprivileged() - * - * Given a bootstrap port, return its unprivileged equivalent. If - * the port is already unprivileged, another reference to the same - * port is returned. - * - * This is most often used by servers, which are launched with their - * bootstrap port set to the privileged port for the server, to get - * an unprivileged version of the same port for use by its unprivileged - * children (or any offspring that it does not want to count as part - * of the "server" for mach_init registration and re-launch purposes). - * - * Native launchd jobs are always started with an unprivileged port. - */ -kern_return_t bootstrap_unprivileged( - mach_port_t bp, - mach_port_t *unpriv_port) - AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; - -/* - * bootstrap_parent() - * - * Given a bootstrap subset port, return the parent bootstrap port. - * If the specified bootstrap port is already the root subset, - * the same port will be returned. Much like "." and ".." are the same - * in the file system name space for the root directory ("/"). - * - * Errors: - * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running - * with an effective user id of root (as determined by the security - * token in the message trailer). - */ -kern_return_t bootstrap_parent( - mach_port_t bp, - mach_port_t *parent_port); - -/* - * bootstrap_register() - * - * Registers a send right for service_port with the service identified by - * service_name. Attempts to register a service where an active binding - * already exists are rejected. - * - * If the service was previously declared with bootstrap_create_service(), - * but is not currently active, this call can be used to undeclare the - * service. The bootstrap port used must have sufficient privilege to - * do so. (Registering MACH_PORT_NULL is especially useful for shutting - * down declared services). - * - * This API is deprecated. Old scenarios and recommendations: - * - * 1) Code that used to call bootstrap_check_in() and then bootstrap_register() - * can now always call bootstrap_check_in(). - * - * 2) If the code was registering a well known name, please switch to launchd. - * - * 3) If the code was registering a dynamically generated string and passing - * the string to other applications, please rewrite the code to send a Mach - * send-right directly. - * - * 4) If the launchd job maintained an optional Mach service, please reserve - * the name with launchd and control the presense of the service through - * ownership of the Mach receive right like so. - * - * MachServices - * - * com.apple.windowserver - * - * com.apple.windowserver.active - * - * HideUntilCheckIn - * - * - * - * - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to - * bootstrap port without privilege. - * Returns BOOTSTRAP_NAME_IN_USE, if service has already been - * register or checked-in. - */ -AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5 -kern_return_t -bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp); - -/* - * bootstrap_create_service() - * - * Creates a service named "service_name" and returns a send right to that - * port in "service_port." The port may later be checked in as if this - * port were configured in the bootstrap configuration file. - * - * This API is deprecated. Please call bootstrap_check_in() instead. - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_SERVICE_ACTIVE, if service already exists. - */ -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6 -AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6 -#endif -kern_return_t -bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp); - -/* - * bootstrap_check_in() - * - * Returns the receive right for the service named by service_name. The - * service must have been declared in the launchd.plist(5) file associated - * with the job. Attempts to check_in a service which is already active - * are not allowed. - * - * If the service was declared as being associated with a server, the - * check_in must come from the server's privileged port (server_port). - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist. - * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to - * bootstrap port without privilege. - * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been - * registered or checked-in. - */ -kern_return_t bootstrap_check_in( - mach_port_t bp, - const name_t service_name, - mach_port_t *sp); - -/* - * bootstrap_look_up() - * - * Returns a send right for the service port declared/registered under the - * name service_name. The service is not guaranteed to be active. Use the - * bootstrap_status call to determine the status of the service. - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist. - */ -kern_return_t bootstrap_look_up( - mach_port_t bp, - const name_t service_name, - mach_port_t *sp); - -/* - * bootstrap_status() - * - * In practice, this call was used to preflight whether the following two - * APIs would succeed. - * - * bootstrap_look_up() - * bootstrap_check_in() - * - * Please don't bother. Just call the above two APIs directly and check - * for failure. - */ -kern_return_t bootstrap_status( - mach_port_t bp, - name_t service_name, - bootstrap_status_t *service_active) - AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; - -/* bootstrap_strerror() - * - * Translate a return value from the bootstrap_*() APIs to a string. - */ -const char *bootstrap_strerror(kern_return_t r) __attribute__((__nothrow__, __pure__, __warn_unused_result__)); - -#pragma GCC visibility pop - -__END_DECLS - -#endif /* __BOOTSTRAP_H__ */ \ No newline at end of file diff --git a/rocketbootstrap/LightMessaging/sandbox.h b/rocketbootstrap/LightMessaging/sandbox.h deleted file mode 100644 index ad38b0b..0000000 --- a/rocketbootstrap/LightMessaging/sandbox.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2006-2010 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _SANDBOX_H_ -#define _SANDBOX_H_ - -#include -#include -#include - -__BEGIN_DECLS -/* - * @function sandbox_init - * Places the current process in a sandbox with a profile as - * specified. If the process is already in a sandbox, the new profile - * is ignored and sandbox_init() returns an error. - * - * @param profile (input) The Sandbox profile to be used. The format - * and meaning of this parameter is modified by the `flags' parameter. - * - * @param flags (input) Must be SANDBOX_NAMED. All other - * values are reserved. - * - * @param errorbuf (output) In the event of an error, sandbox_init - * will set `*errorbuf' to a pointer to a NUL-terminated string - * describing the error. This string may contain embedded newlines. - * This error information is suitable for developers and is not - * intended for end users. - * - * If there are no errors, `*errorbuf' will be set to NULL. The - * buffer `*errorbuf' should be deallocated with `sandbox_free_error'. - * - * @result 0 on success, -1 otherwise. - */ -int sandbox_init(const char *profile, uint64_t flags, char **errorbuf); - -/* - * @define SANDBOX_NAMED The `profile' argument specifies a Sandbox - * profile named by one of the kSBXProfile* string constants. - */ -#define SANDBOX_NAMED 0x0001 - -#ifdef __APPLE_API_PRIVATE - -/* The following flags are reserved for Mac OS X. Developers should not - * depend on their availability. - */ - -/* - * @define SANDBOX_NAMED_BUILTIN The `profile' argument specifies the - * name of a builtin profile that is statically compiled into the - * system. - */ -#define SANDBOX_NAMED_BUILTIN 0x0002 - -/* - * @define SANDBOX_NAMED_EXTERNAL The `profile' argument specifies the - * pathname of a Sandbox profile. The pathname may be abbreviated: If - * the name does not start with a `/' it is treated as relative to - * /usr/share/sandbox and a `.sb' suffix is appended. - */ -#define SANDBOX_NAMED_EXTERNAL 0x0003 - -/* - * @define SANDBOX_NAMED_MASK Mask for name types: 4 bits, 15 possible - * name types, 3 currently defined. - */ -#define SANDBOX_NAMED_MASK 0x000f - -#endif /* __APPLE_API_PRIVATE */ - -/* - * Available Sandbox profiles. - */ - -/* TCP/IP networking is prohibited. */ -extern const char kSBXProfileNoInternet[]; - -/* All sockets-based networking is prohibited. */ -extern const char kSBXProfileNoNetwork[]; - -/* File system writes are prohibited. */ -extern const char kSBXProfileNoWrite[]; - -/* File system writes are restricted to temporary folders /var/tmp and - * confstr(_CS_DARWIN_USER_DIR, ...). - */ -extern const char kSBXProfileNoWriteExceptTemporary[]; - -/* All operating system services are prohibited. */ -extern const char kSBXProfilePureComputation[]; - -/* - * @function sandbox_free_error - * Deallocates an error string previously allocated by sandbox_init. - * - * @param errorbuf (input) The buffer to be freed. Must be a pointer - * previously returned by sandbox_init in the `errorbuf' argument, or NULL. - * - * @result void - */ -void sandbox_free_error(char *errorbuf); - - -#ifdef __APPLE_API_PRIVATE - -/* The following definitions are reserved for Mac OS X. Developers should not - * depend on their availability. - */ - -int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); - -int sandbox_init_with_extensions(const char *profile, uint64_t flags, const char *const extensions[], char **errorbuf); - -enum sandbox_filter_type { - SANDBOX_FILTER_NONE, - SANDBOX_FILTER_PATH, - SANDBOX_FILTER_GLOBAL_NAME, - SANDBOX_FILTER_LOCAL_NAME, - SANDBOX_FILTER_APPLEEVENT_DESTINATION, - SANDBOX_FILTER_RIGHT_NAME, -}; - -extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT __attribute__((weak_import)); - -enum sandbox_extension_flags { - FS_EXT_DEFAULTS = 0, - FS_EXT_FOR_PATH = (1 << 0), - FS_EXT_FOR_FILE = (1 << 1), - FS_EXT_READ = (1 << 2), - FS_EXT_WRITE = (1 << 3), - FS_EXT_PREFER_FILEID = (1 << 4), -}; - -int sandbox_check(pid_t pid, const char *operation, enum sandbox_filter_type type, ...); - -int sandbox_note(const char *note); - -int sandbox_suspend(pid_t pid); -int sandbox_unsuspend(void); - -int sandbox_issue_extension(const char *path, char **ext_token); -int sandbox_issue_fs_extension(const char *path, uint64_t flags, char **ext_token); -int sandbox_issue_fs_rw_extension(const char *path, char **ext_token); -int sandbox_issue_mach_extension(const char *name, char **ext_token); - -int sandbox_consume_extension(const char *path, const char *ext_token); -int sandbox_consume_fs_extension(const char *ext_token, char **path); -int sandbox_consume_mach_extension(const char *ext_token, char **name); - -int sandbox_release_fs_extension(const char *ext_token); - -int sandbox_container_path_for_pid(pid_t pid, char *buffer, size_t bufsize); - -int sandbox_wakeup_daemon(char **errorbuf); - -const char *_amkrtemp(const char *); - -#endif /* __APPLE_API_PRIVATE */ - -__END_DECLS -#endif /* _SANDBOX_H_ */ diff --git a/rocketbootstrap/Makefile b/rocketbootstrap/Makefile deleted file mode 100644 index 886da4d..0000000 --- a/rocketbootstrap/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -LIBRARY_NAME = librocketbootstrap -librocketbootstrap_FILES = Tweak.x Shims.x -librocketbootstrap_LIBRARIES = substrate -librocketbootstrap_FRAMEWORKS = Foundation - -TOOL_NAME = rocketd -rocketd_FILES = rocketd.c -rocketd_CFLAGS = -fblocks -rocketd_FRAMEWORKS = CoreFoundation -rocketd_INSTALL_PATH = /usr/libexec -rocketd_IPHONE_ARCHS = armv6 arm64 - -ADDITIONAL_CFLAGS = -std=c99 -Ioverlayheaders - -IPHONE_ARCHS = armv6 armv7 armv7s arm64 - -SDKVERSION_armv6 = 5.1 -INCLUDE_SDKVERSION_armv6 = 8.4 -TARGET_IPHONEOS_DEPLOYMENT_VERSION = 4.0 - -TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv6 = 3.0 -THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode_Legacy.app/Contents/Developer - -include framework/makefiles/common.mk -include framework/makefiles/library.mk -include framework/makefiles/tool.mk - -stage:: - mkdir -p "$(THEOS_STAGING_DIR)/usr/include" - cp -a rocketbootstrap.h rocketbootstrap_dynamic.h "$(THEOS_STAGING_DIR)/usr/include" - plutil -convert binary1 "$(THEOS_STAGING_DIR)/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist" - plutil -convert binary1 "$(THEOS_STAGING_DIR)/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist" diff --git a/rocketbootstrap/Shims.x b/rocketbootstrap/Shims.x deleted file mode 100644 index 7aeaf39..0000000 --- a/rocketbootstrap/Shims.x +++ /dev/null @@ -1,125 +0,0 @@ -#import "rocketbootstrap_internal.h" - -#import -#import -#import - -static OSSpinLock spin_lock; - -kern_return_t bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags) __attribute__((weak_import)); -kern_return_t (*_bootstrap_look_up3)(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags); - -kern_return_t $bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; - id obj = [threadDictionary objectForKey:@"rocketbootstrap_intercept_next_lookup"]; - if (obj) { - [threadDictionary removeObjectForKey:@"rocketbootstrap_intercept_next_lookup"]; - [pool drain]; - return rocketbootstrap_look_up(bp, service_name, sp); - } - [pool drain]; - return _bootstrap_look_up3(bp, service_name, sp, target_pid, instance_id, flags); -} - -static void hook_bootstrap_lookup(void) -{ - static bool hooked_bootstrap_look_up; - OSSpinLockLock(&spin_lock); - if (!hooked_bootstrap_look_up) { - MSHookFunction(bootstrap_look_up3, $bootstrap_look_up3, (void **)&_bootstrap_look_up3); - hooked_bootstrap_look_up = true; - } - OSSpinLockUnlock(&spin_lock); -} - -CFMessagePortRef rocketbootstrap_cfmessageportcreateremote(CFAllocatorRef allocator, CFStringRef name) -{ - if (rocketbootstrap_is_passthrough()) - return CFMessagePortCreateRemote(allocator, name); - hook_bootstrap_lookup(); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; - [threadDictionary setObject:(id)kCFBooleanTrue forKey:@"rocketbootstrap_intercept_next_lookup"]; - CFMessagePortRef result = CFMessagePortCreateRemote(allocator, name); - [threadDictionary removeObjectForKey:@"rocketbootstrap_intercept_next_lookup"]; - [pool drain]; - return result; -} - -kern_return_t rocketbootstrap_cfmessageportexposelocal(CFMessagePortRef messagePort) -{ - if (rocketbootstrap_is_passthrough()) - return 0; - CFStringRef name = CFMessagePortGetName(messagePort); - if (!name) - return -1; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - kern_return_t result = rocketbootstrap_unlock([(NSString *)name UTF8String]); - [pool drain]; - return result; -} - -@interface CPDistributedMessagingCenter : NSObject -- (void)_setupInvalidationSource; -@end - -%group messaging_center - -static bool has_hooked_messaging_center; - -%hook CPDistributedMessagingCenter - -- (mach_port_t)_sendPort -{ - if (objc_getAssociatedObject(self, &has_hooked_messaging_center)) { - mach_port_t *_sendPort = CHIvarRef(self, _sendPort, mach_port_t); - NSLock **_lock = CHIvarRef(self, _lock, NSLock *); - if (_sendPort && _lock) { - [*_lock lock]; - mach_port_t result = *_sendPort; - if (result == MACH_PORT_NULL) { - NSString **_centerName = CHIvarRef(self, _centerName, NSString *); - if (_centerName && *_centerName && [self respondsToSelector:@selector(_setupInvalidationSource)]) { - mach_port_t bootstrap = MACH_PORT_NULL; - task_get_bootstrap_port(mach_task_self(), &bootstrap); - rocketbootstrap_look_up(bootstrap, [*_centerName UTF8String], _sendPort); - [self _setupInvalidationSource]; - result = *_sendPort; - } - } - [*_lock unlock]; - return result; - } - } - return %orig(); -} - -- (void)runServerOnCurrentThreadProtectedByEntitlement:(id)entitlement -{ - if (objc_getAssociatedObject(self, &has_hooked_messaging_center)) { - NSString **_centerName = CHIvarRef(self, _centerName, NSString *); - if (_centerName && *_centerName) { - rocketbootstrap_unlock([*_centerName UTF8String]); - } - } - %orig(); -} - -%end - -%end - -void rocketbootstrap_distributedmessagingcenter_apply(CPDistributedMessagingCenter *messaging_center) -{ - if (rocketbootstrap_is_passthrough()) - return; - OSSpinLockLock(&spin_lock); - if (!has_hooked_messaging_center) { - has_hooked_messaging_center = true; - %init(messaging_center); - } - OSSpinLockUnlock(&spin_lock); - objc_setAssociatedObject(messaging_center, &has_hooked_messaging_center, (id)kCFBooleanTrue, OBJC_ASSOCIATION_ASSIGN); -} diff --git a/rocketbootstrap/Tweak.x b/rocketbootstrap/Tweak.x deleted file mode 100644 index 880ed76..0000000 --- a/rocketbootstrap/Tweak.x +++ /dev/null @@ -1,437 +0,0 @@ -#define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 0 -#define LIGHTMESSAGING_TIMEOUT 300 -#import "LightMessaging/LightMessaging.h" - -#import "rocketbootstrap_internal.h" - -#ifndef __APPLE_API_PRIVATE -#define __APPLE_API_PRIVATE -#include "sandbox.h" -#undef __APPLE_API_PRIVATE -#else -#include "sandbox.h" -#endif - -#import -#import -#import -//#import -#import -#import -#import - -extern int *_NSGetArgc(void); -extern const char ***_NSGetArgv(void); - -#define kUserAppsPath "/var/mobile/Applications/" -#define kSystemAppsPath "/Applications/" - -static BOOL isDaemon; - -static kern_return_t rocketbootstrap_look_up_with_timeout(mach_port_t bp, const name_t service_name, mach_port_t *sp, mach_msg_timeout_t timeout) -{ - if (rocketbootstrap_is_passthrough() || isDaemon) { - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_5_0) { - int sandbox_result = sandbox_check(getpid(), "mach-lookup", SANDBOX_FILTER_LOCAL_NAME | SANDBOX_CHECK_NO_REPORT, service_name); - if (sandbox_result) { - return sandbox_result; - } - } - return bootstrap_look_up(bp, service_name, sp); - } - // Compatibility mode for Flex, limits it to only the processes in rbs 1.0.1 and earlier - if (strcmp(service_name, "FLMessagingCenterSpringboard") == 0) { - const char **argv = *_NSGetArgv(); - size_t arg0len = strlen(argv[0]); - bool allowed = false; - if ((arg0len > sizeof(kUserAppsPath)) && (memcmp(argv[0], kUserAppsPath, sizeof(kUserAppsPath) - 1) == 0)) - allowed = true; - if ((arg0len > sizeof(kSystemAppsPath)) && (memcmp(argv[0], kSystemAppsPath, sizeof(kSystemAppsPath) - 1) == 0)) - allowed = true; - if (!allowed) - return 1; - } - // Ask our service running inside of the com.apple.ReportCrash.SimulateCrash job - mach_port_t servicesPort = MACH_PORT_NULL; - kern_return_t err = bootstrap_look_up(bp, "com.apple.ReportCrash.SimulateCrash", &servicesPort); - if (err) - return err; - mach_port_t selfTask = mach_task_self(); - // Create a reply port - mach_port_name_t replyPort = MACH_PORT_NULL; - err = mach_port_allocate(selfTask, MACH_PORT_RIGHT_RECEIVE, &replyPort); - if (err) { - mach_port_deallocate(selfTask, servicesPort); - return err; - } - // Send message - size_t service_name_size = strlen(service_name); - size_t size = (sizeof(_rocketbootstrap_lookup_query_t) + service_name_size + 3) & ~3; - if (size < sizeof(_rocketbootstrap_lookup_response_t)) { - size = sizeof(_rocketbootstrap_lookup_response_t); - } - char buffer[size]; - _rocketbootstrap_lookup_query_t *message = (_rocketbootstrap_lookup_query_t *)&buffer[0]; - memset(message, 0, sizeof(_rocketbootstrap_lookup_response_t)); - message->head.msgh_id = ROCKETBOOTSTRAP_LOOKUP_ID; - message->head.msgh_size = size; - message->head.msgh_remote_port = servicesPort; - message->head.msgh_local_port = replyPort; - message->head.msgh_reserved = 0; - message->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); - message->name_length = service_name_size; - memcpy(&message->name[0], service_name, service_name_size); - mach_msg_option_t options = MACH_SEND_MSG | MACH_RCV_MSG; - if (timeout == 0) { - timeout = MACH_MSG_TIMEOUT_NONE; - } else { - options |= MACH_SEND_TIMEOUT | MACH_RCV_TIMEOUT; - } - err = mach_msg(&message->head, options, size, size, replyPort, timeout, MACH_PORT_NULL); - // Parse response - if (!err) { - _rocketbootstrap_lookup_response_t *response = (_rocketbootstrap_lookup_response_t *)message; - if (response->body.msgh_descriptor_count) - *sp = response->response_port.name; - else - err = 1; - } - // Cleanup - mach_port_deallocate(selfTask, servicesPort); - mach_port_deallocate(selfTask, replyPort); - return err; -} - -kern_return_t rocketbootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp) -{ - return rocketbootstrap_look_up_with_timeout(bp, service_name, sp, LIGHTMESSAGING_TIMEOUT); -} - -static NSMutableSet *allowedNames; -static volatile OSSpinLock namesLock; - -static void daemon_restarted_callback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - OSSpinLockLock(&namesLock); - NSSet *allNames = [allowedNames copy]; - OSSpinLockUnlock(&namesLock); - for (NSString *name in allNames) { - const char *service_name = [name UTF8String]; - LMConnectionSendOneWay(&connection, 0, service_name, strlen(service_name)); - } - [allNames release]; - [pool drain]; -} - -kern_return_t rocketbootstrap_unlock(const name_t service_name) -{ - if (rocketbootstrap_is_passthrough()) - return 0; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSString *serviceNameString = [NSString stringWithUTF8String:service_name]; - OSSpinLockLock(&namesLock); - BOOL containedName; - if (!allowedNames) { - allowedNames = [[NSMutableSet alloc] init]; - [allowedNames addObject:serviceNameString]; - CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), &daemon_restarted_callback, daemon_restarted_callback, CFSTR("com.rpetrich.rocketd.started"), NULL, CFNotificationSuspensionBehaviorCoalesce); - containedName = NO; - } else { - containedName = [allowedNames containsObject:serviceNameString]; - if (!containedName) { - [allowedNames addObject:serviceNameString]; - } - } - OSSpinLockUnlock(&namesLock); - [pool drain]; - if (containedName) { - return 0; - } - // Ask rocketd to unlock it for us - int sandbox_result = sandbox_check(getpid(), "mach-lookup", SANDBOX_FILTER_LOCAL_NAME | SANDBOX_CHECK_NO_REPORT, kRocketBootstrapUnlockService); - if (sandbox_result) { - [pool drain]; - return sandbox_result; - } - return LMConnectionSendOneWay(&connection, 0, service_name, strlen(service_name)); -} - -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -kern_return_t rocketbootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp) -{ - kern_return_t err = rocketbootstrap_unlock(service_name); - if (err) - return err; - return bootstrap_register(bp, service_name, sp); -} -#pragma GCC diagnostic warning "-Wdeprecated-declarations" - -mach_msg_return_t mach_msg_server_once(boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_options_t options); - -mach_msg_return_t (*_mach_msg_server_once)(boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_options_t options); - -static volatile OSSpinLock server_once_lock; -static boolean_t (*server_once_demux_orig)(mach_msg_header_t *, mach_msg_header_t *); -static bool continue_server_once; - -static boolean_t new_demux(mach_msg_header_t *request, mach_msg_header_t *reply) -{ - // Highjack ROCKETBOOTSTRAP_LOOKUP_ID from the com.apple.ReportCrash.SimulateCrash demuxer - if (request->msgh_id == ROCKETBOOTSTRAP_LOOKUP_ID) { - continue_server_once = true; - _rocketbootstrap_lookup_query_t *lookup_message = (_rocketbootstrap_lookup_query_t *)request; - // Extract service name - size_t length = request->msgh_size - offsetof(_rocketbootstrap_lookup_query_t, name); - if (lookup_message->name_length <= length) { - length = lookup_message->name_length; - } - // Ask rocketd if it's unlocked - LMResponseBuffer buffer; - if (LMConnectionSendTwoWay(&connection, 1, &lookup_message->name[0], length, &buffer)) - return false; - BOOL nameIsAllowed = LMResponseConsumeInteger(&buffer) != 0; - // Lookup service port - mach_port_t servicePort = MACH_PORT_NULL; - mach_port_t selfTask = mach_task_self(); - kern_return_t err; - if (nameIsAllowed) { - mach_port_t bootstrap = MACH_PORT_NULL; - err = task_get_bootstrap_port(selfTask, &bootstrap); - if (!err) { - char *buffer = malloc(length + 1); - if (buffer) { - memcpy(buffer, lookup_message->name, length); - buffer[length] = '\0'; - err = bootstrap_look_up(bootstrap, buffer, &servicePort); - free(buffer); - } - } - } - // Generate response - _rocketbootstrap_lookup_response_t response; - response.head.msgh_id = 0; - response.head.msgh_size = (sizeof(_rocketbootstrap_lookup_response_t) + 3) & ~3; - response.head.msgh_remote_port = request->msgh_remote_port; - response.head.msgh_local_port = MACH_PORT_NULL; - response.head.msgh_reserved = 0; - response.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); - if (servicePort != MACH_PORT_NULL) { - response.head.msgh_bits |= MACH_MSGH_BITS_COMPLEX; - response.body.msgh_descriptor_count = 1; - response.response_port.name = servicePort; - response.response_port.disposition = MACH_MSG_TYPE_COPY_SEND; - response.response_port.type = MACH_MSG_PORT_DESCRIPTOR; - } else { - response.body.msgh_descriptor_count = 0; - } - // Send response - err = mach_msg(&response.head, MACH_SEND_MSG, response.head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (err) { - if (servicePort != MACH_PORT_NULL) - mach_port_mod_refs(selfTask, servicePort, MACH_PORT_RIGHT_SEND, -1); - mach_port_mod_refs(selfTask, reply->msgh_remote_port, MACH_PORT_RIGHT_SEND_ONCE, -1); - } - return true; - } - return server_once_demux_orig(request, reply); -} - -static mach_msg_return_t $mach_msg_server_once(boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_options_t options) -{ - // Highjack com.apple.ReportCrash.SimulateCrash's use of mach_msg_server_once - OSSpinLockLock(&server_once_lock); - if (!server_once_demux_orig) { - server_once_demux_orig = demux; - demux = new_demux; - } else if (server_once_demux_orig == demux) { - demux = new_demux; - } else { - OSSpinLockUnlock(&server_once_lock); - mach_msg_return_t result = _mach_msg_server_once(demux, max_size, rcv_name, options); - return result; - } - OSSpinLockUnlock(&server_once_lock); - mach_msg_return_t result; - do { - continue_server_once = false; - result = _mach_msg_server_once(demux, max_size, rcv_name, options); - } while (continue_server_once); - return result; -} - -static pid_t pid_of_process(const char *process_name) -{ - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; - size_t miblen = 4; - - size_t size; - int st = sysctl(mib, miblen, NULL, &size, NULL, 0); - - struct kinfo_proc * process = NULL; - struct kinfo_proc * newprocess = NULL; - - do { - size += size / 10; - newprocess = (struct kinfo_proc *)realloc(process, size); - - if (!newprocess) { - if (process) { - free(process); - } - return 0; - } - - process = newprocess; - st = sysctl(mib, miblen, process, &size, NULL, 0); - - } while (st == -1 && errno == ENOMEM); - - if (st == 0) { - if (size % sizeof(struct kinfo_proc) == 0) { - int nprocess = size / sizeof(struct kinfo_proc); - if (nprocess) { - for (int i = nprocess - 1; i >= 0; i--) { - if (strcmp(process[i].kp_proc.p_comm, process_name) == 0) { - pid_t result = process[i].kp_proc.p_pid; - free(process); - return result; - } - } - } - } - } - - free(process); - return 0; -} - -static int daemon_die_queue; -static CFFileDescriptorRef daemon_die_fd; -static CFRunLoopSourceRef daemon_die_source; - -static void process_terminate_callback(CFFileDescriptorRef fd, CFOptionFlags callBackTypes, void *info); - -static void observe_rocketd(void) -{ - // Force the daemon to load - mach_port_t bootstrap = MACH_PORT_NULL; - mach_port_t self = mach_task_self(); - task_get_bootstrap_port(self, &bootstrap); - mach_port_t servicesPort = MACH_PORT_NULL; - kern_return_t err = bootstrap_look_up(bootstrap, "com.rpetrich.rocketbootstrapd", &servicesPort); - if (err) { - //NSLog(@"RocketBootstrap: failed to launch rocketd!"); - } else { - mach_port_name_t replyPort = MACH_PORT_NULL; - err = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &replyPort); - if (err == 0) { - LMResponseBuffer buffer; - uint32_t size = LMBufferSizeForLength(0); - memset(&buffer.message, 0, sizeof(LMMessage)); - buffer.message.head.msgh_id = 2; - buffer.message.head.msgh_size = size; - buffer.message.head.msgh_local_port = replyPort; - buffer.message.head.msgh_reserved = 0; - buffer.message.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); - buffer.message.head.msgh_remote_port = servicesPort; - buffer.message.body.msgh_descriptor_count = 0; - buffer.message.data.in_line.length = 0; - err = mach_msg(&buffer.message.head, MACH_SEND_MSG | MACH_RCV_MSG | _LIGHTMESSAGING_TIMEOUT_FLAGS, size, sizeof(LMResponseBuffer), replyPort, LIGHTMESSAGING_TIMEOUT, MACH_PORT_NULL); - if (err) { - } - // Cleanup - mach_port_mod_refs(self, replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - } - mach_port_mod_refs(self, servicesPort, MACH_PORT_RIGHT_SEND, -1); - } - // Find it - pid_t pid = pid_of_process("rocketd"); - if (pid) { - //NSLog(@"RocketBootstrap: rocketd found: %d", pid); - daemon_die_queue = kqueue(); - struct kevent changes; - EV_SET(&changes, pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, NULL); - (void)kevent(daemon_die_queue, &changes, 1, &changes, 1, NULL); - daemon_die_fd = CFFileDescriptorCreate(NULL, daemon_die_queue, true, process_terminate_callback, NULL); - daemon_die_source = CFFileDescriptorCreateRunLoopSource(NULL, daemon_die_fd, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), daemon_die_source, kCFRunLoopDefaultMode); - CFFileDescriptorEnableCallBacks(daemon_die_fd, kCFFileDescriptorReadCallBack); - } else { - NSLog(@"RocketBootstrap: unable to find rocketd!"); - } -} - -static void process_terminate_callback(CFFileDescriptorRef fd, CFOptionFlags callBackTypes, void *info) -{ - struct kevent event; - (void)kevent(daemon_die_queue, NULL, 0, &event, 1, NULL); - NSLog(@"RocketBootstrap: rocketd terminated: %d, relaunching", (int)(pid_t)event.ident); - // Cleanup - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), daemon_die_source, kCFRunLoopDefaultMode); - CFRelease(daemon_die_source); - CFRelease(daemon_die_fd); - close(daemon_die_queue); - observe_rocketd(); -} - -static void SanityCheckNotificationCallback(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) -{ -} - -%ctor -{ - %init(); - // Attach rockets when in the com.apple.ReportCrash.SimulateCrash job - // (can't check in using the launchd APIs because it hates more than one checkin; this will do) - const char **argv = *_NSGetArgv(); - if (strcmp(argv[0], "/System/Library/CoreServices/ReportCrash") == 0 && argv[1] && strcmp(argv[1], "-f") == 0) { - isDaemon = YES; - MSHookFunction(mach_msg_server_once, $mach_msg_server_once, (void **)&_mach_msg_server_once); - } else if (strcmp(argv[0], "/System/Library/CoreServices/SpringBoard.app/SpringBoard") == 0) { - if (kCFCoreFoundationVersionNumber < 847.20) { - return; - } - // Sanity check on the SimulateCrash service - mach_port_t bootstrap = MACH_PORT_NULL; - mach_port_t self = mach_task_self(); - task_get_bootstrap_port(self, &bootstrap); - mach_port_t servicesPort = MACH_PORT_NULL; - kern_return_t err = bootstrap_look_up(bootstrap, "com.apple.ReportCrash.SimulateCrash", &servicesPort); - //bool has_simulate_crash; - if (err) { - //has_simulate_crash = false; - } else { - mach_port_mod_refs(self, servicesPort, MACH_PORT_RIGHT_SEND, -1); - //has_simulate_crash = true; - //servicesPort = MACH_PORT_NULL; - //err = bootstrap_look_up(bootstrap, "com.rpetrich.rocketbootstrapd", &servicesPort); - } - if (err == 0) { - mach_port_mod_refs(self, servicesPort, MACH_PORT_RIGHT_SEND, -1); - observe_rocketd(); - } else { - const CFTypeRef keys[] = { - kCFUserNotificationAlertHeaderKey, - kCFUserNotificationAlertMessageKey, - kCFUserNotificationDefaultButtonTitleKey, - }; - const CFTypeRef valuesCrash[] = { - CFSTR("System files missing!"), - CFSTR("RocketBootstrap has detected that your SimulateCrash crash reporting daemon is missing or disabled.\nThis daemon is required for proper operation of packages that depend on RocketBootstrap."), - CFSTR("OK"), - }; - /*const CFTypeRef valuesRocket[] = { - CFSTR("System files missing!"), - CFSTR("RocketBootstrap has detected that your rocketbootstrap daemon is missing or disabled.\nThis daemon is required for proper operation of packages that depend on RocketBootstrap."), - CFSTR("OK"), - };*/ - CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, /*has_simulate_crash ? (const void **)valuesRocket :*/ (const void **)valuesCrash, sizeof(keys) / sizeof(*keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - SInt32 err = 0; - CFUserNotificationRef notification = CFUserNotificationCreate(kCFAllocatorDefault, 0.0, kCFUserNotificationPlainAlertLevel, &err, dict); - CFRunLoopSourceRef runLoopSource = CFUserNotificationCreateRunLoopSource(kCFAllocatorDefault, notification, SanityCheckNotificationCallback, 0); - CFRunLoopAddSource(CFRunLoopGetMain(), runLoopSource, kCFRunLoopCommonModes); - CFRelease(dict); - } - } -} diff --git a/rocketbootstrap/bootstrap.h b/rocketbootstrap/bootstrap.h deleted file mode 100644 index 8cb5a2d..0000000 --- a/rocketbootstrap/bootstrap.h +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef __BOOTSTRAP_H__ -#define __BOOTSTRAP_H__ -/* - * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_APACHE_LICENSE_HEADER_START@ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @APPLE_APACHE_LICENSE_HEADER_END@ - */ - -/* - * bootstrap -- fundamental service initiator and port server - * Mike DeMoney, NeXT, Inc. - * Copyright, 1990. All rights reserved. - */ - -/* - * Interface: Bootstrap server - * - * The bootstrap server is the first user-mode task initiated by the Mach - * kernel at system boot time. The bootstrap server provides two services, - * it initiates other system tasks, and manages a table of name-port bindings - * for fundamental system services (e.g. lookupd, Window Manager, etc...). - * - * Name-port bindings can be established with the bootstrap server by either - * of two mechanisms: - * - * 1. The binding can be indicated, in advance of the service that backs it - * being available, via a "service create" request. In this case, bootstrap - * will immediately create a port and bind the indicated name with that port. - * At a later time, a service may "checkin" for the name-port - * binding and will be returned receive rights for the bound port. Lookup's - * on bindings created by this mechanism will return send rights to the port, - * even if no service has "checked-in". In this case, requests sent to the - * bound port will be queued until a server has checked-in and can satisfy the - * request. - * - * 2. Bindings can be established dynamically via a "register" request. In - * this case, the register request provides bootstrap with a name and send - * rights for a port. Bootstrap will provide send rights for the bound port - * to any requestor via the lookup request. - * - * Bootstrap provides its service port to descendant tasks via the Mach - * "bootstrap" special task port. All direct descendants of bootstrap receive - * a "privileged" bootstrap service port. System services that initiate - * untrusted tasks should replace the Mach bootstrap task special port with - * a subset bootstrap port to prevent them from infecting the namespace. - * - * The bootstrap server creates a "backup" port for each service that it - * creates. This is used to detect when a checked out service is no longer - * being served. The bootstrap server regains all rights to the port and - * it is marked available for check-out again. This allows crashed servers to - * resume service to previous clients. Lookup's on this named port will - * continue to be serviced by bootstrap while holding receive rights for the - * bound port. A client may detect that the service is inactive via the - * bootstrap status request. If an inactive service re-registers rather - * than "checking-in" the original bound port is destroyed. - * - * The status of a named service may be obtained via the "status" request. - * A service is "active" if a name-port binding exists and receive rights - * to the bound port are held by a task other than bootstrap. - * - * The bootstrap server may also (re)start server processes associated with - * with a set of services. The definition of the server process is done - * through the "create server" request. The server will be launched in the - * same bootstrap context in which it was registered. - */ -#include -#include -#include -#include -#include -#include - -__BEGIN_DECLS - -#pragma GCC visibility push(default) - -#define BOOTSTRAP_MAX_NAME_LEN 128 -#define BOOTSTRAP_MAX_CMD_LEN 512 - -typedef char name_t[BOOTSTRAP_MAX_NAME_LEN]; -typedef char cmd_t[BOOTSTRAP_MAX_CMD_LEN]; -typedef name_t *name_array_t; -typedef int bootstrap_status_t; -typedef bootstrap_status_t *bootstrap_status_array_t; -typedef unsigned int bootstrap_property_t; -typedef bootstrap_property_t * bootstrap_property_array_t; - -typedef boolean_t *bool_array_t; - -#define BOOTSTRAP_MAX_LOOKUP_COUNT 20 - -#define BOOTSTRAP_SUCCESS 0 -#define BOOTSTRAP_NOT_PRIVILEGED 1100 -#define BOOTSTRAP_NAME_IN_USE 1101 -#define BOOTSTRAP_UNKNOWN_SERVICE 1102 -#define BOOTSTRAP_SERVICE_ACTIVE 1103 -#define BOOTSTRAP_BAD_COUNT 1104 -#define BOOTSTRAP_NO_MEMORY 1105 -#define BOOTSTRAP_NO_CHILDREN 1106 - -#define BOOTSTRAP_STATUS_INACTIVE 0 -#define BOOTSTRAP_STATUS_ACTIVE 1 -#define BOOTSTRAP_STATUS_ON_DEMAND 2 - -/* - * After main() starts, it is safe to assume that this variable is always set. - */ -extern mach_port_t bootstrap_port; - -/* - * bootstrap_create_server() - * - * Declares a server that mach_init will re-spawn within the specified - * bootstrap context. The server is considered already "active" - * (i.e. will not be re-spawned) until the returned server_port is - * deallocated. - * - * In the meantime, services can be declared against the server, - * by using the server_port as the privileged bootstrap target of - * subsequent bootstrap_create_service() calls. - * - * When mach_init re-spawns the server, its task bootstrap port - * is set to the privileged sever_port. Through this special - * bootstrap port, it can access all of parent bootstrap's context - * (and all services are created in the parent's namespace). But - * all additional service declarations (and declaration removals) - * will be associated with this particular server. - * - * Only a holder of the server_port privilege bootstrap port can - * check in or register over those services. - * - * When all services associated with a server are deleted, and the server - * exits, it will automatically be deleted itself. - * - * If the server is declared "on_demand," then a non-running server - * will be re-launched on first use of one of the service ports - * registered against it. Otherwise, it will be re-launched - * immediately upon exiting (whether any client is actively using - * any of the service ports or not). - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_NOT_PRIVILEGED, bootstrap or uid invalid. - */ -kern_return_t bootstrap_create_server( - mach_port_t bp, - cmd_t server_cmd, - uid_t server_uid, - boolean_t on_demand, - mach_port_t *server_port); - -/* - * bootstrap_subset() - * - * Returns a new port to use as a bootstrap port. This port behaves - * exactly like the previous bootstrap_port, except that ports dynamically - * registered via bootstrap_register() are available only to users of this - * specific subset_port. Lookups on the subset_port will return ports - * registered with this port specifically, and ports registered with - * ancestors of this subset_port. Duplications of services already - * registered with an ancestor port may be registered with the subset port - * are allowed. Services already advertised may then be effectively removed - * by registering PORT_NULL for the service. - * When it is detected that the requestor_port is destroyed the subset - * port and all services advertized by it are destroyed as well. - * - * Errors: Returns appropriate kernel errors on rpc failure. - */ -kern_return_t bootstrap_subset( - mach_port_t bp, - mach_port_t requestor_port, - mach_port_t *subset_port); - -/* - * bootstrap_unprivileged() - * - * Given a bootstrap port, return its unprivileged equivalent. If - * the port is already unprivileged, another reference to the same - * port is returned. - * - * This is most often used by servers, which are launched with their - * bootstrap port set to the privileged port for the server, to get - * an unprivileged version of the same port for use by its unprivileged - * children (or any offspring that it does not want to count as part - * of the "server" for mach_init registration and re-launch purposes). - * - * Native launchd jobs are always started with an unprivileged port. - */ -kern_return_t bootstrap_unprivileged( - mach_port_t bp, - mach_port_t *unpriv_port) - AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; - -/* - * bootstrap_parent() - * - * Given a bootstrap subset port, return the parent bootstrap port. - * If the specified bootstrap port is already the root subset, - * the same port will be returned. Much like "." and ".." are the same - * in the file system name space for the root directory ("/"). - * - * Errors: - * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running - * with an effective user id of root (as determined by the security - * token in the message trailer). - */ -kern_return_t bootstrap_parent( - mach_port_t bp, - mach_port_t *parent_port); - -/* - * bootstrap_register() - * - * Registers a send right for service_port with the service identified by - * service_name. Attempts to register a service where an active binding - * already exists are rejected. - * - * If the service was previously declared with bootstrap_create_service(), - * but is not currently active, this call can be used to undeclare the - * service. The bootstrap port used must have sufficient privilege to - * do so. (Registering MACH_PORT_NULL is especially useful for shutting - * down declared services). - * - * This API is deprecated. Old scenarios and recommendations: - * - * 1) Code that used to call bootstrap_check_in() and then bootstrap_register() - * can now always call bootstrap_check_in(). - * - * 2) If the code was registering a well known name, please switch to launchd. - * - * 3) If the code was registering a dynamically generated string and passing - * the string to other applications, please rewrite the code to send a Mach - * send-right directly. - * - * 4) If the launchd job maintained an optional Mach service, please reserve - * the name with launchd and control the presense of the service through - * ownership of the Mach receive right like so. - * - * MachServices - * - * com.apple.windowserver - * - * com.apple.windowserver.active - * - * HideUntilCheckIn - * - * - * - * - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to - * bootstrap port without privilege. - * Returns BOOTSTRAP_NAME_IN_USE, if service has already been - * register or checked-in. - */ -AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5 -kern_return_t -bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp); - -/* - * bootstrap_create_service() - * - * Creates a service named "service_name" and returns a send right to that - * port in "service_port." The port may later be checked in as if this - * port were configured in the bootstrap configuration file. - * - * This API is deprecated. Please call bootstrap_check_in() instead. - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_SERVICE_ACTIVE, if service already exists. - */ -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6 -AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6 -#endif -kern_return_t -bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp); - -/* - * bootstrap_check_in() - * - * Returns the receive right for the service named by service_name. The - * service must have been declared in the launchd.plist(5) file associated - * with the job. Attempts to check_in a service which is already active - * are not allowed. - * - * If the service was declared as being associated with a server, the - * check_in must come from the server's privileged port (server_port). - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist. - * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to - * bootstrap port without privilege. - * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been - * registered or checked-in. - */ -kern_return_t bootstrap_check_in( - mach_port_t bp, - const name_t service_name, - mach_port_t *sp); - -/* - * bootstrap_look_up() - * - * Returns a send right for the service port declared/registered under the - * name service_name. The service is not guaranteed to be active. Use the - * bootstrap_status call to determine the status of the service. - * - * Errors: Returns appropriate kernel errors on rpc failure. - * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist. - */ -kern_return_t bootstrap_look_up( - mach_port_t bp, - const name_t service_name, - mach_port_t *sp); - -/* - * bootstrap_status() - * - * In practice, this call was used to preflight whether the following two - * APIs would succeed. - * - * bootstrap_look_up() - * bootstrap_check_in() - * - * Please don't bother. Just call the above two APIs directly and check - * for failure. - */ -kern_return_t bootstrap_status( - mach_port_t bp, - name_t service_name, - bootstrap_status_t *service_active) - AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; - -/* bootstrap_strerror() - * - * Translate a return value from the bootstrap_*() APIs to a string. - */ -const char *bootstrap_strerror(kern_return_t r) __attribute__((__nothrow__, __pure__, __warn_unused_result__)); - -#pragma GCC visibility pop - -__END_DECLS - -#endif /* __BOOTSTRAP_H__ */ \ No newline at end of file diff --git a/rocketbootstrap/framework b/rocketbootstrap/framework deleted file mode 120000 index 11eaf40..0000000 --- a/rocketbootstrap/framework +++ /dev/null @@ -1 +0,0 @@ -../theos \ No newline at end of file diff --git a/rocketbootstrap/layout/DEBIAN/control b/rocketbootstrap/layout/DEBIAN/control deleted file mode 100644 index 94faa23..0000000 --- a/rocketbootstrap/layout/DEBIAN/control +++ /dev/null @@ -1,14 +0,0 @@ -Package: com.rpetrich.rocketbootstrap -Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 3.0) -Name: RocketBootstrap -Version: 1.0.4 -Architecture: iphoneos-arm -Description: Support library allowing tweaks to communicate with sandboxed processes -Depiction: http://rpetri.ch/cydia/rocketbootstrap/ -Homepage: http://rpetri.ch/cydia/rocketbootstrap/ -Maintainer: BigBoss -Author: Ryan Petrich -Sponsor: thebigboss.org -Section: Tweaks -dev: rpetrich -Tag: purpose::extension, role::developer diff --git a/rocketbootstrap/layout/DEBIAN/postinst b/rocketbootstrap/layout/DEBIAN/postinst deleted file mode 100755 index e707090..0000000 --- a/rocketbootstrap/layout/DEBIAN/postinst +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -launchctl load /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist || true -launchctl stop com.apple.ReportCrash.SimulateCrash || true -mv /System/Library/LaunchDaemons{BAK,}/com.apple.ReportCrash.SimulateCrash.plist 2> /dev/null || true -launchctl load /System/Library/LaunchDaemons/com.apple.ReportCrash.SimulateCrash.plist 2> /dev/null || true diff --git a/rocketbootstrap/layout/DEBIAN/prerm b/rocketbootstrap/layout/DEBIAN/prerm deleted file mode 100755 index e0396bf..0000000 --- a/rocketbootstrap/layout/DEBIAN/prerm +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -launchctl unload /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist || true -launchctl stop com.apple.ReportCrash.SimulateCrash || true diff --git a/rocketbootstrap/layout/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist b/rocketbootstrap/layout/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist deleted file mode 100644 index 7199614..0000000 --- a/rocketbootstrap/layout/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - ProgramArguments - - /usr/libexec/rocketd - - OnDemand - - UserName - mobile - MachServices - - com.rpetrich.rocketbootstrapd - - - Label - com.rpetrich.rocketbootstrapd - JetsamProperties - - JetsamPriority - 18 - - - diff --git a/rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib b/rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib deleted file mode 120000 index 717e877..0000000 --- a/rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/librocketbootstrap.dylib \ No newline at end of file diff --git a/rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist b/rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist deleted file mode 100644 index 13a5b4a..0000000 --- a/rocketbootstrap/layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Filter - - Executables - - ReportCrash - - CoreFoundationVersion - - 800 - - - - diff --git a/rocketbootstrap/overlayheaders b/rocketbootstrap/overlayheaders deleted file mode 120000 index 80cf74d..0000000 --- a/rocketbootstrap/overlayheaders +++ /dev/null @@ -1 +0,0 @@ -../overlayheaders/ \ No newline at end of file diff --git a/rocketbootstrap/rocketbootstrap.h b/rocketbootstrap/rocketbootstrap.h index ca5b890..cb7ee03 100644 --- a/rocketbootstrap/rocketbootstrap.h +++ b/rocketbootstrap/rocketbootstrap.h @@ -1,3 +1,6 @@ +#ifndef ROCKETBOOTSTRAP_H +#define ROCKETBOOTSTRAP_H + #include #include #include "bootstrap.h" @@ -5,23 +8,54 @@ __BEGIN_DECLS #ifndef ROCKETBOOTSTRAP_LOAD_DYNAMIC -kern_return_t rocketbootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp); +// Look up a port by service name +kern_return_t rocketbootstrap_look_up(mach_port_t bootstrap_port, const name_t service_name, mach_port_t *out_service_port); + +// Grant system-wide access to a particular service name +// Note: Will return an error if called from within a sandboxed process +kern_return_t rocketbootstrap_unlock(const name_t service_name); +// Register a port with and grant system-wide access to a particular service name +// Note: Will return an error if called from within a sandboxed process +kern_return_t rocketbootstrap_register(mach_port_t bootstrap_port, name_t service_name, mach_port_t service_port); -kern_return_t rocketbootstrap_unlock(const name_t service_name); // Errors if not in a privileged process such as SpringBoard or backboardd -kern_return_t rocketbootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp); // Errors if not in a privileged process such as SpringBoard or backboardd +// CFMessagePort helpers #ifdef __COREFOUNDATION_CFMESSAGEPORT__ +// Acquire access to a system-wide CFMessagePort service CFMessagePortRef rocketbootstrap_cfmessageportcreateremote(CFAllocatorRef allocator, CFStringRef name); +// Expose access to a CFMessagePort service +// Note: Will return an error if called from within a sandboxed process kern_return_t rocketbootstrap_cfmessageportexposelocal(CFMessagePortRef messagePort); #endif + +// CPDistributedMessagingCenter helpers + #ifdef __OBJC__ +// Unlock access to a system-wide CPDistributedMessagingCenter service +// Note: Server processes may only run inside privileged processes @class CPDistributedMessagingCenter; void rocketbootstrap_distributedmessagingcenter_apply(CPDistributedMessagingCenter *messaging_center); #endif + +// XPC helpers + +#ifdef __XPC_CONNECTION_H__ +// Create an XPC connection representing a system-wide service +// flags should be XPC_CONNECTION_MACH_SERVICE_LISTENER for a listener connection, and 0 for a client client connection +// XPC_CONNECTION_MACH_SERVICE_LISTENER will return an error if called from within a sandboxed process +// 0 will return an error if the service name hasn't been registered +xpc_connection_t rocketbootstrap_xpc_connection_create(const char *name, dispatch_queue_t targetq, uint64_t flags); +// Copy the application bundle identifier of the peer connection +xpc_object_t rocketbootstrap_xpc_connection_copy_application_identifier(xpc_connection_t connection); +#endif + + #else #include "rocketbootstrap_dynamic.h" #endif __END_DECLS + +#endif diff --git a/rocketbootstrap/rocketbootstrap_dynamic.h b/rocketbootstrap/rocketbootstrap_dynamic.h index 45585d1..e5fe5c9 100644 --- a/rocketbootstrap/rocketbootstrap_dynamic.h +++ b/rocketbootstrap/rocketbootstrap_dynamic.h @@ -2,16 +2,43 @@ // Set ROCKETBOOTSTRAP_LOAD_DYNAMIC and then include rocketbootstrap.h #include +#if __has_include() +#include + +__attribute__((unused)) +static void *_rocketbootstrap_dlsym_func(const char *name) { + void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); + if (handle) { + void *result = dlsym(handle, name); + if (result) { + return ptrauth_sign_unauthenticated(ptrauth_strip(result, ptrauth_key_function_pointer), ptrauth_key_function_pointer, 0); + } + } + return NULL; +} + +#else + +__attribute__((unused)) +static void *_rocketbootstrap_dlsym_func(const char *name) { + void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); + if (handle) { + return dlsym(handle, name); + } + return NULL; +} + +#endif + __attribute__((unused)) static kern_return_t rocketbootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp) { static kern_return_t (*impl)(mach_port_t bp, const name_t service_name, mach_port_t *sp); if (!impl) { - void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); - if (handle) - impl = dlsym(handle, "rocketbootstrap_look_up"); - if (!impl) + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_look_up"); + if (!impl) { impl = bootstrap_look_up; + } } return impl(bp, service_name, sp); } @@ -21,11 +48,10 @@ static kern_return_t rocketbootstrap_unlock(const name_t service_name) { static kern_return_t (*impl)(const name_t service_name); if (!impl) { - void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); - if (handle) - impl = dlsym(handle, "rocketbootstrap_unlock"); - if (!impl) + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_unlock"); + if (!impl) { return -1; + } } return impl(service_name); } @@ -36,11 +62,10 @@ static kern_return_t rocketbootstrap_register(mach_port_t bp, name_t service_nam { static kern_return_t (*impl)(mach_port_t bp, name_t service_name, mach_port_t sp); if (!impl) { - void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); - if (handle) - impl = dlsym(handle, "rocketbootstrap_register"); - if (!impl) + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_register"); + if (!impl) { impl = bootstrap_register; + } } return impl(bp, service_name, sp); } @@ -52,11 +77,10 @@ static CFMessagePortRef rocketbootstrap_cfmessageportcreateremote(CFAllocatorRef { static CFMessagePortRef (*impl)(CFAllocatorRef allocator, CFStringRef name); if (!impl) { - void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); - if (handle) - impl = dlsym(handle, "rocketbootstrap_cfmessageportcreateremote"); - if (!impl) + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_cfmessageportcreateremote"); + if (!impl) { impl = CFMessagePortCreateRemote; + } } return impl(allocator, name); } @@ -65,11 +89,10 @@ static kern_return_t rocketbootstrap_cfmessageportexposelocal(CFMessagePortRef m { static kern_return_t (*impl)(CFMessagePortRef messagePort); if (!impl) { - void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); - if (handle) - impl = dlsym(handle, "rocketbootstrap_cfmessageportexposelocal"); - if (!impl) + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_cfmessageportexposelocal"); + if (!impl) { return -1; + } } return impl(messagePort); } @@ -82,12 +105,36 @@ static void rocketbootstrap_distributedmessagingcenter_apply(CPDistributedMessag { static void (*impl)(CPDistributedMessagingCenter *messagingCenter); if (!impl) { - void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); - if (handle) - impl = dlsym(handle, "rocketbootstrap_distributedmessagingcenter_apply"); + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_distributedmessagingcenter_apply"); if (!impl) return; } impl(messaging_center); } #endif + +#ifdef __XPC_CONNECTION_H__ +__attribute__((unused)) +static xpc_connection_t rocketbootstrap_xpc_connection_create(const char *name, dispatch_queue_t targetq, uint64_t flags) +{ + static xpc_connection_t (*impl)(const char *name, dispatch_queue_t targetq, uint64_t flags); + if (!impl) { + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_xpc_connection_create"); + if (!impl) + return NULL; + } + return impl(name, targetq, flags); +} + +__attribute__((unused)) +static xpc_object_t rocketbootstrap_xpc_connection_copy_application_identifier(xpc_connection_t connection) +{ + static xpc_object_t (*impl)(xpc_connection_t connection); + if (!impl) { + impl = _rocketbootstrap_dlsym_func("rocketbootstrap_xpc_connection_copy_application_identifier"); + if (!impl) + return NULL; + } + return impl(connection); +} +#endif diff --git a/rocketbootstrap/rocketbootstrap_internal.h b/rocketbootstrap/rocketbootstrap_internal.h deleted file mode 100644 index 6244b2b..0000000 --- a/rocketbootstrap/rocketbootstrap_internal.h +++ /dev/null @@ -1,36 +0,0 @@ -#import - -#import "rocketbootstrap.h" - -#define kRocketBootstrapUnlockService "com.rpetrich.rocketbootstrapd" - -#define ROCKETBOOTSTRAP_LOOKUP_ID -1 - -typedef struct { - mach_msg_header_t head; - mach_msg_body_t body; - uint32_t name_length; - char name[]; -} _rocketbootstrap_lookup_query_t; - -typedef struct { - mach_msg_header_t head; - mach_msg_body_t body; - mach_msg_port_descriptor_t response_port; -} _rocketbootstrap_lookup_response_t; - -#import "LightMessaging/LightMessaging.h" - -__attribute__((unused)) -static LMConnection connection = { - MACH_PORT_NULL, - kRocketBootstrapUnlockService -}; - -__attribute__((unused)) -static inline bool rocketbootstrap_is_passthrough(void) -{ - return kCFCoreFoundationVersionNumber < 800.0; -} - -kern_return_t _rocketbootstrap_is_unlocked(const name_t service_name); // Errors if not in a privileged process such as SpringBoard or backboardd diff --git a/rocketbootstrap/rocketd.c b/rocketbootstrap/rocketd.c deleted file mode 100644 index 067fab6..0000000 --- a/rocketbootstrap/rocketd.c +++ /dev/null @@ -1,67 +0,0 @@ -#import -#import -#define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 0 - -#import "rocketbootstrap_internal.h" - -static CFMutableSetRef allowedNames; - -static const uint32_t one = 1; - -static void machPortCallback(CFMachPortRef port, void *bytes, CFIndex size, void *info) -{ - LMMessage *request = bytes; - if (!LMDataWithSizeIsValidMessage(bytes, size)) { - LMSendReply(request->head.msgh_remote_port, NULL, 0); - LMResponseBufferFree(bytes); - return; - } - // Send Response - const void *data = LMMessageGetData(request); - size_t length = LMMessageGetDataLength(request); - const void *reply_data = NULL; - uint32_t reply_length = 0; - if (length) { - CFStringRef name = CFStringCreateWithBytes(kCFAllocatorDefault, data, length, kCFStringEncodingUTF8, false); - if (name) { - switch (request->head.msgh_id) { - case 0: // Register -#ifdef DEBUG - CFLog(kCFLogLevelWarning, CFSTR("Unlocking %@"), name); -#endif - CFSetAddValue(allowedNames, name); - break; - case 1: // Query - if (CFSetContainsValue(allowedNames, name)) { - reply_data = &one; - reply_length = sizeof one; -#ifdef DEBUG - CFLog(kCFLogLevelWarning, CFSTR("Queried %@, is unlocked"), name); -#endif - } else { -#ifdef DEBUG - CFLog(kCFLogLevelWarning, CFSTR("Queried %@, is locked!"), name); -#endif - } - break; - case 2: - // Good morning, still awake - reply_data = &one; - reply_length = sizeof one; - break; - } - CFRelease(name); - } - } - LMSendReply(request->head.msgh_remote_port, reply_data, reply_length); - LMResponseBufferFree(bytes); -} - -int main(int argc, char *argv[]) -{ - allowedNames = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); - LMCheckInService(connection.serverName, CFRunLoopGetCurrent(), machPortCallback, NULL); - notify_post("com.rpetrich.rocketd.started"); - CFRunLoopRun(); - return 0; -} diff --git a/rocketbootstrap/sandbox.h b/rocketbootstrap/sandbox.h deleted file mode 100644 index ad38b0b..0000000 --- a/rocketbootstrap/sandbox.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2006-2010 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _SANDBOX_H_ -#define _SANDBOX_H_ - -#include -#include -#include - -__BEGIN_DECLS -/* - * @function sandbox_init - * Places the current process in a sandbox with a profile as - * specified. If the process is already in a sandbox, the new profile - * is ignored and sandbox_init() returns an error. - * - * @param profile (input) The Sandbox profile to be used. The format - * and meaning of this parameter is modified by the `flags' parameter. - * - * @param flags (input) Must be SANDBOX_NAMED. All other - * values are reserved. - * - * @param errorbuf (output) In the event of an error, sandbox_init - * will set `*errorbuf' to a pointer to a NUL-terminated string - * describing the error. This string may contain embedded newlines. - * This error information is suitable for developers and is not - * intended for end users. - * - * If there are no errors, `*errorbuf' will be set to NULL. The - * buffer `*errorbuf' should be deallocated with `sandbox_free_error'. - * - * @result 0 on success, -1 otherwise. - */ -int sandbox_init(const char *profile, uint64_t flags, char **errorbuf); - -/* - * @define SANDBOX_NAMED The `profile' argument specifies a Sandbox - * profile named by one of the kSBXProfile* string constants. - */ -#define SANDBOX_NAMED 0x0001 - -#ifdef __APPLE_API_PRIVATE - -/* The following flags are reserved for Mac OS X. Developers should not - * depend on their availability. - */ - -/* - * @define SANDBOX_NAMED_BUILTIN The `profile' argument specifies the - * name of a builtin profile that is statically compiled into the - * system. - */ -#define SANDBOX_NAMED_BUILTIN 0x0002 - -/* - * @define SANDBOX_NAMED_EXTERNAL The `profile' argument specifies the - * pathname of a Sandbox profile. The pathname may be abbreviated: If - * the name does not start with a `/' it is treated as relative to - * /usr/share/sandbox and a `.sb' suffix is appended. - */ -#define SANDBOX_NAMED_EXTERNAL 0x0003 - -/* - * @define SANDBOX_NAMED_MASK Mask for name types: 4 bits, 15 possible - * name types, 3 currently defined. - */ -#define SANDBOX_NAMED_MASK 0x000f - -#endif /* __APPLE_API_PRIVATE */ - -/* - * Available Sandbox profiles. - */ - -/* TCP/IP networking is prohibited. */ -extern const char kSBXProfileNoInternet[]; - -/* All sockets-based networking is prohibited. */ -extern const char kSBXProfileNoNetwork[]; - -/* File system writes are prohibited. */ -extern const char kSBXProfileNoWrite[]; - -/* File system writes are restricted to temporary folders /var/tmp and - * confstr(_CS_DARWIN_USER_DIR, ...). - */ -extern const char kSBXProfileNoWriteExceptTemporary[]; - -/* All operating system services are prohibited. */ -extern const char kSBXProfilePureComputation[]; - -/* - * @function sandbox_free_error - * Deallocates an error string previously allocated by sandbox_init. - * - * @param errorbuf (input) The buffer to be freed. Must be a pointer - * previously returned by sandbox_init in the `errorbuf' argument, or NULL. - * - * @result void - */ -void sandbox_free_error(char *errorbuf); - - -#ifdef __APPLE_API_PRIVATE - -/* The following definitions are reserved for Mac OS X. Developers should not - * depend on their availability. - */ - -int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); - -int sandbox_init_with_extensions(const char *profile, uint64_t flags, const char *const extensions[], char **errorbuf); - -enum sandbox_filter_type { - SANDBOX_FILTER_NONE, - SANDBOX_FILTER_PATH, - SANDBOX_FILTER_GLOBAL_NAME, - SANDBOX_FILTER_LOCAL_NAME, - SANDBOX_FILTER_APPLEEVENT_DESTINATION, - SANDBOX_FILTER_RIGHT_NAME, -}; - -extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT __attribute__((weak_import)); - -enum sandbox_extension_flags { - FS_EXT_DEFAULTS = 0, - FS_EXT_FOR_PATH = (1 << 0), - FS_EXT_FOR_FILE = (1 << 1), - FS_EXT_READ = (1 << 2), - FS_EXT_WRITE = (1 << 3), - FS_EXT_PREFER_FILEID = (1 << 4), -}; - -int sandbox_check(pid_t pid, const char *operation, enum sandbox_filter_type type, ...); - -int sandbox_note(const char *note); - -int sandbox_suspend(pid_t pid); -int sandbox_unsuspend(void); - -int sandbox_issue_extension(const char *path, char **ext_token); -int sandbox_issue_fs_extension(const char *path, uint64_t flags, char **ext_token); -int sandbox_issue_fs_rw_extension(const char *path, char **ext_token); -int sandbox_issue_mach_extension(const char *name, char **ext_token); - -int sandbox_consume_extension(const char *path, const char *ext_token); -int sandbox_consume_fs_extension(const char *ext_token, char **path); -int sandbox_consume_mach_extension(const char *ext_token, char **name); - -int sandbox_release_fs_extension(const char *ext_token); - -int sandbox_container_path_for_pid(pid_t pid, char *buffer, size_t bufsize); - -int sandbox_wakeup_daemon(char **errorbuf); - -const char *_amkrtemp(const char *); - -#endif /* __APPLE_API_PRIVATE */ - -__END_DECLS -#endif /* _SANDBOX_H_ */ diff --git a/rocketbootstrap/tests/Makefile b/rocketbootstrap/tests/Makefile deleted file mode 100644 index 21a8f60..0000000 --- a/rocketbootstrap/tests/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -LIBRARY_NAME = librocketbootstrap_tests -librocketbootstrap_tests_FILES = tests.m -librocketbootstrap_tests_LIBRARIES = rocketbootstrap -librocketbootstrap_tests_FRAMEWORKS = Foundation UIKit - -ADDITIONAL_CFLAGS = -std=c99 -I../ - -IPHONE_ARCHS = armv6 arm64 - -SDKVERSION_armv6 = 5.1 -INCLUDE_SDKVERSION_armv6 = 8.4 -TARGET_IPHONEOS_DEPLOYMENT_VERSION = 4.0 - -TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv6 = 3.0 -THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode_Legacy.app/Contents/Developer - -include framework/makefiles/common.mk -include framework/makefiles/library.mk diff --git a/rocketbootstrap/tests/control b/rocketbootstrap/tests/control deleted file mode 100644 index 78db715..0000000 --- a/rocketbootstrap/tests/control +++ /dev/null @@ -1,11 +0,0 @@ -Package: com.rpetrich.rocketbootstrap.tests -Depends: com.rpetrich.rocketbootstrap -Name: RocketBootstrap Tests -Version: 0.1 -Architecture: iphoneos-arm -Description: Tests for RocketBootstrap -Maintainer: BigBoss -Author: Ryan Petrich -Sponsor: thebigboss.org -Section: Tweaks -dev: rpetrich diff --git a/rocketbootstrap/tests/framework b/rocketbootstrap/tests/framework deleted file mode 120000 index 12f27c9..0000000 --- a/rocketbootstrap/tests/framework +++ /dev/null @@ -1 +0,0 @@ -../framework \ No newline at end of file diff --git a/rocketbootstrap/tests/tests.m b/rocketbootstrap/tests/tests.m deleted file mode 100644 index f117a48..0000000 --- a/rocketbootstrap/tests/tests.m +++ /dev/null @@ -1,43 +0,0 @@ -#import - -#import "rocketbootstrap.h" - -@implementation NSObject (rocketbootstrap) - -+ (kern_return_t)rocketbootstrap_unlock:(NSString *)name -{ - return rocketbootstrap_unlock([name UTF8String]); -} - -static CFDataRef messagePortCallback(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info) -{ - NSLog(@"rockettest_messageport_server: received %@", data); - return CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"bootstrap", 9); -} - -+ (kern_return_t)rockettest_messageport_server -{ - static CFMessagePortRef messagePort; - if (messagePort) - return 0; - messagePort = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("rockettest_messageport"), messagePortCallback, NULL, NULL); - CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, messagePort, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); - CFRunLoopAddSource(CFRunLoopGetCurrent(), source, (CFStringRef)UITrackingRunLoopMode); - return rocketbootstrap_cfmessageportexposelocal(messagePort); -} - -+ (NSData *)rockettest_messageport_client -{ - CFMessagePortRef remote = rocketbootstrap_cfmessageportcreateremote(kCFAllocatorDefault, CFSTR("rockettest_messageport")); - if (!remote) - return nil; - CFDataRef request = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"rocket", 6); - CFDataRef response = NULL; - CFMessagePortSendRequest(remote, 0, request, 10, 10, CFSTR("rocketboostrap_wait"), &response); - CFRelease(remote); - CFRelease(request); - return [(NSData *)response autorelease]; -} - -@end From bc4a510a9a88d7a8b5208ee063007368a315c341 Mon Sep 17 00:00:00 2001 From: Lightmann Date: Sun, 14 Aug 2022 13:57:46 -0400 Subject: [PATCH 3/6] Bring LICENSE.md up-to-speed --- LICENSE.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index c862d35..8cf434e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -3,8 +3,8 @@ There is no particular license on this repo. Files in this repo come from many s ## By Author ### Apple -* IOKit headers: [Apple Public Source License](https://opensource.apple.com/license/apsl/) -* MediaPlayer, Celestial headers: [2-Clause BSD License](https://github.com/WebKit/webkit/blob/master/Source/WebCore/LICENSE-APPLE) +* IOKit: [Apple Public Source License](https://opensource.apple.com/license/apsl/) +* MediaPlayer, Celestial: [2-Clause BSD License](https://github.com/WebKit/webkit/blob/master/Source/WebCore/LICENSE-APPLE) * launch.h: [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) ### ashikase @@ -12,14 +12,26 @@ There is no particular license on this repo. Files in this repo come from many s * libpackageinfo: [GNU GPL v3](https://github.com/ashikase/libpackageinfo/blob/master/LICENSE) * TechSupport: [GNU LGPL v3, Apache License 2](https://github.com/ashikase/TechSupport/blob/master/LICENSE) +### CreatureSurvive +* CSColorPicker: [MIT](https://github.com/CreatureSurvive/CSColorPicker/blob/master/CSColorPicker/LICENSE) + ### Cykey -* MediaRemote, MobileGestalt headers: [GNU GPL v3](https://github.com/Cykey/ios-reversed-headers/blob/master/LICENSE.txt) +* MediaRemote, MobileGestalt: [GNU GPL v3](https://github.com/Cykey/ios-reversed-headers/blob/master/LICENSE.txt) + +### Cynder +* libCozy: [dragon](https://github.com/cxnder/libCozy/blob/master/LICENSE) ### Dustin Howett * libprefs: [GNU LGPL v3](https://github.com/DHowett/preferenceloader/blob/master/LICENSE) ### KennyTM -* GraphicsServices, IOSurface, substrate2.h headers: [3-Clause BSD License](http://opensource.org/licenses/BSD-3-Clause) +* GraphicsServices, IOSurface, substrate2.h: [3-Clause BSD License](http://opensource.org/licenses/BSD-3-Clause) + +### Muirey03 +* libimagepicker: TBD + +### Nepeta & Andy Shin +* libmitsuha: [MIT](https://github.com/kritanta-ios-tweaks/StatusViz/blob/master/libmitsuha/LICENSE) ### OpenSSL * OpenSSL: [OpenSSL](https://www.openssl.org/source/license.html) @@ -35,10 +47,11 @@ There is no particular license on this repo. Files in this repo come from many s * RocketBootstrap (submodule): ? ### SaurikIT -* Cydia Substrate: Licensing is rather strange and unclear here. - * As of approximately version 0.9.3997, Cydia Substrate became closed source. It was previously GNU GPL v3. - * The header provided here is taken from Cydia Substrate 0.9.4001 (February 2013) and has a comment that indicates that it is licensed under [GNU LGPL v3](substrate.h). - * Cydia Substrate 0.9.5000 (December 2013) changed the license comment to GNU GPL v3. It is unclear why this has changed. +* substrate: [3-Clause BSD License](https://opensource.org/licenses/BSD-3-Clause) + +### SparkDev +* libSparkAppList: [WTFPL v2.0](https://github.com/SparkDev97/libSparkAppList/blob/master/LICENSE.md) +* libSparkColourPicker: [WTFPL v2.0](https://github.com/SparkDev97/libSparkColourPicker/blob/master/LICENSE.md) ### Other headers Headers that aren't from elsewhere are released into the Public Domain. From 1f863dedccea5bae5b45bbaf1d21476aa0da8a1b Mon Sep 17 00:00:00 2001 From: Lightmann Date: Sun, 14 Aug 2022 13:59:10 -0400 Subject: [PATCH 4/6] Two more small things in LICENSE.md --- LICENSE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 8cf434e..9a346c6 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -8,7 +8,7 @@ There is no particular license on this repo. Files in this repo come from many s * launch.h: [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) ### ashikase -* IconSupport: ? +* IconSupport: Unknown * libpackageinfo: [GNU GPL v3](https://github.com/ashikase/libpackageinfo/blob/master/LICENSE) * TechSupport: [GNU LGPL v3, Apache License 2](https://github.com/ashikase/TechSupport/blob/master/LICENSE) @@ -43,8 +43,8 @@ There is no particular license on this repo. Files in this repo come from many s * AppList: [GNU LGPL v2.1](https://github.com/rpetrich/AppList/blob/master/LICENSE) * CaptainHook (submodule): [MIT License](http://mit-license.org/) * libactivator (submodule): [GNU LGPL v2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) -* LightMessaging (submodule): ? -* RocketBootstrap (submodule): ? +* LightMessaging (submodule): Unknown +* RocketBootstrap (submodule): Unknown ### SaurikIT * substrate: [3-Clause BSD License](https://opensource.org/licenses/BSD-3-Clause) From f8a86b5712754d0324593a22439c1312eea342b9 Mon Sep 17 00:00:00 2001 From: Lightmann Date: Sun, 14 Aug 2022 14:00:58 -0400 Subject: [PATCH 5/6] Add libarchive headers --- LICENSE.md | 3 + libarchive/archive.h | 1210 ++++++++++++++++++++++++++++++++++++ libarchive/archive_entry.h | 721 +++++++++++++++++++++ 3 files changed, 1934 insertions(+) create mode 100644 libarchive/archive.h create mode 100644 libarchive/archive_entry.h diff --git a/LICENSE.md b/LICENSE.md index 9a346c6..e38d860 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -33,6 +33,9 @@ There is no particular license on this repo. Files in this repo come from many s ### Nepeta & Andy Shin * libmitsuha: [MIT](https://github.com/kritanta-ios-tweaks/StatusViz/blob/master/libmitsuha/LICENSE) +### libarchive +* libarchive: [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause) + ### OpenSSL * OpenSSL: [OpenSSL](https://www.openssl.org/source/license.html) diff --git a/libarchive/archive.h b/libarchive/archive.h new file mode 100644 index 0000000..75629a8 --- /dev/null +++ b/libarchive/archive.h @@ -0,0 +1,1210 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ + */ + +#ifndef ARCHIVE_H_INCLUDED +#define ARCHIVE_H_INCLUDED + +/* + * The version number is expressed as a single integer that makes it + * easy to compare versions at build time: for version a.b.c, the + * version number is printf("%d%03d%03d",a,b,c). For example, if you + * know your application requires version 2.12.108 or later, you can + * assert that ARCHIVE_VERSION_NUMBER >= 2012108. + */ +/* Note: Compiler will complain if this does not match archive_entry.h! */ +#define ARCHIVE_VERSION_NUMBER 3006002 + +#include +#include /* for wchar_t */ +#include /* For FILE * */ +#include /* For time_t */ + +/* + * Note: archive.h is for use outside of libarchive; the configuration + * headers (config.h, archive_platform.h, etc.) are purely internal. + * Do NOT use HAVE_XXX configuration macros to control the behavior of + * this header! If you must conditionalize, use predefined compiler and/or + * platform macros. + */ +#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 +# include +#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__) && !defined(__CLANG_INTTYPES_H) +# include +#endif + +/* Get appropriate definitions of 64-bit integer */ +#if !defined(__LA_INT64_T_DEFINED) +/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +# include /* ssize_t */ +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Large file support for Android */ +#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__) +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries or non-Windows needs no special declaration. */ +# define __LA_DECL +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__) +#define __LA_PRINTF(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 +# define __LA_DEPRECATED __attribute__((deprecated)) +#else +# define __LA_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The version number is provided as both a macro and a function. + * The macro identifies the installed header; the function identifies + * the library version (which may not be the same if you're using a + * dynamically-linked version of the library). Of course, if the + * header and library are very different, you should expect some + * strangeness. Don't do that. + */ +__LA_DECL int archive_version_number(void); + +/* + * Textual name/version of the library, useful for version displays. + */ +#define ARCHIVE_VERSION_ONLY_STRING "3.6.2dev" +#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING +__LA_DECL const char * archive_version_string(void); + +/* + * Detailed textual name/version of the library and its dependencies. + * This has the form: + * "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..." + * the list of libraries described here will vary depending on how + * libarchive was compiled. + */ +__LA_DECL const char * archive_version_details(void); + +/* + * Returns NULL if libarchive was compiled without the associated library. + * Otherwise, returns the version number that libarchive was compiled + * against. + */ +__LA_DECL const char * archive_zlib_version(void); +__LA_DECL const char * archive_liblzma_version(void); +__LA_DECL const char * archive_bzlib_version(void); +__LA_DECL const char * archive_liblz4_version(void); +__LA_DECL const char * archive_libzstd_version(void); + +/* Declare our basic types. */ +struct archive; +struct archive_entry; + +/* + * Error codes: Use archive_errno() and archive_error_string() + * to retrieve details. Unless specified otherwise, all functions + * that return 'int' use these codes. + */ +#define ARCHIVE_EOF 1 /* Found end of archive. */ +#define ARCHIVE_OK 0 /* Operation was successful. */ +#define ARCHIVE_RETRY (-10) /* Retry might succeed. */ +#define ARCHIVE_WARN (-20) /* Partial success. */ +/* For example, if write_header "fails", then you can't push data. */ +#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ +/* But if write_header is "fatal," then this archive is dead and useless. */ +#define ARCHIVE_FATAL (-30) /* No more operations are possible. */ + +/* + * As far as possible, archive_errno returns standard platform errno codes. + * Of course, the details vary by platform, so the actual definitions + * here are stored in "archive_platform.h". The symbols are listed here + * for reference; as a rule, clients should not need to know the exact + * platform-dependent error code. + */ +/* Unrecognized or invalid file format. */ +/* #define ARCHIVE_ERRNO_FILE_FORMAT */ +/* Illegal usage of the library. */ +/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */ +/* Unknown or unclassified error. */ +/* #define ARCHIVE_ERRNO_MISC */ + +/* + * Callbacks are invoked to automatically read/skip/write/open/close the + * archive. You can provide your own for complex tasks (like breaking + * archives across multiple tapes) or use standard ones built into the + * library. + */ + +/* Returns pointer and size of next block of data from archive. */ +typedef la_ssize_t archive_read_callback(struct archive *, + void *_client_data, const void **_buffer); + +/* Skips at most request bytes from archive and returns the skipped amount. + * This may skip fewer bytes than requested; it may even skip zero bytes. + * If you do skip fewer bytes than requested, libarchive will invoke your + * read callback and discard data as necessary to make up the full skip. + */ +typedef la_int64_t archive_skip_callback(struct archive *, + void *_client_data, la_int64_t request); + +/* Seeks to specified location in the file and returns the position. + * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h. + * Return ARCHIVE_FATAL if the seek fails for any reason. + */ +typedef la_int64_t archive_seek_callback(struct archive *, + void *_client_data, la_int64_t offset, int whence); + +/* Returns size actually written, zero on EOF, -1 on error. */ +typedef la_ssize_t archive_write_callback(struct archive *, + void *_client_data, + const void *_buffer, size_t _length); + +typedef int archive_open_callback(struct archive *, void *_client_data); + +typedef int archive_close_callback(struct archive *, void *_client_data); + +typedef int archive_free_callback(struct archive *, void *_client_data); + +/* Switches from one client data object to the next/prev client data object. + * This is useful for reading from different data blocks such as a set of files + * that make up one large file. + */ +typedef int archive_switch_callback(struct archive *, void *_client_data1, + void *_client_data2); + +/* + * Returns a passphrase used for encryption or decryption, NULL on nothing + * to do and give it up. + */ +typedef const char *archive_passphrase_callback(struct archive *, + void *_client_data); + +/* + * Codes to identify various stream filters. + */ +#define ARCHIVE_FILTER_NONE 0 +#define ARCHIVE_FILTER_GZIP 1 +#define ARCHIVE_FILTER_BZIP2 2 +#define ARCHIVE_FILTER_COMPRESS 3 +#define ARCHIVE_FILTER_PROGRAM 4 +#define ARCHIVE_FILTER_LZMA 5 +#define ARCHIVE_FILTER_XZ 6 +#define ARCHIVE_FILTER_UU 7 +#define ARCHIVE_FILTER_RPM 8 +#define ARCHIVE_FILTER_LZIP 9 +#define ARCHIVE_FILTER_LRZIP 10 +#define ARCHIVE_FILTER_LZOP 11 +#define ARCHIVE_FILTER_GRZIP 12 +#define ARCHIVE_FILTER_LZ4 13 +#define ARCHIVE_FILTER_ZSTD 14 + +#if ARCHIVE_VERSION_NUMBER < 4000000 +#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE +#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP +#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2 +#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS +#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM +#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA +#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ +#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU +#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM +#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP +#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP +#endif + +/* + * Codes returned by archive_format. + * + * Top 16 bits identifies the format family (e.g., "tar"); lower + * 16 bits indicate the variant. This is updated by read_next_header. + * Note that the lower 16 bits will often vary from entry to entry. + * In some cases, this variation occurs as libarchive learns more about + * the archive (for example, later entries might utilize extensions that + * weren't necessary earlier in the archive; in this case, libarchive + * will change the format code to indicate the extended format that + * was used). In other cases, it's because different tools have + * modified the archive and so different parts of the archive + * actually have slightly different formats. (Both tar and cpio store + * format codes in each entry, so it is quite possible for each + * entry to be in a different format.) + */ +#define ARCHIVE_FORMAT_BASE_MASK 0xff0000 +#define ARCHIVE_FORMAT_CPIO 0x10000 +#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) +#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) +#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) +#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) +#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) +#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) +#define ARCHIVE_FORMAT_CPIO_PWB (ARCHIVE_FORMAT_CPIO | 7) +#define ARCHIVE_FORMAT_SHAR 0x20000 +#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) +#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) +#define ARCHIVE_FORMAT_TAR 0x30000 +#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) +#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) +#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) +#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) +#define ARCHIVE_FORMAT_ISO9660 0x40000 +#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) +#define ARCHIVE_FORMAT_ZIP 0x50000 +#define ARCHIVE_FORMAT_EMPTY 0x60000 +#define ARCHIVE_FORMAT_AR 0x70000 +#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) +#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) +#define ARCHIVE_FORMAT_MTREE 0x80000 +#define ARCHIVE_FORMAT_RAW 0x90000 +#define ARCHIVE_FORMAT_XAR 0xA0000 +#define ARCHIVE_FORMAT_LHA 0xB0000 +#define ARCHIVE_FORMAT_CAB 0xC0000 +#define ARCHIVE_FORMAT_RAR 0xD0000 +#define ARCHIVE_FORMAT_7ZIP 0xE0000 +#define ARCHIVE_FORMAT_WARC 0xF0000 +#define ARCHIVE_FORMAT_RAR_V5 0x100000 + +/* + * Codes returned by archive_read_format_capabilities(). + * + * This list can be extended with values between 0 and 0xffff. + * The original purpose of this list was to let different archive + * format readers expose their general capabilities in terms of + * encryption. + */ +#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */ + +/* + * Codes returned by archive_read_has_encrypted_entries(). + * + * In case the archive does not support encryption detection at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader + * for some other reason (e.g. not enough bytes read) cannot say if + * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW + * is returned. + */ +#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2 +#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1 + +/*- + * Basic outline for reading an archive: + * 1) Ask archive_read_new for an archive reader object. + * 2) Update any global properties as appropriate. + * In particular, you'll certainly want to call appropriate + * archive_read_support_XXX functions. + * 3) Call archive_read_open_XXX to open the archive + * 4) Repeatedly call archive_read_next_header to get information about + * successive archive entries. Call archive_read_data to extract + * data for entries of interest. + * 5) Call archive_read_free to end processing. + */ +__LA_DECL struct archive *archive_read_new(void); + +/* + * The archive_read_support_XXX calls enable auto-detect for this + * archive handle. They also link in the necessary support code. + * For example, if you don't want bzlib linked in, don't invoke + * support_compression_bzip2(). The "all" functions provide the + * obvious shorthand. + */ + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_read_support_compression_all(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program(struct archive *, + const char *command) __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program_signature + (struct archive *, const char *, + const void * /* match */, size_t) __LA_DEPRECATED; + +__LA_DECL int archive_read_support_compression_rpm(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_uu(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_read_support_filter_all(struct archive *); +__LA_DECL int archive_read_support_filter_by_code(struct archive *, int); +__LA_DECL int archive_read_support_filter_bzip2(struct archive *); +__LA_DECL int archive_read_support_filter_compress(struct archive *); +__LA_DECL int archive_read_support_filter_gzip(struct archive *); +__LA_DECL int archive_read_support_filter_grzip(struct archive *); +__LA_DECL int archive_read_support_filter_lrzip(struct archive *); +__LA_DECL int archive_read_support_filter_lz4(struct archive *); +__LA_DECL int archive_read_support_filter_lzip(struct archive *); +__LA_DECL int archive_read_support_filter_lzma(struct archive *); +__LA_DECL int archive_read_support_filter_lzop(struct archive *); +__LA_DECL int archive_read_support_filter_none(struct archive *); +__LA_DECL int archive_read_support_filter_program(struct archive *, + const char *command); +__LA_DECL int archive_read_support_filter_program_signature + (struct archive *, const char * /* cmd */, + const void * /* match */, size_t); +__LA_DECL int archive_read_support_filter_rpm(struct archive *); +__LA_DECL int archive_read_support_filter_uu(struct archive *); +__LA_DECL int archive_read_support_filter_xz(struct archive *); +__LA_DECL int archive_read_support_filter_zstd(struct archive *); + +__LA_DECL int archive_read_support_format_7zip(struct archive *); +__LA_DECL int archive_read_support_format_all(struct archive *); +__LA_DECL int archive_read_support_format_ar(struct archive *); +__LA_DECL int archive_read_support_format_by_code(struct archive *, int); +__LA_DECL int archive_read_support_format_cab(struct archive *); +__LA_DECL int archive_read_support_format_cpio(struct archive *); +__LA_DECL int archive_read_support_format_empty(struct archive *); +__LA_DECL int archive_read_support_format_gnutar(struct archive *); +__LA_DECL int archive_read_support_format_iso9660(struct archive *); +__LA_DECL int archive_read_support_format_lha(struct archive *); +__LA_DECL int archive_read_support_format_mtree(struct archive *); +__LA_DECL int archive_read_support_format_rar(struct archive *); +__LA_DECL int archive_read_support_format_rar5(struct archive *); +__LA_DECL int archive_read_support_format_raw(struct archive *); +__LA_DECL int archive_read_support_format_tar(struct archive *); +__LA_DECL int archive_read_support_format_warc(struct archive *); +__LA_DECL int archive_read_support_format_xar(struct archive *); +/* archive_read_support_format_zip() enables both streamable and seekable + * zip readers. */ +__LA_DECL int archive_read_support_format_zip(struct archive *); +/* Reads Zip archives as stream from beginning to end. Doesn't + * correctly handle SFX ZIP files or ZIP archives that have been modified + * in-place. */ +__LA_DECL int archive_read_support_format_zip_streamable(struct archive *); +/* Reads starting from central directory; requires seekable input. */ +__LA_DECL int archive_read_support_format_zip_seekable(struct archive *); + +/* Functions to manually set the format and filters to be used. This is + * useful to bypass the bidding process when the format and filters to use + * is known in advance. + */ +__LA_DECL int archive_read_set_format(struct archive *, int); +__LA_DECL int archive_read_append_filter(struct archive *, int); +__LA_DECL int archive_read_append_filter_program(struct archive *, + const char *); +__LA_DECL int archive_read_append_filter_program_signature + (struct archive *, const char *, const void * /* match */, size_t); + +/* Set various callbacks. */ +__LA_DECL int archive_read_set_open_callback(struct archive *, + archive_open_callback *); +__LA_DECL int archive_read_set_read_callback(struct archive *, + archive_read_callback *); +__LA_DECL int archive_read_set_seek_callback(struct archive *, + archive_seek_callback *); +__LA_DECL int archive_read_set_skip_callback(struct archive *, + archive_skip_callback *); +__LA_DECL int archive_read_set_close_callback(struct archive *, + archive_close_callback *); +/* Callback used to switch between one data object to the next */ +__LA_DECL int archive_read_set_switch_callback(struct archive *, + archive_switch_callback *); + +/* This sets the first data object. */ +__LA_DECL int archive_read_set_callback_data(struct archive *, void *); +/* This sets data object at specified index */ +__LA_DECL int archive_read_set_callback_data2(struct archive *, void *, + unsigned int); +/* This adds a data object at the specified index. */ +__LA_DECL int archive_read_add_callback_data(struct archive *, void *, + unsigned int); +/* This appends a data object to the end of list */ +__LA_DECL int archive_read_append_callback_data(struct archive *, void *); +/* This prepends a data object to the beginning of list */ +__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *); + +/* Opening freezes the callbacks. */ +__LA_DECL int archive_read_open1(struct archive *); + +/* Convenience wrappers around the above. */ +__LA_DECL int archive_read_open(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_close_callback *); +__LA_DECL int archive_read_open2(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_skip_callback *, archive_close_callback *); + +/* + * A variety of shortcuts that invoke archive_read_open() with + * canned callbacks suitable for common situations. The ones that + * accept a block size handle tape blocking correctly. + */ +/* Use this if you know the filename. Note: NULL indicates stdin. */ +__LA_DECL int archive_read_open_filename(struct archive *, + const char *_filename, size_t _block_size); +/* Use this for reading multivolume files by filenames. + * NOTE: Must be NULL terminated. Sorting is NOT done. */ +__LA_DECL int archive_read_open_filenames(struct archive *, + const char **_filenames, size_t _block_size); +__LA_DECL int archive_read_open_filename_w(struct archive *, + const wchar_t *_filename, size_t _block_size); +/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ +__LA_DECL int archive_read_open_file(struct archive *, + const char *_filename, size_t _block_size) __LA_DEPRECATED; +/* Read an archive that's stored in memory. */ +__LA_DECL int archive_read_open_memory(struct archive *, + const void * buff, size_t size); +/* A more involved version that is only used for internal testing. */ +__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff, + size_t size, size_t read_size); +/* Read an archive that's already open, using the file descriptor. */ +__LA_DECL int archive_read_open_fd(struct archive *, int _fd, + size_t _block_size); +/* Read an archive that's already open, using a FILE *. */ +/* Note: DO NOT use this with tape drives. */ +__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file); + +/* Parses and returns next entry header. */ +__LA_DECL int archive_read_next_header(struct archive *, + struct archive_entry **); + +/* Parses and returns next entry header using the archive_entry passed in */ +__LA_DECL int archive_read_next_header2(struct archive *, + struct archive_entry *); + +/* + * Retrieve the byte offset in UNCOMPRESSED data where last-read + * header started. + */ +__LA_DECL la_int64_t archive_read_header_position(struct archive *); + +/* + * Returns 1 if the archive contains at least one encrypted entry. + * If the archive format not support encryption at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. + * If for any other reason (e.g. not enough data read so far) + * we cannot say whether there are encrypted entries, then + * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. + * In general, this function will return values below zero when the + * reader is uncertain or totally incapable of encryption support. + * When this function returns 0 you can be sure that the reader + * supports encryption detection but no encrypted entries have + * been found yet. + * + * NOTE: If the metadata/header of an archive is also encrypted, you + * cannot rely on the number of encrypted entries. That is why this + * function does not return the number of encrypted entries but# + * just shows that there are some. + */ +__LA_DECL int archive_read_has_encrypted_entries(struct archive *); + +/* + * Returns a bitmask of capabilities that are supported by the archive format reader. + * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. + */ +__LA_DECL int archive_read_format_capabilities(struct archive *); + +/* Read data from the body of an entry. Similar to read(2). */ +__LA_DECL la_ssize_t archive_read_data(struct archive *, + void *, size_t); + +/* Seek within the body of an entry. Similar to lseek(2). */ +__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int); + +/* + * A zero-copy version of archive_read_data that also exposes the file offset + * of each returned block. Note that the client has no way to specify + * the desired size of the block. The API does guarantee that offsets will + * be strictly increasing and that returned blocks will not overlap. + */ +__LA_DECL int archive_read_data_block(struct archive *a, + const void **buff, size_t *size, la_int64_t *offset); + +/*- + * Some convenience functions that are built on archive_read_data: + * 'skip': skips entire entry + * 'into_buffer': writes data into memory buffer that you provide + * 'into_fd': writes data to specified filedes + */ +__LA_DECL int archive_read_data_skip(struct archive *); +__LA_DECL int archive_read_data_into_fd(struct archive *, int fd); + +/* + * Set read options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_read_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_read_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_read_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_read_set_options(struct archive *_a, + const char *opts); + +/* + * Add a decryption passphrase. + */ +__LA_DECL int archive_read_add_passphrase(struct archive *, const char *); +__LA_DECL int archive_read_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + + +/*- + * Convenience function to recreate the current entry (whose header + * has just been read) on disk. + * + * This does quite a bit more than just copy data to disk. It also: + * - Creates intermediate directories as required. + * - Manages directory permissions: non-writable directories will + * be initially created with write permission enabled; when the + * archive is closed, dir permissions are edited to the values specified + * in the archive. + * - Checks hardlinks: hardlinks will not be extracted unless the + * linked-to file was also extracted within the same session. (TODO) + */ + +/* The "flags" argument selects optional behavior, 'OR' the flags you want. */ + +/* Default: Do not try to set owner/group. */ +#define ARCHIVE_EXTRACT_OWNER (0x0001) +/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */ +#define ARCHIVE_EXTRACT_PERM (0x0002) +/* Default: Do not restore mtime/atime. */ +#define ARCHIVE_EXTRACT_TIME (0x0004) +/* Default: Replace existing files. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) +/* Default: Try create first, unlink only if create fails with EEXIST. */ +#define ARCHIVE_EXTRACT_UNLINK (0x0010) +/* Default: Do not restore ACLs. */ +#define ARCHIVE_EXTRACT_ACL (0x0020) +/* Default: Do not restore fflags. */ +#define ARCHIVE_EXTRACT_FFLAGS (0x0040) +/* Default: Do not restore xattrs. */ +#define ARCHIVE_EXTRACT_XATTR (0x0080) +/* Default: Do not try to guard against extracts redirected by symlinks. */ +/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */ +#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) +/* Default: Do not reject entries with '..' as path elements. */ +#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) +/* Default: Create parent directories as needed. */ +#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) +/* Default: Overwrite files, even if one on disk is newer. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) +/* Detect blocks of 0 and write holes instead. */ +#define ARCHIVE_EXTRACT_SPARSE (0x1000) +/* Default: Do not restore Mac extended metadata. */ +/* This has no effect except on Mac OS. */ +#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) +/* Default: Use HFS+ compression if it was compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000) +/* Default: Do not use HFS+ compression if it was not compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) +/* Default: Do not reject entries with absolute paths */ +#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000) +/* Default: Do not clear no-change flags when unlinking object */ +#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000) +/* Default: Do not extract atomically (using rename) */ +#define ARCHIVE_EXTRACT_SAFE_WRITES (0x40000) + +__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, + int flags); +__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *, + struct archive * /* dest */); +__LA_DECL void archive_read_extract_set_progress_callback(struct archive *, + void (*_progress_func)(void *), void *_user_data); + +/* Record the dev/ino of a file that will not be written. This is + * generally set to the dev/ino of the archive being read. */ +__LA_DECL void archive_read_extract_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +/* Close the file and release most resources. */ +__LA_DECL int archive_read_close(struct archive *); +/* Release all resources and destroy the object. */ +/* Note that archive_read_free will call archive_read_close for you. */ +__LA_DECL int archive_read_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_read_free() for backwards compatibility. */ +__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED; +#endif + +/*- + * To create an archive: + * 1) Ask archive_write_new for an archive writer object. + * 2) Set any global properties. In particular, you should set + * the compression and format to use. + * 3) Call archive_write_open to open the file (most people + * will use archive_write_open_file or archive_write_open_fd, + * which provide convenient canned I/O callbacks for you). + * 4) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to write the header + * - archive_write_data to write the entry data + * 5) archive_write_close to close the output + * 6) archive_write_free to cleanup the writer and release resources + */ +__LA_DECL struct archive *archive_write_new(void); +__LA_DECL int archive_write_set_bytes_per_block(struct archive *, + int bytes_per_block); +__LA_DECL int archive_write_get_bytes_per_block(struct archive *); +/* XXX This is badly misnamed; suggestions appreciated. XXX */ +__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *, + int bytes_in_last_block); +__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *); + +/* The dev/ino of a file that won't be archived. This is used + * to avoid recursively adding an archive to itself. */ +__LA_DECL int archive_write_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_write_set_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_program(struct archive *, + const char *cmd) __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +/* A convenience function to set the filter based on the code. */ +__LA_DECL int archive_write_add_filter(struct archive *, int filter_code); +__LA_DECL int archive_write_add_filter_by_name(struct archive *, + const char *name); +__LA_DECL int archive_write_add_filter_b64encode(struct archive *); +__LA_DECL int archive_write_add_filter_bzip2(struct archive *); +__LA_DECL int archive_write_add_filter_compress(struct archive *); +__LA_DECL int archive_write_add_filter_grzip(struct archive *); +__LA_DECL int archive_write_add_filter_gzip(struct archive *); +__LA_DECL int archive_write_add_filter_lrzip(struct archive *); +__LA_DECL int archive_write_add_filter_lz4(struct archive *); +__LA_DECL int archive_write_add_filter_lzip(struct archive *); +__LA_DECL int archive_write_add_filter_lzma(struct archive *); +__LA_DECL int archive_write_add_filter_lzop(struct archive *); +__LA_DECL int archive_write_add_filter_none(struct archive *); +__LA_DECL int archive_write_add_filter_program(struct archive *, + const char *cmd); +__LA_DECL int archive_write_add_filter_uuencode(struct archive *); +__LA_DECL int archive_write_add_filter_xz(struct archive *); +__LA_DECL int archive_write_add_filter_zstd(struct archive *); + + +/* A convenience function to set the format based on the code or name. */ +__LA_DECL int archive_write_set_format(struct archive *, int format_code); +__LA_DECL int archive_write_set_format_by_name(struct archive *, + const char *name); +/* To minimize link pollution, use one or more of the following. */ +__LA_DECL int archive_write_set_format_7zip(struct archive *); +__LA_DECL int archive_write_set_format_ar_bsd(struct archive *); +__LA_DECL int archive_write_set_format_ar_svr4(struct archive *); +__LA_DECL int archive_write_set_format_cpio(struct archive *); +__LA_DECL int archive_write_set_format_cpio_bin(struct archive *); +__LA_DECL int archive_write_set_format_cpio_newc(struct archive *); +__LA_DECL int archive_write_set_format_cpio_odc(struct archive *); +__LA_DECL int archive_write_set_format_cpio_pwb(struct archive *); +__LA_DECL int archive_write_set_format_gnutar(struct archive *); +__LA_DECL int archive_write_set_format_iso9660(struct archive *); +__LA_DECL int archive_write_set_format_mtree(struct archive *); +__LA_DECL int archive_write_set_format_mtree_classic(struct archive *); +/* TODO: int archive_write_set_format_old_tar(struct archive *); */ +__LA_DECL int archive_write_set_format_pax(struct archive *); +__LA_DECL int archive_write_set_format_pax_restricted(struct archive *); +__LA_DECL int archive_write_set_format_raw(struct archive *); +__LA_DECL int archive_write_set_format_shar(struct archive *); +__LA_DECL int archive_write_set_format_shar_dump(struct archive *); +__LA_DECL int archive_write_set_format_ustar(struct archive *); +__LA_DECL int archive_write_set_format_v7tar(struct archive *); +__LA_DECL int archive_write_set_format_warc(struct archive *); +__LA_DECL int archive_write_set_format_xar(struct archive *); +__LA_DECL int archive_write_set_format_zip(struct archive *); +__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename); +__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext); +__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); +__LA_DECL int archive_write_zip_set_compression_store(struct archive *); +/* Deprecated; use archive_write_open2 instead */ +__LA_DECL int archive_write_open(struct archive *, void *, + archive_open_callback *, archive_write_callback *, + archive_close_callback *); +__LA_DECL int archive_write_open2(struct archive *, void *, + archive_open_callback *, archive_write_callback *, + archive_close_callback *, archive_free_callback *); +__LA_DECL int archive_write_open_fd(struct archive *, int _fd); +__LA_DECL int archive_write_open_filename(struct archive *, const char *_file); +__LA_DECL int archive_write_open_filename_w(struct archive *, + const wchar_t *_file); +/* A deprecated synonym for archive_write_open_filename() */ +__LA_DECL int archive_write_open_file(struct archive *, const char *_file) + __LA_DEPRECATED; +__LA_DECL int archive_write_open_FILE(struct archive *, FILE *); +/* _buffSize is the size of the buffer, _used refers to a variable that + * will be updated after each write into the buffer. */ +__LA_DECL int archive_write_open_memory(struct archive *, + void *_buffer, size_t _buffSize, size_t *_used); + +/* + * Note that the library will truncate writes beyond the size provided + * to archive_write_header or pad if the provided data is short. + */ +__LA_DECL int archive_write_header(struct archive *, + struct archive_entry *); +__LA_DECL la_ssize_t archive_write_data(struct archive *, + const void *, size_t); + +/* This interface is currently only available for archive_write_disk handles. */ +__LA_DECL la_ssize_t archive_write_data_block(struct archive *, + const void *, size_t, la_int64_t); + +__LA_DECL int archive_write_finish_entry(struct archive *); +__LA_DECL int archive_write_close(struct archive *); +/* Marks the archive as FATAL so that a subsequent free() operation + * won't try to close() cleanly. Provides a fast abort capability + * when the client discovers that things have gone wrong. */ +__LA_DECL int archive_write_fail(struct archive *); +/* This can fail if the archive wasn't already closed, in which case + * archive_write_free() will implicitly call archive_write_close(). */ +__LA_DECL int archive_write_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_write_free() for backwards compatibility. */ +__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED; +#endif + +/* + * Set write options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_write_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_write_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_write_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_write_set_options(struct archive *_a, + const char *opts); + +/* + * Set a encryption passphrase. + */ +__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p); +__LA_DECL int archive_write_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + +/*- + * ARCHIVE_WRITE_DISK API + * + * To create objects on disk: + * 1) Ask archive_write_disk_new for a new archive_write_disk object. + * 2) Set any global properties. In particular, you probably + * want to set the options. + * 3) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to create the file/dir/etc on disk + * - archive_write_data to write the entry data + * 4) archive_write_free to cleanup the writer and release resources + * + * In particular, you can use this in conjunction with archive_read() + * to pull entries out of an archive and create them on disk. + */ +__LA_DECL struct archive *archive_write_disk_new(void); +/* This file will not be overwritten. */ +__LA_DECL int archive_write_disk_set_skip_file(struct archive *, + la_int64_t, la_int64_t); +/* Set flags to control how the next item gets created. + * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */ +__LA_DECL int archive_write_disk_set_options(struct archive *, + int flags); +/* + * The lookup functions are given uname/uid (or gname/gid) pairs and + * return a uid (gid) suitable for this system. These are used for + * restoring ownership and for setting ACLs. The default functions + * are naive, they just return the uid/gid. These are small, so reasonable + * for applications that don't need to preserve ownership; they + * are probably also appropriate for applications that are doing + * same-system backup and restore. + */ +/* + * The "standard" lookup functions use common system calls to lookup + * the uname/gname, falling back to the uid/gid if the names can't be + * found. They cache lookups and are reasonably fast, but can be very + * large, so they are not used unless you ask for them. In + * particular, these match the specifications of POSIX "pax" and old + * POSIX "tar". + */ +__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *); +/* + * If neither the default (naive) nor the standard (big) functions suit + * your needs, you can write your own and register them. Be sure to + * include a cleanup function if you have allocated private data. + */ +__LA_DECL int archive_write_disk_set_group_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL int archive_write_disk_set_user_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t); +__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t); + +/* + * ARCHIVE_READ_DISK API + * + * This is still evolving and somewhat experimental. + */ +__LA_DECL struct archive *archive_read_disk_new(void); +/* The names for symlink modes here correspond to an old BSD + * command-line argument convention: -L, -P, -H */ +/* Follow all symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *); +/* Follow no symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *); +/* Follow symlink initially, then not. */ +__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *); +/* TODO: Handle Linux stat32/stat64 ugliness. */ +__LA_DECL int archive_read_disk_entry_from_file(struct archive *, + struct archive_entry *, int /* fd */, const struct stat *); +/* Look up gname for gid or uname for uid. */ +/* Default implementations are very, very stupid. */ +__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t); +__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t); +/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the + * results for performance. */ +__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *); +/* You can install your own lookups if you like. */ +__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +/* Start traversal. */ +__LA_DECL int archive_read_disk_open(struct archive *, const char *); +__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); +/* + * Request that current entry be visited. If you invoke it on every + * directory, you'll get a physical traversal. This is ignored if the + * current entry isn't a directory or a link to a directory. So, if + * you invoke this on every returned path, you'll get a full logical + * traversal. + */ +__LA_DECL int archive_read_disk_descend(struct archive *); +__LA_DECL int archive_read_disk_can_descend(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); +/* Request that the access time of the entry visited by traversal be restored. */ +__LA_DECL int archive_read_disk_set_atime_restored(struct archive *); +/* + * Set behavior. The "flags" argument selects optional behavior. + */ +/* Request that the access time of the entry visited by traversal be restored. + * This is the same as archive_read_disk_set_atime_restored. */ +#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) +/* Default: Do not skip an entry which has nodump flags. */ +#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) +/* Default: Skip a mac resource fork file whose prefix is "._" because of + * using copyfile. */ +#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) +/* Default: Traverse mount points. */ +#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) +/* Default: Xattrs are read from disk. */ +#define ARCHIVE_READDISK_NO_XATTR (0x0010) +/* Default: ACLs are read from disk. */ +#define ARCHIVE_READDISK_NO_ACL (0x0020) +/* Default: File flags are read from disk. */ +#define ARCHIVE_READDISK_NO_FFLAGS (0x0040) +/* Default: Sparse file information is read from disk. */ +#define ARCHIVE_READDISK_NO_SPARSE (0x0080) + +__LA_DECL int archive_read_disk_set_behavior(struct archive *, + int flags); + +/* + * Set archive_match object that will be used in archive_read_disk to + * know whether an entry should be skipped. The callback function + * _excluded_func will be invoked when an entry is skipped by the result + * of archive_match. + */ +__LA_DECL int archive_read_disk_set_matching(struct archive *, + struct archive *_matching, void (*_excluded_func) + (struct archive *, void *, struct archive_entry *), + void *_client_data); +__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data); + +/* Simplified cleanup interface; + * This calls archive_read_free() or archive_write_free() as needed. */ +__LA_DECL int archive_free(struct archive *); + +/* + * Accessor functions to read/set various information in + * the struct archive object: + */ + +/* Number of filters in the current filter pipeline. */ +/* Filter #0 is the one closest to the format, -1 is a synonym for the + * last filter, which is always the pseudo-filter that wraps the + * client callbacks. */ +__LA_DECL int archive_filter_count(struct archive *); +__LA_DECL la_int64_t archive_filter_bytes(struct archive *, int); +__LA_DECL int archive_filter_code(struct archive *, int); +__LA_DECL const char * archive_filter_name(struct archive *, int); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* These don't properly handle multiple filters, so are deprecated and + * will eventually be removed. */ +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ +__LA_DECL la_int64_t archive_position_compressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ +__LA_DECL la_int64_t archive_position_uncompressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ +__LA_DECL const char *archive_compression_name(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ +__LA_DECL int archive_compression(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_errno(struct archive *); +__LA_DECL const char *archive_error_string(struct archive *); +__LA_DECL const char *archive_format_name(struct archive *); +__LA_DECL int archive_format(struct archive *); +__LA_DECL void archive_clear_error(struct archive *); +__LA_DECL void archive_set_error(struct archive *, int _err, + const char *fmt, ...) __LA_PRINTF(3, 4); +__LA_DECL void archive_copy_error(struct archive *dest, + struct archive *src); +__LA_DECL int archive_file_count(struct archive *); + +/* + * ARCHIVE_MATCH API + */ +__LA_DECL struct archive *archive_match_new(void); +__LA_DECL int archive_match_free(struct archive *); + +/* + * Test if archive_entry is excluded. + * This is a convenience function. This is the same as calling all + * archive_match_path_excluded, archive_match_time_excluded + * and archive_match_owner_excluded. + */ +__LA_DECL int archive_match_excluded(struct archive *, + struct archive_entry *); + +/* + * Test if pathname is excluded. The conditions are set by following functions. + */ +__LA_DECL int archive_match_path_excluded(struct archive *, + struct archive_entry *); +/* Control recursive inclusion of directory content when directory is included. Default on. */ +__LA_DECL int archive_match_set_inclusion_recursion(struct archive *, int); +/* Add exclusion pathname pattern. */ +__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); +__LA_DECL int archive_match_exclude_pattern_w(struct archive *, + const wchar_t *); +/* Add exclusion pathname pattern from file. */ +__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* Add inclusion pathname pattern. */ +__LA_DECL int archive_match_include_pattern(struct archive *, const char *); +__LA_DECL int archive_match_include_pattern_w(struct archive *, + const wchar_t *); +/* Add inclusion pathname pattern from file. */ +__LA_DECL int archive_match_include_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* + * How to get statistic information for inclusion patterns. + */ +/* Return the amount number of unmatched inclusion patterns. */ +__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); +/* Return the pattern of unmatched inclusion with ARCHIVE_OK. + * Return ARCHIVE_EOF if there is no inclusion pattern. */ +__LA_DECL int archive_match_path_unmatched_inclusions_next( + struct archive *, const char **); +__LA_DECL int archive_match_path_unmatched_inclusions_next_w( + struct archive *, const wchar_t **); + +/* + * Test if a file is excluded by its time stamp. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_time_excluded(struct archive *, + struct archive_entry *); + +/* + * Flags to tell a matching type of time stamps. These are used for + * following functions. + */ +/* Time flag: mtime to be tested. */ +#define ARCHIVE_MATCH_MTIME (0x0100) +/* Time flag: ctime to be tested. */ +#define ARCHIVE_MATCH_CTIME (0x0200) +/* Comparison flag: Match the time if it is newer than. */ +#define ARCHIVE_MATCH_NEWER (0x0001) +/* Comparison flag: Match the time if it is older than. */ +#define ARCHIVE_MATCH_OLDER (0x0002) +/* Comparison flag: Match the time if it is equal to. */ +#define ARCHIVE_MATCH_EQUAL (0x0010) +/* Set inclusion time. */ +__LA_DECL int archive_match_include_time(struct archive *, int _flag, + time_t _sec, long _nsec); +/* Set inclusion time by a date string. */ +__LA_DECL int archive_match_include_date(struct archive *, int _flag, + const char *_datestr); +__LA_DECL int archive_match_include_date_w(struct archive *, int _flag, + const wchar_t *_datestr); +/* Set inclusion time by a particular file. */ +__LA_DECL int archive_match_include_file_time(struct archive *, + int _flag, const char *_pathname); +__LA_DECL int archive_match_include_file_time_w(struct archive *, + int _flag, const wchar_t *_pathname); +/* Add exclusion entry. */ +__LA_DECL int archive_match_exclude_entry(struct archive *, + int _flag, struct archive_entry *); + +/* + * Test if a file is excluded by its uid ,gid, uname or gname. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_owner_excluded(struct archive *, + struct archive_entry *); +/* Add inclusion uid, gid, uname and gname. */ +__LA_DECL int archive_match_include_uid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_gid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_uname(struct archive *, const char *); +__LA_DECL int archive_match_include_uname_w(struct archive *, + const wchar_t *); +__LA_DECL int archive_match_include_gname(struct archive *, const char *); +__LA_DECL int archive_match_include_gname_w(struct archive *, + const wchar_t *); + +/* Utility functions */ +/* Convenience function to sort a NULL terminated list of strings */ +__LA_DECL int archive_utility_string_sort(char **); + +#ifdef __cplusplus +} +#endif + +/* These are meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_H_INCLUDED */ diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h new file mode 100644 index 0000000..64e0f4a --- /dev/null +++ b/libarchive/archive_entry.h @@ -0,0 +1,721 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2016 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $ + */ + +#ifndef ARCHIVE_ENTRY_H_INCLUDED +#define ARCHIVE_ENTRY_H_INCLUDED + +/* Note: Compiler will complain if this does not match archive.h! */ +#define ARCHIVE_VERSION_NUMBER 3006002 + +/* + * Note: archive_entry.h is for use outside of libarchive; the + * configuration headers (config.h, archive_platform.h, etc.) are + * purely internal. Do NOT use HAVE_XXX configuration macros to + * control the behavior of this header! If you must conditionalize, + * use predefined compiler and/or platform macros. + */ + +#include +#include /* for wchar_t */ +#include +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#endif + +/* Get a suitable 64-bit integer type. */ +#if !defined(__LA_INT64_T_DEFINED) +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +#include +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Get a suitable definition for mode_t */ +#if ARCHIVE_VERSION_NUMBER >= 3999000 +/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ +# define __LA_MODE_T int +#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) +# define __LA_MODE_T unsigned short +#else +# define __LA_MODE_T mode_t +#endif + +/* Large file support for Android */ +#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__) +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries on all platforms and shared libraries on non-Windows. */ +# define __LA_DECL +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 +# define __LA_DEPRECATED __attribute__((deprecated)) +#else +# define __LA_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Description of an archive entry. + * + * You can think of this as "struct stat" with some text fields added in. + * + * TODO: Add "comment", "charset", and possibly other entries that are + * supported by "pax interchange" format. However, GNU, ustar, cpio, + * and other variants don't support these features, so they're not an + * excruciatingly high priority right now. + * + * TODO: "pax interchange" format allows essentially arbitrary + * key/value attributes to be attached to any entry. Supporting + * such extensions may make this library useful for special + * applications (e.g., a package manager could attach special + * package-management attributes to each entry). + */ +struct archive; +struct archive_entry; + +/* + * File-type constants. These are returned from archive_entry_filetype() + * and passed to archive_entry_set_filetype(). + * + * These values match S_XXX defines on every platform I've checked, + * including Windows, AIX, Linux, Solaris, and BSD. They're + * (re)defined here because platforms generally don't define the ones + * they don't support. For example, Windows doesn't define S_IFLNK or + * S_IFBLK. Instead of having a mass of conditional logic and system + * checks to define any S_XXX values that aren't supported locally, + * I've just defined a new set of such constants so that + * libarchive-based applications can manipulate and identify archive + * entries properly even if the hosting platform can't store them on + * disk. + * + * These values are also used directly within some portable formats, + * such as cpio. If you find a platform that varies from these, the + * correct solution is to leave these alone and translate from these + * portable values to platform-native values when entries are read from + * or written to disk. + */ +/* + * In libarchive 4.0, we can drop the casts here. + * They're needed to work around Borland C's broken mode_t. + */ +#define AE_IFMT ((__LA_MODE_T)0170000) +#define AE_IFREG ((__LA_MODE_T)0100000) +#define AE_IFLNK ((__LA_MODE_T)0120000) +#define AE_IFSOCK ((__LA_MODE_T)0140000) +#define AE_IFCHR ((__LA_MODE_T)0020000) +#define AE_IFBLK ((__LA_MODE_T)0060000) +#define AE_IFDIR ((__LA_MODE_T)0040000) +#define AE_IFIFO ((__LA_MODE_T)0010000) + +/* + * Symlink types + */ +#define AE_SYMLINK_TYPE_UNDEFINED 0 +#define AE_SYMLINK_TYPE_FILE 1 +#define AE_SYMLINK_TYPE_DIRECTORY 2 + +/* + * Basic object manipulation + */ + +__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); +/* The 'clone' function does a deep copy; all of the strings are copied too. */ +__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); +__LA_DECL void archive_entry_free(struct archive_entry *); +__LA_DECL struct archive_entry *archive_entry_new(void); + +/* + * This form of archive_entry_new2() will pull character-set + * conversion information from the specified archive handle. The + * older archive_entry_new(void) form is equivalent to calling + * archive_entry_new2(NULL) and will result in the use of an internal + * default character-set conversion. + */ +__LA_DECL struct archive_entry *archive_entry_new2(struct archive *); + +/* + * Retrieve fields from an archive_entry. + * + * There are a number of implicit conversions among these fields. For + * example, if a regular string field is set and you read the _w wide + * character field, the entry will implicitly convert narrow-to-wide + * using the current locale. Similarly, dev values are automatically + * updated when you write devmajor or devminor and vice versa. + * + * In addition, fields can be "set" or "unset." Unset string fields + * return NULL, non-string fields have _is_set() functions to test + * whether they've been set. You can "unset" a string field by + * assigning NULL; non-string fields have _unset() functions to + * unset them. + * + * Note: There is one ambiguity in the above; string fields will + * also return NULL when implicit character set conversions fail. + * This is usually what you want. + */ +__LA_DECL time_t archive_entry_atime(struct archive_entry *); +__LA_DECL long archive_entry_atime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_atime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_birthtime(struct archive_entry *); +__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_ctime(struct archive_entry *); +__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_dev(struct archive_entry *); +__LA_DECL int archive_entry_dev_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_devminor(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); +__LA_DECL void archive_entry_fflags(struct archive_entry *, + unsigned long * /* set */, + unsigned long * /* clear */); +__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *); +__LA_DECL const char *archive_entry_gname(struct archive_entry *); +__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *); +__LA_DECL int archive_entry_ino_is_set(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); +__LA_DECL time_t archive_entry_mtime(struct archive_entry *); +__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *); +__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdev(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); +__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_size(struct archive_entry *); +__LA_DECL int archive_entry_size_is_set(struct archive_entry *); +__LA_DECL const char *archive_entry_strmode(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *); +__LA_DECL int archive_entry_symlink_type(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *); +__LA_DECL const char *archive_entry_uname(struct archive_entry *); +__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); +__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_encrypted(struct archive_entry *); + +/* + * Set fields in an archive_entry. + * + * Note: Before libarchive 2.4, there were 'set' and 'copy' versions + * of the string setters. 'copy' copied the actual string, 'set' just + * stored the pointer. In libarchive 2.4 and later, strings are + * always copied. + */ + +__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_atime(struct archive_entry *); +#if defined(_WIN32) && !defined(__CYGWIN__) +__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *); +#endif +__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); +__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_ctime(struct archive_entry *); +__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_fflags(struct archive_entry *, + unsigned long /* set */, unsigned long /* clear */); +/* Returns pointer to start of first invalid token, or NULL if none. */ +/* Note that all recognized tokens are processed, regardless. */ +__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, + const char *); +__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, + const wchar_t *); +__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_mtime(struct archive_entry *); +__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_unset_size(struct archive_entry *); +__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *); +__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_symlink_type(struct archive_entry *, int); +__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted); +__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted); +/* + * Routines to bulk copy fields to/from a platform-native "struct + * stat." Libarchive used to just store a struct stat inside of each + * archive_entry object, but this created issues when trying to + * manipulate archives on systems different than the ones they were + * created on. + * + * TODO: On Linux and other LFS systems, provide both stat32 and + * stat64 versions of these functions and all of the macro glue so + * that archive_entry_stat is magically defined to + * archive_entry_stat32 or archive_entry_stat64 as appropriate. + */ +__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); +__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); + +/* + * Storage for Mac OS-specific AppleDouble metadata information. + * Apple-format tar files store a separate binary blob containing + * encoded metadata with ACL, extended attributes, etc. + * This provides a place to store that blob. + */ + +__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); +__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); + +/* + * Digest routine. This is used to query the raw hex digest for the + * given entry. The type of digest is provided as an argument. + */ +#define ARCHIVE_ENTRY_DIGEST_MD5 0x00000001 +#define ARCHIVE_ENTRY_DIGEST_RMD160 0x00000002 +#define ARCHIVE_ENTRY_DIGEST_SHA1 0x00000003 +#define ARCHIVE_ENTRY_DIGEST_SHA256 0x00000004 +#define ARCHIVE_ENTRY_DIGEST_SHA384 0x00000005 +#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006 + +__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */); + +/* + * ACL routines. This used to simply store and return text-format ACL + * strings, but that proved insufficient for a number of reasons: + * = clients need control over uname/uid and gname/gid mappings + * = there are many different ACL text formats + * = would like to be able to read/convert archives containing ACLs + * on platforms that lack ACL libraries + * + * This last point, in particular, forces me to implement a reasonably + * complete set of ACL support routines. + */ + +/* + * Permission bits. + */ +#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001 +#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002 +#define ARCHIVE_ENTRY_ACL_READ 0x00000004 +#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008 +#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008 +#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010 +#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010 +#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020 +#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020 +#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040 +#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080 +#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100 +#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200 +#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400 +#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800 +#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000 +#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000 +#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000 +#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000 + +#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_WRITE \ + | ARCHIVE_ENTRY_ACL_READ) + +#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_READ_DATA \ + | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \ + | ARCHIVE_ENTRY_ACL_WRITE_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_FILE \ + | ARCHIVE_ENTRY_ACL_APPEND_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \ + | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_DELETE_CHILD \ + | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_DELETE \ + | ARCHIVE_ENTRY_ACL_READ_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_OWNER \ + | ARCHIVE_ENTRY_ACL_SYNCHRONIZE) + +/* + * Inheritance values (NFS4 ACLs only); included in permset. + */ +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000 + +#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \ + (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ + | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) + +/* We need to be able to specify combinations of these. */ +#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ + | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) +#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ + | ARCHIVE_ENTRY_ACL_TYPE_DENY \ + | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \ + | ARCHIVE_ENTRY_ACL_TYPE_ALARM) + +/* Tag values mimic POSIX.1e */ +#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ +#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ +#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ +#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ +#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */ + +/* + * Set the ACL by clearing it and adding entries one at a time. + * Unlike the POSIX.1e ACL routines, you must specify the type + * (access/default) for each entry. Internally, the ACL data is just + * a soup of entries. API calls here allow you to retrieve just the + * entries of interest. This design (which goes against the spirit of + * POSIX.1e) is useful for handling archive formats that combine + * default and access information in a single ACL list. + */ +__LA_DECL void archive_entry_acl_clear(struct archive_entry *); +__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const char * /* name */); +__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const wchar_t * /* name */); + +/* + * To retrieve the ACL, first "reset", then repeatedly ask for the + * "next" entry. The want_type parameter allows you to request only + * certain types of entries. + */ +__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); +__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, + int * /* type */, int * /* permset */, int * /* tag */, + int * /* qual */, const char ** /* name */); + +/* + * Construct a text-format ACL. The flags argument is a bitmask that + * can include any of the following: + * + * Flags only for archive entries with POSIX.1e ACL: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. + * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each + * default ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and + * "mask" entries. + * + * Flags only for archive entries with NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for + * unset permissions and flags in NFSv4 ACL permission and flag fields + * + * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in + * each ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma + * instead of newline. + */ +#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001 +#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002 +#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004 +#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008 +#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 + +__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, + const wchar_t * /* wtext */, int /* type */); +__LA_DECL int archive_entry_acl_from_text(struct archive_entry *, + const char * /* text */, int /* type */); + +/* Deprecated constants */ +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 + +/* Deprecated functions */ +__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, + int /* flags */) __LA_DEPRECATED; +__LA_DECL const char *archive_entry_acl_text(struct archive_entry *, + int /* flags */) __LA_DEPRECATED; + +/* Return bitmask of ACL types in an archive entry */ +__LA_DECL int archive_entry_acl_types(struct archive_entry *); + +/* Return a count of entries matching 'want_type' */ +__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); + +/* Return an opaque ACL object. */ +/* There's not yet anything clients can actually do with this... */ +struct archive_acl; +__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *); + +/* + * extended attributes + */ + +__LA_DECL void archive_entry_xattr_clear(struct archive_entry *); +__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, + const char * /* name */, const void * /* value */, + size_t /* size */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_xattr_count(struct archive_entry *); +__LA_DECL int archive_entry_xattr_reset(struct archive_entry *); +__LA_DECL int archive_entry_xattr_next(struct archive_entry *, + const char ** /* name */, const void ** /* value */, size_t *); + +/* + * sparse + */ + +__LA_DECL void archive_entry_sparse_clear(struct archive_entry *); +__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *, + la_int64_t /* offset */, la_int64_t /* length */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_sparse_count(struct archive_entry *); +__LA_DECL int archive_entry_sparse_reset(struct archive_entry *); +__LA_DECL int archive_entry_sparse_next(struct archive_entry *, + la_int64_t * /* offset */, la_int64_t * /* length */); + +/* + * Utility to match up hardlinks. + * + * The 'struct archive_entry_linkresolver' is a cache of archive entries + * for files with multiple links. Here's how to use it: + * 1. Create a lookup object with archive_entry_linkresolver_new() + * 2. Tell it the archive format you're using. + * 3. Hand each archive_entry to archive_entry_linkify(). + * That function will return 0, 1, or 2 entries that should + * be written. + * 4. Call archive_entry_linkify(resolver, NULL) until + * no more entries are returned. + * 5. Call archive_entry_linkresolver_free(resolver) to free resources. + * + * The entries returned have their hardlink and size fields updated + * appropriately. If an entry is passed in that does not refer to + * a file with multiple links, it is returned unchanged. The intention + * is that you should be able to simply filter all entries through + * this machine. + * + * To make things more efficient, be sure that each entry has a valid + * nlinks value. The hardlink cache uses this to track when all links + * have been found. If the nlinks value is zero, it will keep every + * name in the cache indefinitely, which can use a lot of memory. + * + * Note that archive_entry_size() is reset to zero if the file + * body should not be written to the archive. Pay attention! + */ +struct archive_entry_linkresolver; + +/* + * There are three different strategies for marking hardlinks. + * The descriptions below name them after the best-known + * formats that rely on each strategy: + * + * "Old cpio" is the simplest, it always returns any entry unmodified. + * As far as I know, only cpio formats use this. Old cpio archives + * store every link with the full body; the onus is on the dearchiver + * to detect and properly link the files as they are restored. + * "tar" is also pretty simple; it caches a copy the first time it sees + * any link. Subsequent appearances are modified to be hardlink + * references to the first one without any body. Used by all tar + * formats, although the newest tar formats permit the "old cpio" strategy + * as well. This strategy is very simple for the dearchiver, + * and reasonably straightforward for the archiver. + * "new cpio" is trickier. It stores the body only with the last + * occurrence. The complication is that we might not + * see every link to a particular file in a single session, so + * there's no easy way to know when we've seen the last occurrence. + * The solution here is to queue one link until we see the next. + * At the end of the session, you can enumerate any remaining + * entries by calling archive_entry_linkify(NULL) and store those + * bodies. If you have a file with three links l1, l2, and l3, + * you'll get the following behavior if you see all three links: + * linkify(l1) => NULL (the resolver stores l1 internally) + * linkify(l2) => l1 (resolver stores l2, you write l1) + * linkify(l3) => l2, l3 (all links seen, you can write both). + * If you only see l1 and l2, you'll get this behavior: + * linkify(l1) => NULL + * linkify(l2) => l1 + * linkify(NULL) => l2 (at end, you retrieve remaining links) + * As the name suggests, this strategy is used by newer cpio variants. + * It's noticeably more complex for the archiver, slightly more complex + * for the dearchiver than the tar strategy, but makes it straightforward + * to restore a file using any link by simply continuing to scan until + * you see a link that is stored with a body. In contrast, the tar + * strategy requires you to rescan the archive from the beginning to + * correctly extract an arbitrary link. + */ + +__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); +__LA_DECL void archive_entry_linkresolver_set_strategy( + struct archive_entry_linkresolver *, int /* format_code */); +__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); +__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, + struct archive_entry **, struct archive_entry **); +__LA_DECL struct archive_entry *archive_entry_partial_links( + struct archive_entry_linkresolver *res, unsigned int *links); +#ifdef __cplusplus +} +#endif + +/* This is meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_ENTRY_H_INCLUDED */ From 6e6ee24d2562d9e829ebc1a845c21c44b3ab8895 Mon Sep 17 00:00:00 2001 From: Lightmann Date: Sat, 31 Dec 2022 15:13:53 -0500 Subject: [PATCH 6/6] Bump ver --- metadata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.yml b/metadata.yml index 6add772..087bc8e 100644 --- a/metadata.yml +++ b/metadata.yml @@ -1,2 +1,2 @@ --- -version: 1.0.1 +version: 1.0.2