macosx-nat-utils.c [plain text]
#include "defs.h"
#include "top.h"
#include "inferior.h"
#include "target.h"
#include "symfile.h"
#include "symtab.h"
#include "objfiles.h"
#include "gdb.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "gdbthread.h"
#include "regcache.h"
#include "environ.h"
#include "event-top.h"
#include "event-loop.h"
#include "inf-loop.h"
#include "gdb_stat.h"
#include "gdb_assert.h"
#include "exceptions.h"
#include "checkpoint.h"
#include "bfd.h"
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <CoreFoundation/CFURLAccess.h>
#include <CoreFoundation/CFPropertyList.h>
#include "macosx-nat-utils.h"
static const char *make_info_plist_path (const char *bundle,
const char *bundle_suffix,
const char *plist_bundle_path);
char *
macosx_filename_in_bundle (const char *filename, int mainline)
{
const char *info_plist_filename = NULL;
char *full_pathname = NULL;
const void *plist = NULL;
int shallow_bundle = 0;
if (!mainline)
return NULL;
info_plist_filename = make_info_plist_path (filename, ".app", "Info.plist");
if (info_plist_filename)
plist = macosx_parse_plist (info_plist_filename);
if (plist != NULL)
{
shallow_bundle = 1;
}
else
{
xfree ((char *) info_plist_filename);
info_plist_filename = make_info_plist_path (filename, ".app",
"Contents/Info.plist");
if (info_plist_filename)
plist = macosx_parse_plist (info_plist_filename);
}
if (plist != NULL)
{
const char *bundle_exe_from_plist;
bundle_exe_from_plist = macosx_get_plist_posix_value (plist,
"CFBundleExecutable");
macosx_free_plist (&plist);
if (bundle_exe_from_plist != NULL)
{
int info_plist_dir_len = strlen (info_plist_filename) -
strlen ("Info.plist");
int full_pathname_length = info_plist_dir_len +
strlen (bundle_exe_from_plist) + 1;
if (!shallow_bundle)
full_pathname_length += strlen ("MacOS/");
full_pathname = xmalloc (full_pathname_length);
if (full_pathname)
{
memcpy (full_pathname, info_plist_filename, info_plist_dir_len);
full_pathname[info_plist_dir_len] = '\0';
if (!shallow_bundle)
strcat (full_pathname, "MacOS/");
strcat (full_pathname, bundle_exe_from_plist);
gdb_assert ( strlen(full_pathname) + 1 == full_pathname_length );
}
xfree ((char *) bundle_exe_from_plist);
}
}
if (info_plist_filename)
xfree ((char *) info_plist_filename);
return full_pathname;
}
static const char *
make_info_plist_path (const char *bundle, const char *bundle_suffix,
const char *plist_bundle_path)
{
char plist_path[PATH_MAX];
char plist_realpath[PATH_MAX];
char *bundle_suffix_pos = NULL;
char *t = NULL;
int bundle_suffix_len = strlen (bundle_suffix);
for (t = strstr (bundle, bundle_suffix); t != NULL;
t = strstr (t+1, bundle_suffix))
bundle_suffix_pos = t;
if (bundle_suffix_pos != NULL && bundle_suffix_pos > bundle)
{
int bundle_dir_len = (bundle_suffix_pos - bundle) + bundle_suffix_len;
int info_plist_len = bundle_dir_len + 1 + strlen (plist_bundle_path) + 1;
if (info_plist_len < PATH_MAX)
{
memcpy (plist_path, bundle, bundle_dir_len);
plist_path[bundle_dir_len] = '/';
plist_path[bundle_dir_len+1] = '\0';
strcat (plist_path, plist_bundle_path);
gdb_assert ( strlen(plist_path) + 1 == info_plist_len );
if (realpath (plist_path, plist_realpath) == NULL)
return xstrdup (plist_path);
else
return xstrdup (plist_realpath);
}
}
return NULL;
}
const void *
macosx_parse_plist (const char *path)
{
CFPropertyListRef plist = NULL;
const char url_header[] = "file://";
char *url_text = NULL;
CFURLRef url = NULL;
CFAllocatorRef cf_alloc = kCFAllocatorDefault;
size_t url_text_len = (sizeof (url_header) - 1) + strlen (path) + 1;
url_text = xmalloc (url_text_len);
strcpy (url_text, url_header);
strcat (url_text, path);
url = CFURLCreateWithBytes (cf_alloc, (const UInt8 *)url_text,
url_text_len, kCFStringEncodingUTF8, NULL);
if (url)
{
CFDataRef data = NULL;
if (CFURLCreateDataAndPropertiesFromResource (cf_alloc, url, &data,
NULL, NULL,NULL)
&& data != NULL)
{
plist = CFPropertyListCreateFromXMLData (cf_alloc, data,
kCFPropertyListImmutable,
NULL);
CFRelease (data);
if (plist != NULL)
{
if (CFGetTypeID (plist) != CFDictionaryGetTypeID ())
{
CFRelease (plist);
plist = NULL;
}
}
}
CFRelease (url);
}
xfree (url_text);
return plist;
}
const char *
macosx_get_plist_posix_value (const void *plist, const char* key)
{
char *value = NULL;
if (plist == NULL)
return NULL;
CFStringRef cf_key = CFStringCreateWithCString (kCFAllocatorDefault, key,
kCFStringEncodingUTF8);
CFStringRef cf_value = CFDictionaryGetValue ((CFDictionaryRef) plist, cf_key);
if (cf_value != NULL && CFGetTypeID (cf_value) == CFStringGetTypeID ())
{
CFIndex max_value_len = CFStringGetMaximumSizeOfFileSystemRepresentation
(cf_value);
if (max_value_len > 0)
{
value = (char *)xmalloc (max_value_len + 1);
if (value)
{
if (!CFStringGetFileSystemRepresentation (cf_value, value,
max_value_len))
{
xfree (value);
value = NULL;
}
}
}
}
return value;
}
const char *
macosx_get_plist_string_value (const void *plist, const char* key)
{
char *value = NULL;
if (plist == NULL)
return NULL;
CFStringRef cf_key = CFStringCreateWithCString (kCFAllocatorDefault, key,
kCFStringEncodingUTF8);
CFStringRef cf_value = CFDictionaryGetValue ((CFDictionaryRef) plist, cf_key);
if (cf_value != NULL && CFGetTypeID (cf_value) == CFStringGetTypeID ())
{
CFIndex max_value_len = CFStringGetLength (cf_value);
max_value_len = CFStringGetMaximumSizeForEncoding (max_value_len,
kCFStringEncodingUTF8);
if (max_value_len > 0)
{
value = xmalloc (max_value_len + 1);
if (value)
{
if (!CFStringGetCString (cf_value, value, max_value_len,
kCFStringEncodingUTF8))
{
xfree (value);
value = NULL;
}
}
}
}
return value;
}
void
macosx_free_plist (const void **plist)
{
if (*plist != NULL)
{
CFRelease ((CFPropertyListRef)*plist);
*plist = NULL;
}
}