Skip to content

Commit b1fa004

Browse files
committed
lib/package_alternatives.c: use xbps_alternative_link
1 parent 5e2b6b6 commit b1fa004

File tree

1 file changed

+73
-153
lines changed

1 file changed

+73
-153
lines changed

lib/package_alternatives.c

Lines changed: 73 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -77,110 +77,34 @@ xbps_alternative_link(const char *alternative,
7777
return 0;
7878
}
7979

80-
static char *
81-
left(const char *str)
82-
{
83-
char *p;
84-
size_t len;
85-
86-
p = strdup(str);
87-
len = strlen(p) - strlen(strchr(p, ':'));
88-
p[len] = '\0';
89-
90-
return p;
91-
}
92-
93-
static const char *
94-
right(const char *str)
95-
{
96-
return strchr(str, ':') + 1;
97-
}
98-
99-
static const char *
100-
normpath(char *path)
101-
{
102-
char *seg, *p;
103-
104-
for (p = path, seg = NULL; *p; p++) {
105-
if (strncmp(p, "/../", 4) == 0 || strncmp(p, "/..", 4) == 0) {
106-
memmove(seg ? seg : p, p+3, strlen(p+3) + 1);
107-
return normpath(path);
108-
} else if (strncmp(p, "/./", 3) == 0 || strncmp(p, "/.", 3) == 0) {
109-
memmove(p, p+2, strlen(p+2) + 1);
110-
} else if (strncmp(p, "//", 2) == 0 || strncmp(p, "/", 2) == 0) {
111-
memmove(p, p+1, strlen(p+1) + 1);
112-
}
113-
if (*p == '/')
114-
seg = p;
115-
}
116-
return path;
117-
}
118-
119-
static char *
120-
relpath(char *from, char *to)
121-
{
122-
int up;
123-
char *p = to, *rel;
124-
125-
assert(from[0] == '/');
126-
assert(to[0] == '/');
127-
normpath(from);
128-
normpath(to);
129-
130-
for (; *from == *to && *to; from++, to++) {
131-
if (*to == '/')
132-
p = to;
133-
}
134-
135-
for (up = -1, from--; from && *from; from = strchr(from + 1, '/'), up++);
136-
137-
rel = calloc(3 * up + strlen(p), 1);
138-
if (!rel)
139-
return NULL;
140-
141-
while (up--)
142-
strcat(rel, "../");
143-
if (*p)
144-
strcat(rel, p+1);
145-
return rel;
146-
}
147-
14880
static int
14981
remove_symlinks(struct xbps_handle *xhp, xbps_array_t a, const char *grname)
15082
{
151-
unsigned int i, cnt;
83+
char path[PATH_MAX];
15284
struct stat st;
15385

154-
cnt = xbps_array_count(a);
155-
for (i = 0; i < cnt; i++) {
156-
xbps_string_t str;
157-
char *l, *lnk;
158-
159-
str = xbps_array_get(a, i);
160-
l = left(xbps_string_cstring_nocopy(str));
161-
assert(l);
162-
if (l[0] != '/') {
163-
const char *tgt;
164-
char *tgt_dup, *tgt_dir;
165-
tgt = right(xbps_string_cstring_nocopy(str));
166-
tgt_dup = strdup(tgt);
167-
assert(tgt_dup);
168-
tgt_dir = dirname(tgt_dup);
169-
lnk = xbps_xasprintf("%s%s/%s", xhp->rootdir, tgt_dir, l);
170-
free(tgt_dup);
171-
} else {
172-
lnk = xbps_xasprintf("%s%s", xhp->rootdir, l);
86+
for (unsigned int i = 0; i < xbps_array_count(a); i++) {
87+
const char *alternative;
88+
int r;
89+
90+
xbps_array_get_cstring_nocopy(a, i, &alternative);
91+
92+
r = xbps_alternative_link(alternative, path, sizeof(path), NULL, 0);
93+
if (r < 0) {
94+
/* XXX: print error, but don't abort transaction */
95+
continue;
17396
}
174-
if (lstat(lnk, &st) == -1 || !S_ISLNK(st.st_mode)) {
175-
free(lnk);
176-
free(l);
97+
if (xbps_path_prepend(path, sizeof(path), xhp->rootdir) == -1) {
98+
/* XXX: print error, but don't abort transaction */
17799
continue;
178100
}
101+
102+
if (lstat(path, &st) == -1 || !S_ISLNK(st.st_mode))
103+
continue;
104+
179105
xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_LINK_REMOVED, 0, NULL,
180-
"Removing '%s' alternatives group symlink: %s", grname, l);
181-
unlink(lnk);
182-
free(lnk);
183-
free(l);
106+
"Removing '%s' alternatives group symlink: %s", grname, path);
107+
unlink(path);
184108
}
185109

186110
return 0;
@@ -189,84 +113,80 @@ remove_symlinks(struct xbps_handle *xhp, xbps_array_t a, const char *grname)
189113
static int
190114
create_symlinks(struct xbps_handle *xhp, xbps_array_t a, const char *grname)
191115
{
192-
int rv;
193-
unsigned int i, n;
194-
char *alternative, *tok1, *tok2, *linkpath, *target, *dir, *p;
195-
196-
n = xbps_array_count(a);
116+
char path[PATH_MAX];
117+
char target[PATH_MAX];
118+
char dir[PATH_MAX];
119+
int rv = 0;
197120

198-
for (i = 0; i < n; i++) {
199-
alternative = xbps_string_cstring(xbps_array_get(a, i));
121+
for (unsigned int i = 0; i < xbps_array_count(a); i++) {
122+
const char *alt;
123+
char *p;
124+
int r;
125+
xbps_array_get_cstring_nocopy(a, i, &alt);
200126

201-
if (!(tok1 = strtok(alternative, ":")) ||
202-
!(tok2 = strtok(NULL, ":"))) {
203-
free(alternative);
204-
return -1;
127+
r = xbps_alternative_link(alt, path, sizeof(path), target, sizeof(target));
128+
if (r < 0) {
129+
/* XXX: print error, but don't abort transaction */
130+
continue;
131+
}
132+
if (xbps_path_prepend(path, sizeof(path), xhp->rootdir) == -1) {
133+
/* XXX: print error, but don't abort transaction */
134+
continue;
205135
}
206136

207-
target = strdup(tok2);
208-
dir = dirname(tok2);
209-
210-
/* add target dir to relative links */
211-
if (tok1[0] != '/')
212-
linkpath = xbps_xasprintf("%s/%s/%s", xhp->rootdir, dir, tok1);
213-
else
214-
linkpath = xbps_xasprintf("%s/%s", xhp->rootdir, tok1);
215-
137+
p = strrchr(path, '/');
138+
if (!p) {
139+
/* XXX: print error, but don't abort transaction */
140+
continue;
141+
}
142+
strncpy(dir, path, p-path);
143+
dir[p-path] = '\0';
216144
/* create target directory, necessary for dangling symlinks */
217-
dir = xbps_xasprintf("%s/%s", xhp->rootdir, dir);
218145
if (strcmp(dir, ".") && xbps_mkpath(dir, 0755) && errno != EEXIST) {
219146
rv = errno;
220147
xbps_dbg_printf(xhp,
221148
"failed to create target dir '%s' for group '%s': %s\n",
222149
dir, grname, strerror(errno));
223-
free(dir);
224-
goto err;
150+
continue;
225151
}
226-
free(dir);
227-
152+
if (xbps_path_append(dir, sizeof(dir), target) == -1) {
153+
rv = errno;
154+
xbps_dbg_printf(xhp,
155+
"failed to create target symlink\n");
156+
continue;
157+
}
158+
p= strrchr(dir, '/');
159+
if (!p) {
160+
rv = EINVAL;
161+
continue;
162+
}
163+
*p = '\0';
228164
/* create link directory, necessary for dangling symlinks */
229-
p = strdup(linkpath);
230-
dir = dirname(p);
231165
if (strcmp(dir, ".") && xbps_mkpath(dir, 0755) && errno != EEXIST) {
232166
rv = errno;
233167
xbps_dbg_printf(xhp,
234168
"failed to create symlink dir '%s' for group '%s': %s\n",
235169
dir, grname, strerror(errno));
236-
free(p);
237-
goto err;
170+
continue;
238171
}
239-
free(p);
240172

173+
/* skip the rootdir in the status callback */
174+
p = path;
175+
if (strcmp(xhp->rootdir, "/") != 0)
176+
p += strlen(xhp->rootdir);
241177
xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_LINK_ADDED, 0, NULL,
242178
"Creating '%s' alternatives group symlink: %s -> %s",
243-
grname, tok1, target);
179+
grname, p, target);
244180

245-
if (target[0] == '/') {
246-
p = relpath(linkpath + strlen(xhp->rootdir), target);
247-
free(target);
248-
target = p;
249-
}
250-
251-
unlink(linkpath);
252-
if ((rv = symlink(target, linkpath)) != 0) {
253-
xbps_dbg_printf(xhp,
254-
"failed to create alt symlink '%s' for group '%s': %s\n",
255-
linkpath, grname, strerror(errno));
256-
goto err;
181+
(void) unlink(path);
182+
if (symlink(target, path) != 0) {
183+
rv = errno;
184+
xbps_error_printf(
185+
"Failed to create alternative symlink '%s' for group '%s': %s\n",
186+
path, grname, strerror(errno));
257187
}
258-
259-
free(alternative);
260-
free(target);
261-
free(linkpath);
262188
}
263189

264-
return 0;
265-
266-
err:
267-
free(alternative);
268-
free(target);
269-
free(linkpath);
270190
return rv;
271191
}
272192

@@ -551,7 +471,9 @@ remove_obsoletes(struct xbps_handle *xhp, const char *pkgname, const char *pkgve
551471
if (array2) {
552472
xbps_array_get_cstring_nocopy(array2, 0, &first);
553473
if (strcmp(pkgname, first) == 0) {
474+
#if 0
554475
remove_symlinks(xhp, array_repo, keyname);
476+
#endif
555477
}
556478
}
557479
}
@@ -577,9 +499,7 @@ xbps_alternatives_register(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod)
577499
int rv = 0;
578500

579501
assert(xhp);
580-
581-
if (xhp->pkgdb == NULL)
582-
return EINVAL;
502+
assert(xhp->pkgdb);
583503

584504
alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_");
585505
if (alternatives == NULL) {
@@ -624,8 +544,8 @@ xbps_alternatives_register(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod)
624544
}
625545
/* already registered, update symlinks */
626546
rv = create_symlinks(xhp,
627-
xbps_dictionary_get(pkg_alternatives, keyname),
628-
keyname);
547+
xbps_dictionary_get(pkg_alternatives, keyname),
548+
keyname);
629549
if (rv != 0)
630550
break;
631551
} else {

0 commit comments

Comments
 (0)