aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/xcode
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2015-06-30 21:15:44 +0000
committerGravatar Florian Weikert <fwe@google.com>2015-07-01 09:17:26 +0000
commitf64f2117894f01c50c9460ccb841474b78a1aff0 (patch)
tree905e256d8cb090c8bd5601d66036233b70ad12be /src/tools/xcode
parentc057d47e9b81385889b7989ddc6dcccf076e4231 (diff)
Implementation of realpath for Mac OS X. This will allow us to move some of our tools (ibtool, actool etc) to shell scripts which should be faster and easier to maintain.
RELNOTES: -- MOS_MIGRATED_REVID=97263085
Diffstat (limited to 'src/tools/xcode')
-rw-r--r--src/tools/xcode/realpath/BUILD11
-rw-r--r--src/tools/xcode/realpath/README14
-rw-r--r--src/tools/xcode/realpath/realpath.c103
3 files changed, 128 insertions, 0 deletions
diff --git a/src/tools/xcode/realpath/BUILD b/src/tools/xcode/realpath/BUILD
new file mode 100644
index 0000000000..0dc2455a81
--- /dev/null
+++ b/src/tools/xcode/realpath/BUILD
@@ -0,0 +1,11 @@
+package(default_visibility = ["//src:__subpackages__"])
+
+# This target will only build on a Mac.
+genrule(
+ name = "realpath_genrule",
+ srcs = ["realpath.c"],
+ outs = ["realpath"],
+ cmd = "/usr/bin/xcrun clang -o $@ $<",
+ output_to_bindir = 1,
+ visibility = ["//visibility:public"],
+)
diff --git a/src/tools/xcode/realpath/README b/src/tools/xcode/realpath/README
new file mode 100644
index 0000000000..66ab1795cc
--- /dev/null
+++ b/src/tools/xcode/realpath/README
@@ -0,0 +1,14 @@
+realpath is a simple implementation of the realpath utility:
+http://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html
+since Mac OS X does not have anything equivalent.
+
+This version takes no options.
+
+This is based on the default GNU/Linux implementation that allows the last
+component to not exist. This is different than the Debian implementation that
+requires the last component to exist. Supporting the GNU/Linux implementation
+makes writing scripts that depend on realpath much easier, and is probably
+closer to what Apple may actually ship as a realpath implementation in the
+future.
+
+realpath only builds/runs on Darwin.
diff --git a/src/tools/xcode/realpath/realpath.c b/src/tools/xcode/realpath/realpath.c
new file mode 100644
index 0000000000..06addf38c7
--- /dev/null
+++ b/src/tools/xcode/realpath/realpath.c
@@ -0,0 +1,103 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// realpath.c
+//
+// A simple implementation of realpath for Mac OS X.
+// This implementation follows gnu/linux conventions and allows the last
+// component to not exist:
+// http://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html
+// Debian requires all components to exist.
+//
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Print a simple error message and exit.
+static void PrintError(const char *argv[]) {
+ fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+ exit(1);
+}
+
+// Concatenate two paths together adding a '/' if appropriate.
+// Returned pointer is owned by client and should be freed.
+static char *JoinPaths(const char *path1, const char* path2) {
+ size_t len1 = strlen(path1);
+ size_t len2 = strlen(path2);
+ // +1 for '/' and +1 for '\0'
+ size_t totalSize = len1 + 1 + len2 + 1;
+ char *outPath = malloc(totalSize);
+ if (outPath == NULL) {
+ return NULL;
+ }
+ strlcpy(outPath, path1, totalSize);
+ if (len1 > 0 && len2 > 0) {
+ if (path1[len1 - 1] != '/' && path2[0] != '/') {
+ strlcat(outPath, "/", totalSize);
+ }
+ }
+ strlcat(outPath, path2, totalSize);
+ return outPath;
+}
+
+// Since this is a simple utility that quits immediately, we are not worrying
+// about making the code more complex by freeing up any memory allocations.
+int main(int argc, const char *argv[]) {
+ if (argc != 2) {
+ fprintf(stderr, "realpath <path>\n");
+ return 1;
+ }
+ const char *path = argv[1];
+ char *goodPath = realpath(path, NULL);
+ if (goodPath == NULL) {
+ if ((errno != ENOENT) || (strlen(path) == 0)) {
+ PrintError(argv);
+ }
+
+ // If only the last element is missing, then call realpath on the parent
+ // dir and append the basename back onto it.
+
+ // Technically the strdup is not required on Mac OS X, but this
+ // keeps things compatible with other basename/dirname implementations
+ // that do require a string they can modify.
+ char *dirCopy = strdup(path);
+ char *baseCopy = strdup(path);
+ if (dirCopy == NULL || baseCopy == NULL) {
+ PrintError(argv);
+ }
+ char *dir = dirname(dirCopy);
+ if (dir == NULL) {
+ PrintError(argv);
+ }
+ char *base = basename(baseCopy);
+ if (base == NULL) {
+ PrintError(argv);
+ }
+ char *realdir = realpath(dir, NULL);
+ if (realdir == NULL) {
+ PrintError(argv);
+ }
+ goodPath = JoinPaths(realdir, base);
+ if (goodPath == NULL) {
+ PrintError(argv);
+ }
+ }
+ fprintf(stdout, "%s\n", goodPath);
+ return 0;
+}