Skip to content

Commit 312a1d5

Browse files
authored
Merge pull request #444 from jrohel/fix/resources_in_xxopen
Fix: lzopen, zstdopen, zchunkopen
2 parents d52e359 + 7257785 commit 312a1d5

1 file changed

Lines changed: 63 additions & 32 deletions

File tree

ext/solv_xfopen.c

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)