Output the relative representation if possible. If BUF is non-null, write to that buffer rather than to stdout. */
| 85 | /* Output the relative representation if possible. |
| 86 | If BUF is non-null, write to that buffer rather than to stdout. */ |
| 87 | bool |
| 88 | relpath (char const *can_fname, char const *can_reldir, char *buf, size_t len) |
| 89 | { |
| 90 | bool buf_err = false; |
| 91 | |
| 92 | /* Skip the prefix common to --relative-to and path. */ |
| 93 | int common_index = path_common_prefix (can_reldir, can_fname); |
| 94 | if (!common_index) |
| 95 | return false; |
| 96 | |
| 97 | char const *relto_suffix = can_reldir + common_index; |
| 98 | char const *fname_suffix = can_fname + common_index; |
| 99 | |
| 100 | /* Skip over extraneous '/'. */ |
| 101 | if (*relto_suffix == '/') |
| 102 | relto_suffix++; |
| 103 | if (*fname_suffix == '/') |
| 104 | fname_suffix++; |
| 105 | |
| 106 | /* Replace remaining components of --relative-to with '..', to get |
| 107 | to a common directory. Then output the remainder of fname. */ |
| 108 | if (*relto_suffix) |
| 109 | { |
| 110 | buf_err |= buffer_or_output ("..", &buf, &len); |
| 111 | for (; *relto_suffix; ++relto_suffix) |
| 112 | { |
| 113 | if (*relto_suffix == '/') |
| 114 | buf_err |= buffer_or_output ("/..", &buf, &len); |
| 115 | } |
| 116 | |
| 117 | if (*fname_suffix) |
| 118 | { |
| 119 | buf_err |= buffer_or_output ("/", &buf, &len); |
| 120 | buf_err |= buffer_or_output (fname_suffix, &buf, &len); |
| 121 | } |
| 122 | } |
| 123 | else |
| 124 | { |
| 125 | buf_err |= buffer_or_output (*fname_suffix ? fname_suffix : ".", |
| 126 | &buf, &len); |
| 127 | } |
| 128 | |
| 129 | if (buf_err) |
| 130 | error (0, ENAMETOOLONG, "%s", _("generating relative path")); |
| 131 | |
| 132 | return !buf_err; |
| 133 | } |
no test coverage detected