#include <sys/param.h>
#include <sys/mount.h>
#include <NetFS/NetFSPlugin.h>
#include <NetFS/NetFSUtil.h>
#include <NetFS/NetFSPrivate.h>
#include <asl.h>
#include "smb_netfs.h"
#include <netsmb/smb_lib.h>
#include <netsmb/smb_conn.h>
#include <parse_url.h>
netfsError SMB_CreateSessionRef(void **sessionRef)
{
int error;
error = smb_load_library();
if (error) {
smb_log_info("%s: loading the smb library failed!", error, ASL_LEVEL_ERR, __FUNCTION__);
*sessionRef = NULL;
return error;
}
*sessionRef = smb_create_ctx();
if (*sessionRef == NULL) {
smb_log_info("%s: creating session refernce failed!\n", ENOMEM, ASL_LEVEL_ERR, __FUNCTION__);
return ENOMEM;
}
#ifdef SMB_DEBUG
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, *sessionRef);
#endif // SMB_DEBUG
return 0;
}
netfsError SMB_Cancel(void *sessionRef)
{
#ifdef SMB_DEBUG
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, sessionRef);
#endif // SMB_DEBUG
smb_ctx_cancel_connection((struct smb_ctx *)sessionRef);
return 0;
}
netfsError SMB_CloseSession(void *sessionRef)
{
#ifdef SMB_DEBUG
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, sessionRef);
#endif // SMB_DEBUG
smb_ctx_done(sessionRef);
return 0;
}
netfsError SMB_ParseURL(CFURLRef url, CFDictionaryRef *urlParms)
{
*urlParms = NULL;
if (url == NULL) {
smb_log_info("%s: failed URL is NULL!", EINVAL, ASL_LEVEL_ERR, __FUNCTION__);
return EINVAL;
}
return smb_url_to_dictionary(url, urlParms);
}
netfsError SMB_CreateURL(CFDictionaryRef urlParms, CFURLRef *url)
{
*url = NULL;
if (urlParms == NULL) {
smb_log_info("%s: failed dictionary is NULL!", EINVAL, ASL_LEVEL_ERR, __FUNCTION__);
return EINVAL;
}
return smb_dictionary_to_url(urlParms, url);
}
netfsError SMB_OpenSession(CFURLRef url, void *sessionRef, CFDictionaryRef openOptions, CFDictionaryRef *sessionInfo)
{
struct smb_ctx *ctx = sessionRef;
int error = 0;
if ((sessionRef == NULL) || (url == NULL)) {
smb_log_info("%s: - in parameters are NULL!", EINVAL, ASL_LEVEL_ERR, __FUNCTION__);
return EINVAL;
}
pthread_mutex_lock(&ctx->ctx_mutex);
if ((openOptions == NULL) ||
((CFDictionaryGetValue(openOptions, kNetFSUseKerberosKey) == NULL) &&
(CFDictionaryGetValue(openOptions, kNetFSUseGuestKey) == NULL) &&
(CFDictionaryGetValue(openOptions, kNetFSUseAnonymousKey) == NULL))) {
CFMutableDictionaryRef openOptionsKerb;
if (openOptions)
openOptionsKerb = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, openOptions);
else
openOptionsKerb = CFDictionaryCreateMutable(kCFAllocatorDefault, 0 ,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (openOptionsKerb) {
CFDictionarySetValue (openOptionsKerb, kNetFSUseKerberosKey, kCFBooleanTrue);
error = smb_open_session(sessionRef, url, openOptionsKerb, sessionInfo);
smb_log_info("%s: No security method selected attempting Kerberos. error = %d", 0, ASL_LEVEL_DEBUG, __FUNCTION__, error);
CFRelease(openOptionsKerb);
} else
error = EAUTH;
if (error == EAUTH)
error = smb_open_session(sessionRef, url, openOptions, sessionInfo);
} else
error = smb_open_session(sessionRef, url, openOptions, sessionInfo);
pthread_mutex_unlock(&ctx->ctx_mutex);
if (error)
smb_log_info("%s: - error = %d!", 0, ASL_LEVEL_DEBUG, __FUNCTION__, error);
#ifdef SMB_DEBUG
else
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, sessionRef);
#endif // SMB_DEBUG
return error;
}
netfsError SMB_GetServerInfo(CFURLRef url, void *sessionRef, CFDictionaryRef openOptions, CFDictionaryRef *serverParms)
{
struct smb_ctx *ctx = sessionRef;
int error = 0;
if ((sessionRef == NULL) || (url == NULL)) {
smb_log_info("%s: - in parameters are NULL!", EINVAL, ASL_LEVEL_ERR, __FUNCTION__);
return EINVAL;
}
pthread_mutex_lock(&ctx->ctx_mutex);
error = smb_get_server_info(sessionRef, url, openOptions, serverParms);
pthread_mutex_unlock(&ctx->ctx_mutex);
if (error)
smb_log_info("%s: - error = %d!", 0, ASL_LEVEL_DEBUG, __FUNCTION__, error);
#ifdef SMB_DEBUG
else
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, sessionRef);
#endif // SMB_DEBUG
return error;
}
netfsError SMB_EnumerateShares(void *sessionRef, CFDictionaryRef enumerateOptions, CFDictionaryRef *sharePoints )
{
#pragma unused(enumerateOptions)
struct smb_ctx *ctx = sessionRef;
int error = 0;
if (sessionRef == NULL) {
smb_log_info("%s: failed session reference is NULL!", EINVAL, ASL_LEVEL_ERR, __FUNCTION__);
return EINVAL;
}
pthread_mutex_lock(&ctx->ctx_mutex);
error = smb_enumerate_shares(sessionRef, sharePoints);
pthread_mutex_unlock(&ctx->ctx_mutex);
if (error)
smb_log_info("%s: - error = %d!", 0, ASL_LEVEL_DEBUG, __FUNCTION__, error);
#ifdef SMB_DEBUG
else
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, sessionRef);
#endif // SMB_DEBUG
return error;
}
netfsError SMB_Mount(void *sessionRef, CFURLRef url, CFStringRef mPoint, CFDictionaryRef mOptions, CFDictionaryRef *mInfo)
{
struct smb_ctx *ctx = sessionRef;
int error = 0;
if ((sessionRef == NULL) || (mPoint == NULL) || (url == NULL)) {
smb_log_info("%s: - in parameters are NULL!", EINVAL, ASL_LEVEL_ERR, __FUNCTION__);
return EINVAL;
}
pthread_mutex_lock(&ctx->ctx_mutex);
if (ctx->ct_url)
CFRelease(ctx->ct_url);
ctx->ct_url = CFURLCopyAbsoluteURL(url);
if (ctx->ct_url)
error = ParseSMBURL(ctx, SMB_ST_DISK);
else
error = ENOMEM;
if (error)
smb_log_info("%s: Parsing URL failed!", error, ASL_LEVEL_ERR, __FUNCTION__);
else
error = smb_mount(sessionRef, mPoint, mOptions, mInfo);
pthread_mutex_unlock(&ctx->ctx_mutex);
if (error)
smb_log_info("%s: - error = %d!", 0, ASL_LEVEL_DEBUG, __FUNCTION__, error);
#ifdef SMB_DEBUG
else
smb_log_info("%s: refernce %p\n", 0, ASL_LEVEL_DEBUG, __FUNCTION__, sessionRef);
#endif // SMB_DEBUG
return error;
}
netfsError SMB_GetMountInfo(CFStringRef in_Mountpath, CFDictionaryRef *out_MountInfo)
{
int error;
char *mountpath;
struct statfs statbuf;
char *sharepointname;
char *url;
size_t url_length;
CFStringRef url_CString;
CFMutableDictionaryRef mutableDict = NULL;
*out_MountInfo = NULL;
mutableDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (mutableDict == NULL)
return ENOMEM;
mountpath = NetFSCFStringtoCString(in_Mountpath);
if (mountpath == NULL) {
CFRelease(mutableDict);
return ENOMEM;
}
if (statfs(mountpath, &statbuf) == -1) {
error = errno;
CFRelease(mutableDict);
free(mountpath);
return error;
}
free(mountpath);
smb_ctx_get_user_mount_info(statbuf.f_mntonname, mutableDict);
sharepointname = statbuf.f_mntfromname;
while ((*sharepointname == '/') || (*sharepointname == '\\')) {
++sharepointname;
}
url_length = sizeof(SMB_PREFIX) + strlen(sharepointname);
url = malloc(url_length);
if (url == NULL) {
CFRelease(mutableDict);
return ENOMEM;
}
strlcpy(url, SMB_PREFIX, url_length);
strlcat(url, sharepointname, url_length);
url_CString = CFStringCreateWithCString(kCFAllocatorDefault, url,
kCFStringEncodingUTF8);
free(url);
if (url_CString == NULL) {
CFRelease(mutableDict);
return ENOMEM;
}
CFDictionarySetValue (mutableDict, kNetFSMountedURLKey, url_CString);
*out_MountInfo = mutableDict;
CFRelease(url_CString);
return 0;
}