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

Side by Side Diff: ports/glibc-compat/src/realpath.c

Issue 557473002: Add working realpath implementation to glibc-compat (Closed) Base URL: https://naclports.googlecode.com/svn/trunk/src
Patch Set: Created 6 years, 3 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
« no previous file with comments | « ports/glibc-compat/Makefile ('k') | ports/glibc-compat/src/stubs.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Copyright 2014 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 /*
6 * Copied from native_client_sdk/src/libraries/nacl_io/
7 * TODO(sbc): remove this file once realpath.c is added to libnacl
8 */
9
10 #include <assert.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <limits.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18
19 char* realpath(const char* path, char* resolved_path) {
20 if (path == NULL) {
21 errno = EINVAL;
22 return NULL;
23 }
24
25 int needs_free = 0;
26 if (resolved_path == NULL) {
27 resolved_path = (char*)malloc(PATH_MAX);
28 needs_free = 1;
29 }
30
31 struct stat statbuf;
32 const char* in = path;
33 char* out = resolved_path;
34 char* out_end = resolved_path + PATH_MAX - 1;
35 int done = 0;
36
37 *out = 0;
38
39 if (*in == '/') {
40 // Absolute path.
41 strcat(out, "/");
42 in++;
43 out++;
44 } else {
45 // Relative path.
46 if (getcwd(out, out_end - out) == NULL)
47 goto fail;
48
49 out += strlen(out);
50 }
51
52 if (stat(resolved_path, &statbuf) != 0)
53 goto fail;
54
55 while (!done) {
56 const char* next_slash = strchr(in, '/');
57 size_t namelen;
58 const char* next_in;
59 if (next_slash) {
60 namelen = next_slash - in;
61 next_in = next_slash + 1;
62 } else {
63 namelen = strlen(in);
64 next_in = in + namelen; // Move to the '\0'
65 done = 1;
66 }
67
68 if (namelen == 0) {
69 // Empty name, do nothing.
70 } else if (namelen == 1 && strncmp(in, ".", 1) == 0) {
71 // Current directory, do nothing.
72 } else if (namelen == 2 && strncmp(in, "..", 2) == 0) {
73 // Parent directory, find previous slash in resolved_path.
74 char* prev_slash = strrchr(resolved_path, '/');
75 assert(prev_slash != NULL);
76
77 out = prev_slash;
78 if (prev_slash == resolved_path) {
79 // Moved to the root. Keep the slash.
80 ++out;
81 }
82
83 *out = 0;
84 } else {
85 // Append a slash if not at root.
86 if (out != resolved_path + 1) {
87 if (out + 1 > out_end) {
88 errno = ENAMETOOLONG;
89 goto fail;
90 }
91
92 strncat(out, "/", namelen);
93 out++;
94 }
95
96 if (out + namelen > out_end) {
97 errno = ENAMETOOLONG;
98 goto fail;
99 }
100
101 strncat(out, in, namelen);
102 out += namelen;
103 }
104
105 in = next_in;
106
107 if (stat(resolved_path, &statbuf) != 0)
108 goto fail;
109
110 // If there is more to the path, then the current path must be a directory.
111 if (!done && !S_ISDIR(statbuf.st_mode)) {
112 errno = ENOTDIR;
113 goto fail;
114 }
115 }
116
117 return resolved_path;
118
119 fail:
120 if (needs_free) {
121 free(resolved_path);
122 }
123 return NULL;
124 }
OLDNEW
« no previous file with comments | « ports/glibc-compat/Makefile ('k') | ports/glibc-compat/src/stubs.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698