//
//  *.c
//  async_wake_ios
//
//  Created by George on 18/12/17.
//  Copyright © 2017 Ian Beer. All rights reserved.
//

#import <stdlib.h>

#import "kernel_utils.h"
#import "patchfinder64.h"
#import "kexecute.h"
#import "offsetof.h"

#include "liboffsetfinder64/getoffsets.h"

#import <Foundation/Foundation.h>
#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(0)

int vnode_lookup(const char *path, int flags, uint64_t *vnode, uint64_t vfs_context) {
    
    size_t len = strlen(path) + 1;
    uint64_t ptr = Kernel_alloc(8);
    uint64_t ptr2 = Kernel_alloc(len);
    KernelWrite(ptr2, path, len);
    
    if (Kernel_Execute(find_symbol("_vnode_lookup") + get_kernel_slide(), ptr2, flags, ptr, vfs_context, 0, 0, 0)) {
        return -1;
    }
    *vnode = KernelRead_64bits(ptr);
    Kernel_free(ptr2, len);
    Kernel_free(ptr, 8);
    return 0;
}

uint64_t get_vfs_context() {
    return ZmFixAddr(Kernel_Execute(find_symbol("_vfs_context_current") + get_kernel_slide(), 1, 0, 0, 0, 0, 0, 0));
}

int vnode_put(uint64_t vnode) {
    return (int)Kernel_Execute(find_symbol("_vnode_put") + get_kernel_slide(), vnode, 0, 0, 0, 0, 0, 0);
}

uint64_t get_vnode_at_path(const char *path) {
    uint64_t *vnode_ptr = (uint64_t *)malloc(8);
    if (vnode_lookup(path, 0, vnode_ptr, get_vfs_context())) {
        free(vnode_ptr);
        return -1;
    }
    else {
        uint64_t vnode = *vnode_ptr;
        free(vnode_ptr);
        return vnode;
    }
}

int fix_vnode_for_mmap(const char* path) {

#define VSHARED_DYLD 0x000200
    
    uint64_t vnode = get_vnode_at_path(path);
    if (vnode == -1) {
        LOG("[-] Unable to fix mmap of path: %s\n", path);
        return -1;
    }
    uint32_t v_flags = KernelRead_32bits(vnode + off_v_flags);
    KernelWrite_32bits(vnode + off_v_flags, v_flags | VSHARED_DYLD);
    
    vnode_put(vnode);
    
    return KernelRead_32bits(vnode + off_v_flags) & VSHARED_DYLD;
}

