#include <SystemConfiguration/SystemConfiguration.h>
#include "SCPPrivate.h"
#include <fcntl.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/param.h>
static const struct scp_errmsg {
SCPStatus status;
char *message;
} scp_errmsgs[] = {
{ SCP_OK, "Success!" },
{ SCP_BUSY, "Configuration daemon busy" },
{ SCP_NEEDLOCK, "Lock required for this operation" },
{ SCP_EACCESS, "Permission denied (must be root to obtain lock)" },
{ SCP_ENOENT, "Configuration file not found" },
{ SCP_BADCF, "Configuration file corrupt" },
{ SCP_NOKEY, "No such key" },
{ SCP_NOLINK, "No such link" },
{ SCP_EXISTS, "Key already defined" },
{ SCP_STALE, "Write attempted on stale version of object" },
{ SCP_INVALIDARGUMENT, "Invalid argument" },
{ SCP_FAILED, "Failed!" }
};
#define nSCP_ERRMSGS (sizeof(scp_errmsgs)/sizeof(struct scp_errmsg))
__private_extern__ CFDataRef
_SCPSignatureFromStatbuf(const struct stat *statBuf)
{
CFMutableDataRef signature;
SCPSignatureDataRef sig;
signature = CFDataCreateMutable(NULL, sizeof(SCPSignatureData));
CFDataSetLength(signature, sizeof(SCPSignatureData));
sig = (SCPSignatureDataRef)CFDataGetBytePtr(signature);
sig->st_dev = statBuf->st_dev;
sig->st_ino = statBuf->st_ino;
sig->st_mtimespec = statBuf->st_mtimespec;
sig->st_size = statBuf->st_size;
return signature;
}
__private_extern__ char *
_SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user)
{
CFStringRef path = NULL;
int pathLen;
char *pathStr;
if (perUser) {
if (prefsID == NULL) {
return NULL;
} else if (CFStringHasPrefix(prefsID, CFSTR("/"))) {
path = CFRetain(prefsID);
} else {
char login[MAXLOGNAME+1];
struct passwd *pwd;
bzero(&login, sizeof(login));
if (user == NULL) {
if (SCDConsoleUserGet(login,
MAXLOGNAME,
NULL,
NULL) != SCD_OK) {
return NULL;
}
} else {
(void)CFStringGetBytes(user,
CFRangeMake(0, CFStringGetLength(user)),
kCFStringEncodingMacRoman,
0,
FALSE,
login,
MAXLOGNAME,
NULL);
}
pwd = getpwnam(login);
if (pwd == NULL) {
return NULL;
}
path = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("%s/%@/%@"),
pwd->pw_dir,
PREFS_DEFAULT_USER_DIR,
prefsID);
}
} else {
if (prefsID == NULL) {
path = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("%@/%@"),
PREFS_DEFAULT_DIR,
PREFS_DEFAULT_CONFIG);
} else if (CFStringHasPrefix(prefsID, CFSTR("/"))) {
path = CFRetain(prefsID);
} else {
path = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("%@/%@"),
PREFS_DEFAULT_DIR,
prefsID);
}
}
pathLen = CFStringGetLength(path) + 1;
pathStr = CFAllocatorAllocate(NULL, pathLen, 0);
if (!CFStringGetCString(path,
pathStr,
pathLen,
kCFStringEncodingMacRoman)) {
SCDLog(LOG_DEBUG, CFSTR("could not convert path to C string"));
CFAllocatorDeallocate(NULL, pathStr);
pathStr = NULL;
}
CFRelease(path);
return pathStr;
}
SCPStatus
SCPGetSignature(SCPSessionRef session, CFDataRef *signature)
{
SCPSessionPrivateRef sessionPrivate;
if (session == NULL) {
return SCP_FAILED;
}
sessionPrivate = (SCPSessionPrivateRef)session;
*signature = sessionPrivate->signature;
return SCP_OK;
}
__private_extern__ CFStringRef
_SCPNotificationKey(CFStringRef prefsID,
boolean_t perUser,
CFStringRef user,
int keyType)
{
CFStringRef key = NULL;
char *pathStr;
char *typeStr;
pathStr = _SCPPrefsPath(prefsID, perUser, user);
if (pathStr == NULL) {
return NULL;
}
switch (keyType) {
case kSCPKeyLock :
typeStr = "lock";
break;
case kSCPKeyCommit :
typeStr = "commit";
break;
case kSCPKeyApply :
typeStr = "apply";
break;
default :
typeStr = "?";
}
key = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("%@%s:%s"),
kSCCacheDomainPrefs,
typeStr,
pathStr);
CFAllocatorDeallocate(NULL, pathStr);
return key;
}
CFStringRef
SCPNotificationKeyCreate(CFStringRef prefsID, int keyType)
{
return _SCPNotificationKey(prefsID, FALSE, NULL, keyType);
}
CFStringRef
SCPUserNotificationKeyCreate(CFStringRef prefsID, CFStringRef user, int keyType)
{
return _SCPNotificationKey(prefsID, TRUE, user, keyType);
}
const char *
SCPError(SCPStatus status)
{
int i;
for (i = 0; i < nSCP_ERRMSGS; i++) {
if (scp_errmsgs[i].status == status) {
return scp_errmsgs[i].message;
}
}
return "(unknown error)";
}