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

Side by Side 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: Fix pnacl and add comment about linux standalone test 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* Copyright 2013 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. */
4
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13
14 #include "sdk_util/macros.h"
15
16 EXTERN_C_BEGIN
17
18 #if defined(__native_client__)
19
20 // TODO(binji): glibc has realpath, but it fails for all tests. Investigate.
21
22 char* realpath(const char* path, char* resolved_path) {
23 if (path == NULL) {
24 errno = EINVAL;
25 return NULL;
26 }
27
28 int needs_free = 0;
29 if (resolved_path == NULL) {
30 resolved_path = (char*)malloc(PATH_MAX);
31 needs_free = 1;
32 }
33
34 struct stat statbuf;
35 const char* in = path;
36 char* out = resolved_path;
37 char* out_end = resolved_path + PATH_MAX - 1;
38 int done = 0;
39
40 *out = 0;
41
42 if (*in == '/') {
43 // Absolute path.
44 strcat(out, "/");
45 in++;
46 out++;
47 } else {
48 // Relative path.
49 if (getcwd(out, out_end - out) == NULL)
50 goto fail;
51
52 out += strlen(out);
53 }
54
55 if (stat(resolved_path, &statbuf) != 0)
56 goto fail;
57
58 while (!done) {
59 const char* next_slash = strchr(in, '/');
60 size_t namelen;
61 const char* next_in;
62 if (next_slash) {
63 namelen = next_slash - in;
64 next_in = next_slash + 1;
65 } else {
66 namelen = strlen(in);
67 next_in = in + namelen; // Move to the '\0'
68 done = 1;
69 }
70
71 if (namelen == 0) {
72 // Empty name, do nothing.
73 } else if (namelen == 1 && strncmp(in, ".", 1) == 0) {
74 // Current directory, do nothing.
75 } else if (namelen == 2 && strncmp(in, "..", 2) == 0) {
76 // Parent directory, find previous slash in resolved_path.
77 char* prev_slash = strrchr(resolved_path, '/');
78 assert(prev_slash != NULL);
79
80 out = prev_slash;
81 if (prev_slash == resolved_path) {
82 // Moved to the root. Keep the slash.
83 ++out;
84 }
85
86 *out = 0;
87 } else {
88 // Append a slash if not at root.
89 if (out != resolved_path + 1) {
90 if (out + 1 > out_end) {
91 errno = ENAMETOOLONG;
92 goto fail;
93 }
94
95 strncat(out, "/", namelen);
96 out++;
97 }
98
99 if (out + namelen > out_end) {
100 errno = ENAMETOOLONG;
101 goto fail;
102 }
103
104 strncat(out, in, namelen);
105 out += namelen;
106 }
107
108 in = next_in;
109
110 if (stat(resolved_path, &statbuf) != 0)
111 goto fail;
112
113 // If there is more to the path, then the current path must be a directory.
114 if (!done && !S_ISDIR(statbuf.st_mode)) {
115 errno = ENOTDIR;
116 goto fail;
117 }
118 }
119
120 return resolved_path;
121
122 fail:
123 if (needs_free) {
124 free(resolved_path);
125 }
126 return NULL;
127 }
128
129 EXTERN_C_END
130
131 #endif // defined(__native_client__)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698