#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <sys/mount.h>
#include <unistd.h>
#include <stdlib.h>
#include <asl.h>
#include <stdio.h>
#include "load_webdavfs.h"
#include "webdavfs_load_kext.h"
#include "webdavfs_load_kextServer.h"
#define CFENVFORMATSTRING "__CF_USER_TEXT_ENCODING=0x%X:0:0"
union MaxMsgSize {
union __RequestUnion__webdavfs_load_kext_subsystem req;
union __ReplyUnion__webdavfs_load_kext_subsystem rep;
};
static int LoadKext(const char *inKextPath)
{
int pid;
int result = -1;
union wait status;
pid = fork();
if (pid == 0)
{
char CFUserTextEncodingEnvSetting[sizeof(CFENVFORMATSTRING) + 20];
char *env[] = {CFUserTextEncodingEnvSetting, "", (char *) 0 };
snprintf(CFUserTextEncodingEnvSetting, sizeof(CFUserTextEncodingEnvSetting), CFENVFORMATSTRING, getuid());
result = execle(KEXT_LOAD_PATH, KEXT_LOAD_PATH, inKextPath, NULL, env);
_exit (errno);
}
if (pid == -1)
{
result = errno;
goto Return;
}
if ((wait4(pid, (int *) &status, 0, NULL) == pid) && (WIFEXITED(status)))
{
result = status.w_retcode;
}
else
{
result = EIO;
}
Return:
return (result);
}
kern_return_t do_load_kext(mach_port_t test_port __attribute__((unused)), string_t kextname)
{
int error = KERN_SUCCESS;
struct vfsconf vfc;
if(geteuid() != 0)
{
asl_log(NULL, NULL, ASL_LEVEL_ERR, "Need to be root to load kext euid = %d!\n", geteuid());
return EACCES;
}
if (strcmp(kextname, WEBDAVFS_VFSNAME) == 0) {
if (getvfsbyname(WEBDAVFS_VFSNAME, &vfc) != 0)
error = LoadKext(WEBDAV_KEXT_PATH);
} else
error = ENOENT;
return error;
}
static mach_port_t checkin_or_register(const char *bname)
{
kern_return_t kr;
mach_port_t mp;
kr = bootstrap_check_in(bootstrap_port, (const char *)bname, &mp);
if (kr == KERN_SUCCESS)
return mp;
exit(EXIT_FAILURE);
}
int main(void)
{
mach_msg_size_t mxmsgsz = (mach_msg_size_t)(sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE);
mach_port_t mp = checkin_or_register(WEBDAVFS_LOAD_KEXT_BOOTSTRAP_NAME);
kern_return_t kr;
kr = mach_msg_server_once(webdavfs_load_kext_server, mxmsgsz, mp, 0);
if (kr != KERN_SUCCESS) {
asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "mach_msg_server(mp): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}