Create symlink contents suitable for symlinking TARGET to LINKNAME, as a freshly allocated string. TARGET should be a relative file name, and is relative to the global variable DIRECTORY. LINKNAME can be either relative or absolute. Return a null pointer if the symlink contents was not computed because LINKNAME is absolute but DIRECTORY is not. */
| 1673 | remove_temp(char const *temp) |
| 1674 | { |
| 1675 | if (remove(temp) < 0) |
| 1676 | fprintf(stderr, _("%s: Can't remove temporary file %s%s%s: %s\n"), |
| 1677 | progname, diagdir(temp), diagslash(temp), temp, strerror(errno)); |
| 1678 | } |
| 1679 | |
| 1680 | /* Create symlink contents suitable for symlinking TARGET to LINKNAME, as a |
| 1681 | freshly allocated string. TARGET should be a relative file name, and |
| 1682 | is relative to the global variable DIRECTORY. LINKNAME can be either |
| 1683 | relative or absolute. Return a null pointer if the symlink contents |
| 1684 | was not computed because LINKNAME is absolute but DIRECTORY is not. */ |
| 1685 | static char * |
| 1686 | relname(char const *target, char const *linkname) |
| 1687 | { |
| 1688 | size_t i, taillen, dir_len = 0, dotdots = 0; |
| 1689 | ptrdiff_t dotdotetcsize, linksize = INDEX_MAX; |
| 1690 | char const *f = target; |
| 1691 | char *result = NULL; |
| 1692 | if (*linkname == '/') { |
| 1693 | /* Make F absolute too. */ |
| 1694 | size_t len = strlen(directory); |
| 1695 | bool needs_slash = len && directory[len - 1] != '/'; |
| 1696 | size_t lenslash = len + needs_slash; |
| 1697 | size_t targetsize = strlen(target) + 1; |
| 1698 | char *cp; |
| 1699 | if (*directory != '/') |
| 1700 | return NULL; |
| 1701 | linksize = size_sum(lenslash, targetsize); |
| 1702 | f = cp = result = xmalloc(linksize); |
| 1703 | cp = mempcpy(cp, directory, len); |
| 1704 | *cp = '/'; |
| 1705 | memcpy(cp + needs_slash, target, targetsize); |
| 1706 | } |
| 1707 | for (i = 0; f[i] && f[i] == linkname[i]; i++) |
| 1708 | if (f[i] == '/') |
| 1709 | dir_len = i + 1; |
| 1710 | for (; linkname[i]; i++) |
| 1711 | dotdots += linkname[i] == '/' && linkname[i - 1] != '/'; |
| 1712 | taillen = strlen(f + dir_len); |
| 1713 | dotdotetcsize = size_sum(size_product(dotdots, 3), taillen + 1); |
| 1714 | if (dotdotetcsize <= linksize) { |
| 1715 | char *cp; |
| 1716 | if (!result) |
| 1717 | result = xmalloc(dotdotetcsize); |
no test coverage detected