mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

129 lines
3.4 KiB

--- ./libshell/realpath.c 27 Jan 2004 21:50:42 -0000 1.9
+++ ./libshell/realpath.c 10 May 2004 16:44:14 -0000 1.10
@@ -1,14 +1,3 @@
-/* realpath - determine the absolute pathname of a file
-
- Copyright (C) 2003 Thomas M. Ogrisegg <tom-dietlibc@fnord.at>
-
- This realpath has still space for improvements:
- e.g., if the initial path does not start with '/' it should
- be checked whether the first path component(s) is/are symlinks.
- This would save lots of filesystem lookups, but also greatly
- increases complexity.
-*/
-
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
@@ -16,75 +5,44 @@
#include <errno.h>
#include <unistd.h>
#include <string.h>
+#include <fcntl.h>
-#define CD(x) (x=='/'||!x)
-
-char *
-realpath (const char *file, char *dst)
-{
- unsigned char buffer[PATH_MAX];
- size_t i, off;
-
- if (!file || !dst) { errno = EINVAL; return (NULL); }
- if (!*file) { errno = ENOENT; return (NULL); }
-
- if (*file != '/') {
- if (!getcwd (buffer, sizeof (buffer))) return (NULL);
- off = strlen (buffer);
- while (file[0] == '.' && file[1] == '.' && file[2] == '/') {
- if (off) off--;
- while (off && buffer[off] != '/') off--;
- file += 3;
- }
- buffer[off++] = '/';
- i = strlen (file);
- if (i+off >= PATH_MAX) return (NULL);
- memcpy (buffer+off, file, i+1);
- file = buffer;
+static char* myrealpath(const char* file, char* dest, int count) {
+/* assume dest has PATH_MAX space */
+ char buf[PATH_MAX+1];
+ char* c;
+ int i;
+
+ if (count<0) { errno=EMLINK; return 0; }
+ if (chdir(file)==0)
+ /* hurray! The easy case: it's a directory! */
+ return getcwd(dest,PATH_MAX);
+
+ c=strrchr(file,'/');
+ if (c) {
+ if (c-file>PATH_MAX) return 0;
+ memcpy(buf,file,c-file);
+ buf[c-file]=0;
+ if (chdir(buf)==-1) return 0;
+ file=c+1;
}
-
- off = i = 0;
-
- while (file[i]) {
- if (file[i] == '.' && file[i-1] == '/' &&
- ((file[i+1] == '.'&&CD(file[i+2])) || CD(file[i+1]))) {
- if (file[i+1] == '/') { i+=2; continue; }
- if (file[i+1] == '.') {
- if (off > 2) off -= 2;
- while (off && dst[off] != '/') off--;
- i++;
- }
- i++;
- continue;
- }
-
- if (file[i] == '/' && off < PATH_MAX) {
- unsigned char buf[PATH_MAX];
- int ret;
-
- if (file[i+1] == '/') { i+=2; continue; }
-
- if (off) {
- if (dst[off-1] == '/') { i++; continue; }
-
-last_test:
- dst[off] = 0;
- if (-1 != (ret = readlink (dst, buf, sizeof (buf)))) {
- struct stat st;
- buf[ret] = 0;
- if (-1 == stat (buf, &st)) return (NULL);
- if (ret+(PATH_MAX-i) > PATH_MAX) return (NULL);
- strcpy (buf+ret, file+i);
- return (realpath (buf, dst));
- } else
- if (errno == EACCES || errno == ENOENT) return (NULL);
-
- if (!file[i]) return (dst);
- }
- }
- dst[off++] = file[i++];
+ if (readlink(file,buf,PATH_MAX)==0)
+ return myrealpath(buf,dest,count-1);
+ if (getcwd(dest,PATH_MAX)==0) return 0;
+ i=strlen(dest); dest[i]='/'; ++i;
+ for (; i<PATH_MAX-1; ++i) {
+ if (!(dest[i]=*file)) break;
+ ++file;
}
+ dest[i]=0;
+ return dest;
+}
- if (off > 2 && dst[off-1] == '/') off--;
- goto last_test;
+char* realpath(const char* file, char* dest) {
+ int fd=open(".",O_RDONLY); /* save directory */
+ char* res=myrealpath(file,dest,31);
+ fchdir(fd);
+ close(fd);
+ return res;
}
+