]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: set the initial working directory
authorDavid Crawshaw <crawshaw@golang.org>
Wed, 25 Feb 2015 21:11:53 +0000 (16:11 -0500)
committerDavid Crawshaw <crawshaw@golang.org>
Wed, 25 Feb 2015 22:22:02 +0000 (22:22 +0000)
Gives tests a way to find the bundle that contains their testdata, and
is generally useful for finding resources.

Change-Id: Idfa03e8543af927c17bc8ec8aadc5014ec82df28
Reviewed-on: https://go-review.googlesource.com/6000
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
src/runtime/cgo/cgo.go
src/runtime/cgo/gcc_darwin_arm.c

index 9a41399cd6e66c6504bc4df9c385e90af6fb2864..510a817c3219cf6946e4c8b05d778c7841ec650e 100644 (file)
@@ -12,6 +12,7 @@ package cgo
 /*
 
 #cgo darwin,!arm LDFLAGS: -lpthread
+#cgo darwin,arm LDFLAGS: -framework CoreFoundation
 #cgo dragonfly LDFLAGS: -lpthread
 #cgo freebsd LDFLAGS: -lpthread
 #cgo android LDFLAGS: -llog
index d56c55777d316b3ea2853ec1899d3fb76ca7372b..521964c97357c12673881cb9a4f01de2efed9164 100644 (file)
@@ -2,10 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include <string.h> /* for strerror */
+#include <limits.h>
 #include <pthread.h>
 #include <signal.h>
-#include <limits.h>
+#include <string.h> /* for strerror */
+#include <sys/param.h>
+#include <unistd.h>
+
+#include <CoreFoundation/CFBundle.h>
+#include <CoreFoundation/CFString.h>
+
 #include "libcgo.h"
 
 #define magic (0xe696c4f4U)
@@ -82,6 +88,43 @@ threadentry(void *v)
        return nil;
 }
 
+// init_working_dir sets the current working directory to the app root.
+// By default darwin/arm processes start in "/".
+static void
+init_working_dir()
+{
+       CFBundleRef bundle = CFBundleGetMainBundle();
+       if (bundle == NULL) {
+               fprintf(stderr, "runtime/cgo: no main bundle\n");
+               return;
+       }
+       CFURLRef url_ref = CFBundleCopyResourceURL(bundle, CFSTR("Info"), CFSTR("plist"), NULL);
+       if (url_ref == NULL) {
+               fprintf(stderr, "runtime/cgo: no Info.plist URL\n");
+               return;
+       }
+       CFStringRef url_str_ref = CFURLGetString(url_ref);
+       char url[MAXPATHLEN];
+        if (!CFStringGetCString(url_str_ref, url, sizeof(url), kCFStringEncodingUTF8)) {
+               fprintf(stderr, "runtime/cgo: cannot get URL string\n");
+               return;
+       }
+
+       // url is of the form "file:///path/to/Info.plist".
+       // strip it down to the working directory "/path/to".
+       int url_len = strlen(url);
+       if (url_len < sizeof("file://")+sizeof("/Info.plist")) {
+               fprintf(stderr, "runtime/cgo: bad URL: %s\n", url);
+               return;
+       }
+       url[url_len-sizeof("/Info.plist")+1] = 0;
+       char *dir = &url[0] + sizeof("file://")-1;
+
+       if (chdir(dir) != 0) {
+               fprintf(stderr, "runtime/cgo: chdir(%s) failed\n", dir);
+       }
+}
+
 void
 x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
 {
@@ -96,4 +139,6 @@ x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
 
        // yes, tlsbase from mrc might not be correctly aligned.
        inittls(tlsg, (void**)((uintptr)tlsbase & ~3));
+
+       init_working_dir();
 }