11/*-
22 * Copyright (c) 2013-2019 Juan Romero Pardines.
3- * Copyright (c) 2023 Duncan Overbruck <[email protected] >. 3+ * Copyright (c) 2023-2025 Duncan Overbruck <[email protected] >. 44 * All rights reserved.
55 *
66 * Redistribution and use in source and binary forms, with or without
@@ -131,48 +131,17 @@ archive_dict(struct archive *ar, const char *filename, xbps_dictionary_t dict)
131131}
132132
133133int
134- repodata_flush (const char * repodir ,
135- const char * arch ,
136- xbps_dictionary_t index ,
137- xbps_dictionary_t stage ,
138- xbps_dictionary_t meta ,
139- const char * compression )
134+ repodata_write_fd (int fd , xbps_dictionary_t index , xbps_dictionary_t stage ,
135+ xbps_dictionary_t meta , const char * compression )
140136{
141- char path [PATH_MAX ];
142- char tmp [PATH_MAX ];
143- struct archive * ar = NULL ;
144- mode_t prevumask ;
137+ struct archive * ar ;
145138 int r ;
146- int fd ;
147-
148- r = snprintf (path , sizeof (path ), "%s/%s-repodata" , repodir , arch );
149- if (r < 0 || (size_t )r >= sizeof (tmp )) {
150- xbps_error_printf ("repodata path too long: %s: %s\n" , path ,
151- strerror (ENAMETOOLONG ));
152- return - ENAMETOOLONG ;
153- }
154-
155- r = snprintf (tmp , sizeof (tmp ), "%s.XXXXXXX" , path );
156- if (r < 0 || (size_t )r >= sizeof (tmp )) {
157- xbps_error_printf ("repodata tmp path too long: %s: %s\n" , path ,
158- strerror (ENAMETOOLONG ));
159- return - ENAMETOOLONG ;
160- }
161-
162- prevumask = umask (S_IXUSR |S_IRWXG |S_IRWXO );
163- fd = mkstemp (tmp );
164- if (fd == -1 ) {
165- r = - errno ;
166- xbps_error_printf ("failed to open temp file: %s: %s" , tmp , strerror (- r ));
167- umask (prevumask );
168- goto err ;
169- }
170- umask (prevumask );
171139
172140 ar = open_archive (fd , compression );
173141 if (!ar ) {
174142 r = - errno ;
175- goto err ;
143+ xbps_error_printf ("failed to open archive: %s\n" , strerror (- r ));
144+ return r ;
176145 }
177146
178147 r = archive_dict (ar , XBPS_REPODATA_INDEX , index );
@@ -185,25 +154,72 @@ repodata_flush(const char *repodir,
185154 if (r < 0 )
186155 goto err ;
187156
188- /* Write data to tempfile and rename */
157+
189158 if (archive_write_close (ar ) == ARCHIVE_FATAL ) {
190159 r = - archive_errno (ar );
191- if ( r == 1 )
192- r = - EINVAL ;
193- xbps_error_printf ( "failed to close archive: %s\n" , archive_error_string ( ar ) );
194- goto err ;
160+ xbps_error_printf (
161+ "failed to close archive: %s\n" , archive_error_string ( ar )) ;
162+ archive_write_free ( ar );
163+ return r ;
195164 }
196165 if (archive_write_free (ar ) == ARCHIVE_FATAL ) {
197166 r = - errno ;
198- xbps_error_printf ("failed to free archive: %s\n" , strerror (- r ));
199- goto err ;
167+ xbps_error_printf (
168+ "failed to free archive: %s\n" , strerror (- r ));
169+ archive_write_free (ar );
170+ return r ;
200171 }
201172
202173#ifdef HAVE_FDATASYNC
203174 fdatasync (fd );
204175#else
205176 fsync (fd );
206177#endif
178+ return 0 ;
179+
180+ err :
181+ archive_write_free (ar );
182+ return r ;
183+ }
184+
185+ int
186+ repodata_write_tmpfile (char * path , size_t pathsz , char * tmp , size_t tmpsz ,
187+ const char * repodir , const char * arch , xbps_dictionary_t index ,
188+ xbps_dictionary_t stage , xbps_dictionary_t meta , const char * compression )
189+ {
190+ mode_t prevumask ;
191+ int fd ;
192+ int r ;
193+
194+ r = snprintf (path , pathsz , "%s/%s-repodata" , repodir , arch );
195+ if (r < 0 || (size_t )r >= pathsz ) {
196+ xbps_error_printf ("repodata path too long: %s: %s\n" , path ,
197+ strerror (ENAMETOOLONG ));
198+ return - ENAMETOOLONG ;
199+ }
200+
201+ r = snprintf (tmp , tmpsz , "%s.XXXXXXX" , path );
202+ if (r < 0 || (size_t )r >= tmpsz ) {
203+ xbps_error_printf ("repodata tmp path too long: %s: %s\n" , path ,
204+ strerror (ENAMETOOLONG ));
205+ return - ENAMETOOLONG ;
206+ }
207+
208+ prevumask = umask (S_IXUSR |S_IRWXG |S_IRWXO );
209+
210+ fd = mkstemp (tmp );
211+ if (fd == -1 ) {
212+ r = - errno ;
213+ xbps_error_printf ("failed to open temp file: %s: %s" , tmp , strerror (- r ));
214+ umask (prevumask );
215+ goto err ;
216+ }
217+
218+ umask (prevumask );
219+
220+ repodata_write_fd (fd , index , stage , meta , compression );
221+ if (r < 0 )
222+ goto err ;
207223
208224 if (fchmod (fd , 0664 ) == -1 ) {
209225 errno = - r ;
@@ -215,22 +231,35 @@ repodata_flush(const char *repodir,
215231 }
216232 close (fd );
217233
234+ return 0 ;
235+ err :
236+ if (fd != -1 )
237+ close (fd );
238+ unlink (tmp );
239+ return r ;
240+ }
241+
242+ int
243+ repodata_write_file (const char * repodir , const char * arch ,
244+ xbps_dictionary_t index , xbps_dictionary_t stage , xbps_dictionary_t meta ,
245+ const char * compression )
246+ {
247+ char path [PATH_MAX ];
248+ char tmp [PATH_MAX ];
249+ int r ;
250+
251+ r = repodata_write_tmpfile (path , sizeof (path ), tmp , sizeof (tmp ), repodir ,
252+ arch , index , stage , meta , compression );
253+ if (r < 0 )
254+ return r ;
255+
218256 if (rename (tmp , path ) == -1 ) {
219257 r = - errno ;
220258 xbps_error_printf ("failed to rename repodata: %s: %s: %s\n" ,
221259 tmp , path , strerror (- r ));
222260 unlink (tmp );
223261 return r ;
224262 }
225- return 0 ;
226263
227- err :
228- if (ar ) {
229- archive_write_close (ar );
230- archive_write_free (ar );
231- }
232- if (fd != -1 )
233- close (fd );
234- unlink (tmp );
235- return r ;
264+ return 0 ;
236265}
0 commit comments