123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- #include "porting.h"
- #define MAX_READLINKS 32
- char *chroot_realpath(const char *root, const char *path,
- char resolved_path[]);
- char *chroot_realpath(const char *root, const char *path,
- char resolved_path[])
- {
- char copy_path[PATH_MAX];
- char link_path[PATH_MAX];
- char got_path[PATH_MAX];
- char *got_path_root = got_path;
- char *new_path = got_path;
- char *max_path;
- int readlinks = 0;
- int n;
- int chroot_len;
-
- if (root == NULL || *root == '\0' ||
- (*root == '/' && root[1] == '\0')) {
- strcpy(resolved_path, path);
- return resolved_path;
- }
- chroot_len = strlen(root);
- if (chroot_len + strlen(path) >= PATH_MAX - 3) {
- errno = ENAMETOOLONG;
- return NULL;
- }
-
- strcpy(copy_path, path);
- path = copy_path;
- max_path = copy_path + PATH_MAX - chroot_len - 3;
-
- strcpy(new_path, root);
- new_path += chroot_len;
- while (*new_path == '/' && new_path > got_path)
- new_path--;
- got_path_root = new_path;
- *new_path++ = '/';
-
- while (*path != '\0') {
-
- if (*path == '/') {
- path++;
- continue;
- }
- if (*path == '.') {
-
- if (path[1] == '\0' || path[1] == '/') {
- path++;
- continue;
- }
- if (path[1] == '.') {
- if (path[2] == '\0' || path[2] == '/') {
- path += 2;
-
- if (new_path == got_path_root + 1)
- continue;
-
- while ((--new_path)[-1] != '/') ;
- continue;
- }
- }
- }
-
- while (*path != '\0' && *path != '/') {
- if (path > max_path) {
- errno = ENAMETOOLONG;
- return NULL;
- }
- *new_path++ = *path++;
- }
- if (*path == '\0')
-
- break;
- #ifdef S_IFLNK
-
- if (readlinks++ > MAX_READLINKS) {
- errno = ELOOP;
- return NULL;
- }
-
- *new_path = '\0';
- n = readlink(got_path, link_path, PATH_MAX - 1);
- if (n < 0) {
-
- if (errno != EINVAL) {
-
- *new_path = '\0';
- strcpy(resolved_path, got_path);
- return NULL;
- }
- } else {
-
- link_path[n] = '\0';
- if (*link_path == '/')
-
- new_path = got_path_root;
- else
-
- while (*(--new_path) != '/') ;
-
- if (strlen(path) + n >= PATH_MAX - 2) {
- errno = ENAMETOOLONG;
- return NULL;
- }
-
- strcat(link_path, path);
- strcpy(copy_path, link_path);
- path = copy_path;
- }
- #endif
- *new_path++ = '/';
- }
-
- if (new_path != got_path + 1 && new_path[-1] == '/')
- new_path--;
-
- *new_path = '\0';
- strcpy(resolved_path, got_path);
- return resolved_path;
- }
|