| 121 | The result is malloced. */ |
| 122 | |
| 123 | static char * |
| 124 | convert_abs_rel (char const *from, char const *target) |
| 125 | { |
| 126 | /* Get dirname to generate paths relative to. We don't resolve |
| 127 | the full TARGET as the last component could be an existing symlink. */ |
| 128 | char *targetdir = dir_name (target); |
| 129 | |
| 130 | char *realdest = canonicalize_filename_mode (targetdir, CAN_MISSING); |
| 131 | char *realfrom = canonicalize_filename_mode (from, CAN_MISSING); |
| 132 | |
| 133 | char *relative_from = NULL; |
| 134 | if (realdest && realfrom) |
| 135 | { |
| 136 | /* Write to a PATH_MAX buffer. */ |
| 137 | relative_from = xmalloc (PATH_MAX); |
| 138 | |
| 139 | if (!relpath (realfrom, realdest, relative_from, PATH_MAX)) |
| 140 | { |
| 141 | free (relative_from); |
| 142 | relative_from = NULL; |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | free (targetdir); |
| 147 | free (realdest); |
| 148 | free (realfrom); |
| 149 | |
| 150 | return relative_from ? relative_from : xstrdup (from); |
| 151 | } |
| 152 | |
| 153 | /* Link SOURCE to DESTDIR_FD + DEST_BASE atomically. DESTDIR_FD is |
| 154 | the directory containing DEST_BASE. Return 0 if successful, a |