Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: native_client_sdk/src/libraries/nacl_io/syscalls/realpath.c

Issue 295933009: [NaCl SDK] Add realpath(3) implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge master Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/libraries/nacl_io/syscalls/realpath.c
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/realpath.c b/native_client_sdk/src/libraries/nacl_io/syscalls/realpath.c
new file mode 100644
index 0000000000000000000000000000000000000000..9451243c70feee7603032590e2341b25d0fd1cea
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/realpath.c
@@ -0,0 +1,131 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "sdk_util/macros.h"
+
+EXTERN_C_BEGIN
+
+#if defined(__native_client__)
+
+// TODO(binji): glibc has realpath, but it fails for all tests. Investigate.
+
+char* realpath(const char* path, char* resolved_path) {
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ int needs_free = 0;
+ if (resolved_path == NULL) {
+ resolved_path = (char*)malloc(PATH_MAX);
+ needs_free = 1;
+ }
+
+ struct stat statbuf;
+ const char* in = path;
+ char* out = resolved_path;
+ char* out_end = resolved_path + PATH_MAX - 1;
+ int done = 0;
+
+ *out = 0;
+
+ if (*in == '/') {
+ // Absolute path.
+ strcat(out, "/");
+ in++;
+ out++;
+ } else {
+ // Relative path.
+ if (getcwd(out, out_end - out) == NULL)
+ goto fail;
+
+ out += strlen(out);
+ }
+
+ if (stat(resolved_path, &statbuf) != 0)
+ goto fail;
+
+ while (!done) {
+ const char* next_slash = strchr(in, '/');
+ size_t namelen;
+ const char* next_in;
+ if (next_slash) {
+ namelen = next_slash - in;
+ next_in = next_slash + 1;
+ } else {
+ namelen = strlen(in);
+ next_in = in + namelen; // Move to the '\0'
+ done = 1;
+ }
+
+ if (namelen == 0) {
+ // Empty name, do nothing.
+ } else if (namelen == 1 && strncmp(in, ".", 1) == 0) {
+ // Current directory, do nothing.
+ } else if (namelen == 2 && strncmp(in, "..", 2) == 0) {
+ // Parent directory, find previous slash in resolved_path.
+ char* prev_slash = strrchr(resolved_path, '/');
+ assert(prev_slash != NULL);
+
+ out = prev_slash;
+ if (prev_slash == resolved_path) {
+ // Moved to the root. Keep the slash.
+ ++out;
+ }
+
+ *out = 0;
+ } else {
+ // Append a slash if not at root.
+ if (out != resolved_path + 1) {
+ if (out + 1 > out_end) {
+ errno = ENAMETOOLONG;
+ goto fail;
+ }
+
+ strncat(out, "/", namelen);
+ out++;
+ }
+
+ if (out + namelen > out_end) {
+ errno = ENAMETOOLONG;
+ goto fail;
+ }
+
+ strncat(out, in, namelen);
+ out += namelen;
+ }
+
+ in = next_in;
+
+ if (stat(resolved_path, &statbuf) != 0)
+ goto fail;
+
+ // If there is more to the path, then the current path must be a directory.
+ if (!done && !S_ISDIR(statbuf.st_mode)) {
+ errno = ENOTDIR;
+ goto fail;
+ }
+ }
+
+ return resolved_path;
+
+fail:
+ if (needs_free) {
+ free(resolved_path);
+ }
+ return NULL;
+}
+
+EXTERN_C_END
+
+#endif // defined(__native_client__)
« no previous file with comments | « native_client_sdk/src/libraries/nacl_io/syscalls/mkdir.c ('k') | native_client_sdk/src/tests/nacl_io_test/example.dsc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698