11/*-
22 * Copyright (c) 2014-2020 Juan Romero Pardines.
3+ * Copyright (c) 2025-2026 Duncan Overbruck <mail@duncano.de>.
34 * All rights reserved.
45 *
56 * Redistribution and use in source and binary forms, with or without
@@ -56,6 +57,10 @@ struct shlib_entry {
5657struct shlib_ctx {
5758 struct xbps_handle * xhp ;
5859 struct shlib_entry * entries ;
60+ // XXX: _32bit is a big hack because there is nothing allowing us
61+ // to separate 32bit shlibs from normal shlibs, so we collect them
62+ // in a separate hashmap based on the package name ending with `-32bit`.
63+ struct shlib_entry * entries_32bit ;
5964 xbps_dictionary_t seen ;
6065 xbps_array_t missing ;
6166};
@@ -69,9 +74,9 @@ shlib_entry_find(struct shlib_entry *head, const char *name)
6974}
7075
7176static struct shlib_entry *
72- shlib_entry_get (struct shlib_ctx * ctx , const char * name )
77+ shlib_entry_get (struct shlib_entry * * head , const char * name )
7378{
74- struct shlib_entry * res = shlib_entry_find (ctx -> entries , name );
79+ struct shlib_entry * res = shlib_entry_find (* head , name );
7580 if (res )
7681 return res ;
7782 res = calloc (1 , sizeof (* res ));
@@ -80,25 +85,34 @@ shlib_entry_get(struct shlib_ctx *ctx, const char *name)
8085 return NULL ;
8186 }
8287 res -> name = name ;
83- HASH_ADD_STR (ctx -> entries , name , res );
88+ HASH_ADD_STR (* head , name , res );
8489 return res ;
8590}
8691
8792static int
88- collect_shlib_array (struct shlib_ctx * ctx , xbps_array_t array )
93+ collect_shlib_array (struct shlib_entry * * head , xbps_array_t array )
8994{
9095 for (unsigned int i = 0 ; i < xbps_array_count (array ); i ++ ) {
9196 struct shlib_entry * entry ;
9297 const char * shlib = NULL ;
9398 if (!xbps_array_get_cstring_nocopy (array , i , & shlib ))
9499 return - EINVAL ;
95- entry = shlib_entry_get (ctx , shlib );
100+ entry = shlib_entry_get (head , shlib );
96101 if (!entry )
97102 return - errno ;
98103 }
99104 return 0 ;
100105}
101106
107+ static bool
108+ endswith (const char * s , const char * end , size_t len )
109+ {
110+ size_t slen = strlen (s );
111+ if (slen <= len )
112+ return false;
113+ return strcmp (s + (slen - len ), end ) == 0 ;
114+ }
115+
102116static int
103117collect_shlibs (struct shlib_ctx * ctx , xbps_array_t pkgs )
104118{
@@ -134,7 +148,11 @@ collect_shlibs(struct shlib_ctx *ctx, xbps_array_t pkgs)
134148
135149 array = xbps_dictionary_get (pkgd , "shlib-provides" );
136150 if (array ) {
137- int r = collect_shlib_array (ctx , array );
151+ bool is32bit =
152+ endswith (pkgname , "-32bit" , sizeof ("-32bit" ) - 1 );
153+ int r = collect_shlib_array (
154+ !is32bit ? & ctx -> entries : & ctx -> entries_32bit ,
155+ array );
138156 if (r < 0 )
139157 return r ;
140158 }
@@ -161,7 +179,11 @@ collect_shlibs(struct shlib_ctx *ctx, xbps_array_t pkgs)
161179
162180 array = xbps_dictionary_get (pkgd , "shlib-provides" );
163181 if (array ) {
164- int r = collect_shlib_array (ctx , array );
182+ bool is32bit =
183+ endswith (pkgname , "-32bit" , sizeof ("-32bit" ) - 1 );
184+ int r = collect_shlib_array (
185+ !is32bit ? & ctx -> entries : & ctx -> entries_32bit ,
186+ array );
165187 if (r < 0 )
166188 return r ;
167189 }
@@ -174,34 +196,41 @@ collect_shlibs(struct shlib_ctx *ctx, xbps_array_t pkgs)
174196static int
175197check_shlibs (struct shlib_ctx * ctx , xbps_array_t pkgs )
176198{
199+ char msg [1024 ];
177200 xbps_object_iterator_t iter ;
178201 xbps_object_t obj ;
179202
180203 for (unsigned int i = 0 ; i < xbps_array_count (pkgs ); i ++ ) {
181204 xbps_array_t array ;
182205 xbps_dictionary_t pkgd = xbps_array_get (pkgs , i );
183206 xbps_trans_type_t ttype = xbps_transaction_pkg_type (pkgd );
207+ const char * pkgname = NULL ;
208+ bool is32bit ;
184209
185210 if (ttype == XBPS_TRANS_HOLD || ttype == XBPS_TRANS_REMOVE )
186211 continue ;
187212
213+ if (!xbps_dictionary_get_cstring_nocopy (pkgd , "pkgname" , & pkgname ))
214+ return - EINVAL ;
215+
216+ is32bit = endswith (pkgname , "-32bit" , sizeof ("-32bit" ) - 1 );
217+
188218 array = xbps_dictionary_get (pkgd , "shlib-requires" );
189219 if (!array )
190220 continue ;
191221 for (unsigned int j = 0 ; j < xbps_array_count (array ); j ++ ) {
192222 const char * pkgver = NULL ;
193223 const char * shlib = NULL ;
194- char * missing ;
195224 if (!xbps_array_get_cstring_nocopy (array , j , & shlib ))
196225 return - EINVAL ;
197- if (shlib_entry_find (ctx -> entries , shlib ))
226+ if (shlib_entry_find (! is32bit ? ctx -> entries : ctx -> entries_32bit , shlib ))
198227 continue ;
199228 if (!xbps_dictionary_get_cstring_nocopy (pkgd , "pkgver" , & pkgver ))
200229 return - EINVAL ;
201- missing = xbps_xasprintf (
202- "%s: broken, unresolvable shlib `%s'" ,
203- pkgver , shlib );
204- if (!xbps_array_add_cstring_nocopy (ctx -> missing , missing ))
230+ snprintf ( msg , sizeof ( msg ),
231+ "%s: broken, unresolvable shlib `%s'" , pkgver ,
232+ shlib );
233+ if (!xbps_array_add_cstring_nocopy (ctx -> missing , msg ))
205234 return xbps_error_oom ();
206235 }
207236 }
@@ -214,6 +243,7 @@ check_shlibs(struct shlib_ctx *ctx, xbps_array_t pkgs)
214243 xbps_array_t array ;
215244 xbps_dictionary_t pkgd ;
216245 const char * pkgname = NULL ;
246+ bool is32bit ;
217247
218248 pkgname = xbps_dictionary_keysym_cstring_nocopy (obj );
219249 /* ignore internal objs */
@@ -225,23 +255,24 @@ check_shlibs(struct shlib_ctx *ctx, xbps_array_t pkgs)
225255 if (xbps_dictionary_get (ctx -> seen , pkgname ))
226256 continue ;
227257
258+ is32bit = endswith (pkgname , "-32bit" , sizeof ("-32bit" ) - 1 );
259+
228260 array = xbps_dictionary_get (pkgd , "shlib-requires" );
229261 if (!array )
230262 continue ;
231263 for (unsigned int i = 0 ; i < xbps_array_count (array ); i ++ ) {
232264 const char * pkgver = NULL ;
233265 const char * shlib = NULL ;
234- char * missing ;
235266 if (!xbps_array_get_cstring_nocopy (array , i , & shlib ))
236267 return - EINVAL ;
237- if (shlib_entry_find (ctx -> entries , shlib ))
268+ if (shlib_entry_find (! is32bit ? ctx -> entries : ctx -> entries_32bit , shlib ))
238269 continue ;
239270 if (!xbps_dictionary_get_cstring_nocopy (pkgd , "pkgver" , & pkgver ))
240271 return - EINVAL ;
241- missing = xbps_xasprintf (
272+ snprintf ( msg , sizeof ( msg ),
242273 "%s: broken, unresolvable shlib `%s'" , pkgver ,
243274 shlib );
244- if (!xbps_array_add_cstring_nocopy (ctx -> missing , missing ))
275+ if (!xbps_array_add_cstring_nocopy (ctx -> missing , msg ))
245276 return xbps_error_oom ();
246277 }
247278 }
@@ -276,6 +307,10 @@ xbps_transaction_check_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs)
276307 HASH_DEL (ctx .entries , entry );
277308 free (entry );
278309 }
310+ HASH_ITER (hh , ctx .entries_32bit , entry , tmp ) {
311+ HASH_DEL (ctx .entries_32bit , entry );
312+ free (entry );
313+ }
279314 if (ctx .seen )
280315 xbps_object_release (ctx .seen );
281316 return r == 0 ;
0 commit comments