/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #include int __solve_dir_symlinks(const char * __symlink_path, char * __real_path) { char path_copy[FILENAME_MAX]; char * last_part; int is_root = 0; /* Reject NULLs... */ if (!__symlink_path || !__real_path) { errno = EINVAL; return 0; } /* ...and empty strings */ if (__symlink_path[0] == '\0') { errno = ENOENT; return 0; } /* Handle root directories */ if ( ((__symlink_path[0] == '/') || (__symlink_path[0] == '\\')) && (__symlink_path[1] == '\0')) is_root = 1; if ( __symlink_path[0] && (__symlink_path[1] == ':') && ((__symlink_path[2] == '/') || (__symlink_path[2] == '\\')) && (__symlink_path[3] == '\0')) is_root = 1; if (is_root) { strcpy(__real_path, __symlink_path); return 1; } strcpy(path_copy, __symlink_path); last_part = basename(path_copy); if (*last_part == '\0') { /* If basename() returned pointer to the end of string, cut the last * dir separator and try again. Exception: for paths like 'C:', just * copy it to the result and return. */ if (*(last_part - 1) == ':') { strcpy(__real_path, path_copy); return 1; } *(last_part - 1) = '\0'; last_part = basename(path_copy); } if (last_part == path_copy) { /* The path is made from single part */ strcpy(__real_path, path_copy); return 1; } /* If the have path like c:/file or c:file, just copy it to the result * and return. */ if (*(last_part - 1) == ':') { strcpy(__real_path, path_copy); return 1; } *(last_part - 1) = '\0'; if (!__solve_symlinks(path_copy, __real_path)) return 0; strcat(__real_path, "/"); strcat(__real_path, last_part); return 1; } #ifdef TEST #include int main(int argc, char *argv[]) { char buf[FILENAME_MAX]; int i; puts("User requested tests:"); for (i = 1; i < argc; i++) { __solve_dir_symlinks(argv[i], buf); printf("%s -> %s\n", argv[i], buf); } return EXIT_SUCCESS; } #endif