@@ -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-
14880static int
14981remove_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)
189113static int
190114create_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