@@ -165,7 +165,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz)
165165 LZFILE * lzfile ;
166166 lzma_ret ret ;
167167
168- if (!path && fd < 0 )
168+ if (( !path && fd < 0 ) || ( path && fd >= 0 ) )
169169 return 0 ;
170170 for (; * mode ; mode ++ )
171171 {
@@ -176,14 +176,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz)
176176 else if (* mode >= '1' && * mode <= '9' )
177177 level = * mode - '0' ;
178178 }
179- if (fd != -1 )
180- fp = fdopen (fd , encoding ? "w" : "r" );
181- else
182- fp = fopen (path , encoding ? "w" : "r" );
183- if (!fp )
184- return 0 ;
185179 lzfile = solv_calloc (1 , sizeof (* lzfile ));
186- lzfile -> file = fp ;
187180 lzfile -> encoding = encoding ;
188181 lzfile -> eof = 0 ;
189182 lzfile -> strm = stream_init ;
@@ -198,10 +191,20 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz)
198191 ret = lzma_auto_decoder (& lzfile -> strm , 100 << 20 , 0 );
199192 if (ret != LZMA_OK )
200193 {
201- fclose (fp );
202- free (lzfile );
194+ solv_free (lzfile );
195+ return 0 ;
196+ }
197+ if (!path )
198+ fp = fdopen (fd , encoding ? "w" : "r" );
199+ else
200+ fp = fopen (path , encoding ? "w" : "r" );
201+ if (!fp )
202+ {
203+ lzma_end (& lzfile -> strm );
204+ solv_free (lzfile );
203205 return 0 ;
204206 }
207+ lzfile -> file = fp ;
205208 return lzfile ;
206209}
207210
@@ -232,7 +235,7 @@ static int lzclose(void *cookie)
232235 }
233236 lzma_end (& lzfile -> strm );
234237 rc = fclose (lzfile -> file );
235- free (lzfile );
238+ solv_free (lzfile );
236239 return rc ;
237240}
238241
@@ -346,7 +349,7 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
346349 FILE * fp ;
347350 ZSTDFILE * zstdfile ;
348351
349- if (!path && fd < 0 )
352+ if (( !path && fd < 0 ) || ( path && fd >= 0 ) )
350353 return 0 ;
351354 for (; * mode ; mode ++ )
352355 {
@@ -357,12 +360,6 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
357360 else if (* mode >= '1' && * mode <= '9' )
358361 level = * mode - '0' ;
359362 }
360- if (fd != -1 )
361- fp = fdopen (fd , encoding ? "w" : "r" );
362- else
363- fp = fopen (path , encoding ? "w" : "r" );
364- if (!fp )
365- return 0 ;
366363 zstdfile = solv_calloc (1 , sizeof (* zstdfile ));
367364 zstdfile -> encoding = encoding ;
368365 if (encoding )
@@ -372,14 +369,12 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
372369 if (!zstdfile -> cstream )
373370 {
374371 solv_free (zstdfile );
375- fclose (fp );
376372 return 0 ;
377373 }
378374 if (ZSTD_isError (ZSTD_initCStream (zstdfile -> cstream , level )))
379375 {
380376 ZSTD_freeCStream (zstdfile -> cstream );
381377 solv_free (zstdfile );
382- fclose (fp );
383378 return 0 ;
384379 }
385380 zstdfile -> out .dst = zstdfile -> buf ;
@@ -393,13 +388,25 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
393388 {
394389 ZSTD_freeDStream (zstdfile -> dstream );
395390 solv_free (zstdfile );
396- fclose (fp );
397391 return 0 ;
398392 }
399393 zstdfile -> in .src = zstdfile -> buf ;
400394 zstdfile -> in .pos = 0 ;
401395 zstdfile -> in .size = 0 ;
402396 }
397+ if (!path )
398+ fp = fdopen (fd , encoding ? "w" : "r" );
399+ else
400+ fp = fopen (path , encoding ? "w" : "r" );
401+ if (!fp )
402+ {
403+ if (encoding )
404+ ZSTD_freeCStream (zstdfile -> cstream );
405+ else
406+ ZSTD_freeDStream (zstdfile -> dstream );
407+ solv_free (zstdfile );
408+ return 0 ;
409+ }
403410 zstdfile -> file = fp ;
404411 return zstdfile ;
405412}
@@ -432,7 +439,7 @@ static int zstdclose(void *cookie)
432439 ZSTD_freeDStream (zstdfile -> dstream );
433440 }
434441 rc = fclose (zstdfile -> file );
435- free (zstdfile );
442+ solv_free (zstdfile );
436443 return rc ;
437444}
438445
@@ -541,9 +548,9 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
541548{
542549 zckCtx * f ;
543550
544- if (!path && fd < 0 )
551+ if (( !path && fd < 0 ) || ( path && fd >= 0 ) )
545552 return 0 ;
546- if (fd == -1 )
553+ if (path )
547554 {
548555 if (* mode != 'w' )
549556 fd = open (path , O_RDONLY );
@@ -555,18 +562,29 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
555562 f = zck_create ();
556563 if (!f )
557564 {
558- close (fd );
565+ if (path )
566+ close (fd );
559567 return 0 ;
560568 }
561569 if (* mode != 'w' )
562570 {
563571 if (!zck_init_read (f , fd ))
564- return 0 ;
572+ {
573+ zck_free (& f );
574+ if (path )
575+ close (fd );
576+ return 0 ;
577+ }
565578 }
566579 else
567580 {
568581 if (!zck_init_write (f , fd ))
569- return 0 ;
582+ {
583+ zck_free (& f );
584+ if (path )
585+ close (fd );
586+ return 0 ;
587+ }
570588 }
571589 return cookieopen (f , mode , cookie_zckread , cookie_zckwrite , cookie_zckclose );
572590}
@@ -580,19 +598,32 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
580598{
581599 FILE * fp ;
582600 void * f ;
583- if (!path && fd < 0 )
601+ int tmpfd ;
602+ if ((!path && fd < 0 ) || (path && fd >= 0 ))
584603 return 0 ;
585- if (fd != -1 )
604+ if (strcmp (mode , "r" ) != 0 )
605+ return 0 ;
606+ if (!path )
586607 fp = fdopen (fd , mode );
587608 else
588609 fp = fopen (path , mode );
589610 if (!fp )
590611 return 0 ;
591- if (strcmp (mode , "r" ) != 0 )
592- return 0 ;
593612 f = solv_zchunk_open (fp , 1 );
594613 if (!f )
595- fclose (fp );
614+ {
615+ /* When 0 is returned, fd passed by user must not be closed! */
616+ /* Dup (save) the original fd to a temporary variable and then back. */
617+ /* It is ugly and thread unsafe hack (non atomical sequence fclose dup2). */
618+ if (!path )
619+ tmpfd = dup (fd );
620+ fclose (fp );
621+ if (!path )
622+ {
623+ dup2 (tmpfd , fd );
624+ close (tmpfd );
625+ }
626+ }
596627 return cookieopen (f , mode , (ssize_t (* )(void * , char * , size_t ))solv_zchunk_read , 0 , (int (* )(void * ))solv_zchunk_close );
597628}
598629
0 commit comments