Calculate_relative_path(): fix when using symlinks
This commit is contained in:
		
							parent
							
								
									40fc2f2bee
								
							
						
					
					
						commit
						4ad13b57a8
					
				
							
								
								
									
										42
									
								
								src/io.c
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/io.c
									
									
									
									
									
								
							@ -1131,6 +1131,7 @@ int Remove_directory(const char * path)
 | 
			
		||||
char * Calculate_relative_path(const char * ref_path, const char * path)
 | 
			
		||||
{
 | 
			
		||||
  char * real_ref_path;
 | 
			
		||||
  char * real_path;
 | 
			
		||||
  char * rel_path = NULL;
 | 
			
		||||
  int last_separator = -1;
 | 
			
		||||
  int i;
 | 
			
		||||
@ -1142,67 +1143,75 @@ char * Calculate_relative_path(const char * ref_path, const char * path)
 | 
			
		||||
  real_ref_path = Realpath(ref_path, NULL);
 | 
			
		||||
  if (real_ref_path == NULL)
 | 
			
		||||
    real_ref_path = strdup(ref_path);
 | 
			
		||||
  real_path = Realpath(path, NULL);
 | 
			
		||||
  if (real_path == NULL)
 | 
			
		||||
    real_path = strdup(path);
 | 
			
		||||
#if defined(WIN32) || defined(__MINT__)
 | 
			
		||||
  if (real_ref_path[1] == ':' && path[1] == ':')
 | 
			
		||||
  if (real_ref_path[1] == ':' && real_path[1] == ':')
 | 
			
		||||
  {
 | 
			
		||||
    // use same case for drive letter
 | 
			
		||||
    real_ref_path[0] = (real_ref_path[0] & ~32) | (path[0] & 32);
 | 
			
		||||
    if (real_ref_path[0] != path[0])
 | 
			
		||||
    real_ref_path[0] = (real_ref_path[0] & ~32) | (real_path[0] & 32);
 | 
			
		||||
    if (real_ref_path[0] != real_path[0])
 | 
			
		||||
    {
 | 
			
		||||
      free(real_ref_path);
 | 
			
		||||
      free(real_path);
 | 
			
		||||
      return NULL;  // path on different volumes, not possible
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  // look for common path parts
 | 
			
		||||
  for (i = 0; real_ref_path[i] == path[i] && path[i] != '\0'; i++)
 | 
			
		||||
  for (i = 0; real_ref_path[i] == real_path[i] && real_path[i] != '\0'; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (path[i] == PATH_SEPARATOR[0])
 | 
			
		||||
    if (real_path[i] == PATH_SEPARATOR[0])
 | 
			
		||||
      last_separator = i;
 | 
			
		||||
#if defined(WIN32)
 | 
			
		||||
    else if(path[i] == '/')
 | 
			
		||||
    else if(real_path[i] == '/')
 | 
			
		||||
      last_separator = i;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
  // at this point, all chars from index 0 to i-1 are identical in
 | 
			
		||||
  // real_ref_path and path.
 | 
			
		||||
  // real_ref_path[i] and path[i] are either different, or both '\0'
 | 
			
		||||
  if (real_ref_path[i] == PATH_SEPARATOR[0] && real_ref_path[i + 1] == '\0' && path[i] == '\0')
 | 
			
		||||
  if (real_ref_path[i] == PATH_SEPARATOR[0] && real_ref_path[i + 1] == '\0' && real_path[i] == '\0')
 | 
			
		||||
  {
 | 
			
		||||
    free(real_ref_path);
 | 
			
		||||
    free(real_path);
 | 
			
		||||
    return strdup("."); // path are identical (real_ref_path has additional trailing separator)
 | 
			
		||||
  }
 | 
			
		||||
  if (real_ref_path[i] == '\0')
 | 
			
		||||
  {
 | 
			
		||||
    if (path[i] == '\0')
 | 
			
		||||
    if (real_path[i] == '\0')
 | 
			
		||||
    {
 | 
			
		||||
      free(real_ref_path);
 | 
			
		||||
      free(real_path);
 | 
			
		||||
      return strdup("."); // path are identical
 | 
			
		||||
    }
 | 
			
		||||
    // path is under ref_path
 | 
			
		||||
    if (path[i] == PATH_SEPARATOR[0])
 | 
			
		||||
    if (real_path[i] == PATH_SEPARATOR[0])
 | 
			
		||||
    {
 | 
			
		||||
      free(real_ref_path);
 | 
			
		||||
      len = strlen(path + i) + 1;
 | 
			
		||||
      len = strlen(real_path + i) + 1;
 | 
			
		||||
      rel_path = GFX2_malloc(len + 1);
 | 
			
		||||
      if (rel_path != NULL)
 | 
			
		||||
        snprintf(rel_path, len + 1, ".%s", path + i);
 | 
			
		||||
        snprintf(rel_path, len + 1, ".%s", real_path + i);
 | 
			
		||||
      free(real_path);
 | 
			
		||||
      return rel_path;
 | 
			
		||||
    }
 | 
			
		||||
    else if (i > 0 && real_ref_path[i - 1] == PATH_SEPARATOR[0])
 | 
			
		||||
    {
 | 
			
		||||
      free(real_ref_path);
 | 
			
		||||
      len = strlen(path + i - 1) + 1;
 | 
			
		||||
      len = strlen(real_path + i - 1) + 1;
 | 
			
		||||
      rel_path = GFX2_malloc(len + 1);
 | 
			
		||||
      if (rel_path != NULL)
 | 
			
		||||
        snprintf(rel_path, len + 1, ".%s", path + i - 1);
 | 
			
		||||
        snprintf(rel_path, len + 1, ".%s", real_path + i - 1);
 | 
			
		||||
      free(real_path);
 | 
			
		||||
      return rel_path;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (last_separator <= 0)
 | 
			
		||||
  {
 | 
			
		||||
    free(real_ref_path);
 | 
			
		||||
    return strdup(path);  // no common part found return absolute path
 | 
			
		||||
    return real_path;  // no common part found return absolute path
 | 
			
		||||
  }
 | 
			
		||||
  // count the number of path separators in the reference path
 | 
			
		||||
  for (i = last_separator; real_ref_path[i] != '\0'; i++)
 | 
			
		||||
@ -1213,15 +1222,16 @@ char * Calculate_relative_path(const char * ref_path, const char * path)
 | 
			
		||||
  free(real_ref_path);
 | 
			
		||||
  i = 0;
 | 
			
		||||
  // construct the relative path
 | 
			
		||||
  len = separator_count * (2 + strlen(PATH_SEPARATOR)) + strlen(path + last_separator + 1) + 1;
 | 
			
		||||
  len = separator_count * (2 + strlen(PATH_SEPARATOR)) + strlen(real_path + last_separator + 1) + 1;
 | 
			
		||||
  rel_path = GFX2_malloc(len + 1);
 | 
			
		||||
  if (rel_path != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    while(separator_count-- > 0)
 | 
			
		||||
      i += snprintf(rel_path + i, len + 1 - i, "..%s", PATH_SEPARATOR);
 | 
			
		||||
    strncpy(rel_path + i, path + last_separator + 1, len + 1 - i);
 | 
			
		||||
    strncpy(rel_path + i, real_path + last_separator + 1, len + 1 - i);
 | 
			
		||||
    rel_path[len] = '\0';
 | 
			
		||||
  }
 | 
			
		||||
  free(real_path);
 | 
			
		||||
  return rel_path;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user