diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2000-12-09 01:20:32 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2000-12-09 01:20:32 +0000 |
commit | 2efbc2a7dfa35d14c29c5c66837dc09f07c949ac (patch) | |
tree | e4a03a7344f83176b68f65a551ee04daa9f229ff /newlib/libc/sys/linux/realpath.c | |
parent | a08c98bb808d1a1806c93be0b7934a19f48b5a0a (diff) | |
download | cygnal-2efbc2a7dfa35d14c29c5c66837dc09f07c949ac.tar.gz cygnal-2efbc2a7dfa35d14c29c5c66837dc09f07c949ac.tar.bz2 cygnal-2efbc2a7dfa35d14c29c5c66837dc09f07c949ac.zip |
2000-12-08 Werner Almesberger <Werner.Almesberger@epfl.ch>
* configure.host: Added x86 linux target.
* libc/unix/getpass.c (_PATH_PASSWD, _PASSWORD_LEN): Default
definitions provided if not already defined.
* libc/sys/linux/crt0.c: New file.
* libc/sys/linux/Makefile.am: Ditto.
* libc/sys/linux/Makefile.in: Ditto.
* libc/sys/linux/aclocal.m4: Ditto.
* libc/sys/linux/brk.c: Ditto.
* libc/sys/linux/configure: Ditto.
* libc/sys/linux/configure.in: Ditto.
* libc/sys/linux/getoptlong.c: Ditto.
* libc/sys/linux/ids.c: Ditto.
* libc/sys/linux/inode.c: Ditto.
* libc/sys/linux/io.c: Ditto.
* libc/sys/linux/linux.c: Ditto.
* libc/sys/linux/process.c: Ditto.
* libc/sys/linux/realpath.c: Ditto.
* libc/sys/linux/select.c: Ditto.
* libc/sys/linux/signal.c: Ditto.
* libc/sys/linux/systat.c: Ditto.
* libc/sys/linux/termios.c: Ditto.
* libc/sys/linux/time.c: Ditto.
* libc/sys/linux/wait.c: Ditto.
* libc/sys/linux/include/alloca.h: Ditto.
* libc/sys/linux/include/getopt.h: Ditto.
* libc/sys/linux/include/stdint.h: Ditto.
* libc/sys/linux/include/unistd.h: Ditto.
* libc/sys/linux/sys/cdefs.h: Ditto.
* libc/sys/linux/sys/dirent.h: Ditto.
* libc/sys/linux/sys/errno.h: Ditto.
* libc/sys/linux/sys/fcntl.h: Ditto.
* libc/sys/linux/sys/file.h: Ditto.
* libc/sys/linux/sys/ioctl.h: Ditto.
* libc/sys/linux/sys/resource.h: Ditto.
* libc/sys/linux/sys/signal.h: Ditto.
* libc/sys/linux/sys/stat.h: Ditto.
* libc/sys/linux/sys/syscall.h: Ditto.
* libc/sys/linux/sys/termios.h: Ditto.
* libc/sys/linux/sys/time.h: Ditto.
* libc/sys/linux/sys/types.h: Ditto.
* libc/sys/linux/sys/utmp.h: Ditto.
* libc/sys/linux/sys/utsname.h: Ditto.
* libc/sys/linux/sys/wait.h: Ditto.
Diffstat (limited to 'newlib/libc/sys/linux/realpath.c')
-rw-r--r-- | newlib/libc/sys/linux/realpath.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/newlib/libc/sys/linux/realpath.c b/newlib/libc/sys/linux/realpath.c new file mode 100644 index 000000000..8aa5eb445 --- /dev/null +++ b/newlib/libc/sys/linux/realpath.c @@ -0,0 +1,92 @@ +/* realpath.c - Return the canonicalized absolute pathname */ + +/* Written 2000 by Werner Almesberger */ + + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <limits.h> +#include <errno.h> +#include <sys/stat.h> + + +/* FIXME: buffer overrun possible, loops forever on cyclic symlinks */ + + +/* + * Canonical name: never ends with a slash + */ + +static int resolve_path(char *path,char *result,char *pos) +{ + if (*path == '/') { + *result = '/'; + pos = result+1; + path++; + } + *pos = 0; + if (!*path) return 0; + while (1) { + char *slash; + struct stat st; + + slash = *path ? strchr(path,'/') : NULL; + if (slash) *slash = 0; + if (!path[0] || (path[0] == '.' && + (!path[1] || (path[1] == '.' && !path[2])))) { + pos--; + if (pos != result && path[0] && path[1]) + while (*--pos != '/'); + } + else { + strcpy(pos,path); + if (lstat(result,&st) < 0) return -1; + if (S_ISLNK(st.st_mode)) { + char buf[PATH_MAX]; + + if (readlink(result,buf,sizeof(buf)) < 0) return -1; + *pos = 0; + if (slash) { + *slash = '/'; + strcat(buf,slash); + } + strcpy(path,buf); + if (*path == '/') result[1] = 0; + pos = strchr(result,0); + continue; + } + pos = strchr(result,0); + } + if (slash) { + *pos++ = '/'; + path = slash+1; + } + *pos = 0; + if (!slash) break; + } + return 0; +} + + +char *realpath(const char *path,char *resolved_path) +{ + char cwd[PATH_MAX]; + char *path_copy; + int res; + + if (!*path) { + errno = ENOENT; /* SUSv2 */ + return NULL; + } + if (!getcwd(cwd,sizeof(cwd))) return NULL; + strcpy(resolved_path,"/"); + if (resolve_path(cwd,resolved_path,resolved_path)) return NULL; + strcat(resolved_path,"/"); + path_copy = strdup(path); + if (!path_copy) return NULL; + res = resolve_path(path_copy,resolved_path,strchr(resolved_path,0)); + free(path_copy); + if (res) return NULL; + return resolved_path; +} |