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