Symlinks make this hard! */
| 220 | |
| 221 | /* Symlinks make this hard! */ |
| 222 | char *path_rel(const tal_t *ctx, const char *from, const char *to) |
| 223 | { |
| 224 | char *cfrom, *cto, *ret, *p; |
| 225 | tal_t *tmpctx; |
| 226 | size_t common, num_back, i, postlen; |
| 227 | |
| 228 | /* This frees from if we're supposed to take it. */ |
| 229 | tmpctx = cfrom = path_canon(ctx, from); |
| 230 | if (!cfrom) |
| 231 | goto fail_take_to; |
| 232 | |
| 233 | /* From is a directory, so we append / to it. */ |
| 234 | if (!streq(cfrom, PATH_SEP_STR)) { |
| 235 | if (!tal_resize(&cfrom, strlen(cfrom)+2)) |
| 236 | goto fail_take_to; |
| 237 | tmpctx = cfrom; |
| 238 | strcat(cfrom, PATH_SEP_STR); |
| 239 | } |
| 240 | |
| 241 | /* This frees to if we're supposed to take it. */ |
| 242 | cto = path_canon(tmpctx, to); |
| 243 | if (!cto) { |
| 244 | ret = NULL; |
| 245 | goto out; |
| 246 | } |
| 247 | |
| 248 | /* How much is in common? */ |
| 249 | for (common = i = 0; cfrom[i] && cto[i]; i++) { |
| 250 | if (cfrom[i] != cto[i]) |
| 251 | break; |
| 252 | if (cfrom[i] == PATH_SEP) |
| 253 | common = i + 1; |
| 254 | } |
| 255 | |
| 256 | /* Skip over / if matches end of other path. */ |
| 257 | if (!cfrom[i] && cto[i] == PATH_SEP) { |
| 258 | cto++; |
| 259 | common = i; |
| 260 | } else if (!cto[i] && cfrom[i] == PATH_SEP) { |
| 261 | cfrom++; |
| 262 | common = i; |
| 263 | } |
| 264 | |
| 265 | /* Normalize so strings point past common area. */ |
| 266 | cfrom += common; |
| 267 | cto += common; |
| 268 | |
| 269 | /* One .. for every path element remaining in 'from', to get |
| 270 | * back to common prefix. Then the rest of 'to'. */ |
| 271 | num_back = strcount(cfrom, PATH_SEP_STR); |
| 272 | postlen = strlen(cto) + 1; |
| 273 | |
| 274 | /* Nothing left? That's ".". */ |
| 275 | if (num_back == 0 && postlen == 1) { |
| 276 | ret = tal_strdup(ctx, "."); |
| 277 | goto out; |
| 278 | } |
| 279 |