- add mode argument to sat_xfopen* functions
[platform/upstream/libsolv.git] / ext / sat_xfopen.c
1 /*
2  * Copyright (c) 2011, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #define _GNU_SOURCE
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <zlib.h>
13 #include <fcntl.h>
14
15 #include "sat_xfopen.h"
16
17 static ssize_t cookie_gzread(void *cookie, char *buf, size_t nbytes)
18 {
19   return gzread((gzFile *)cookie, buf, nbytes);
20 }
21
22 static int
23 cookie_gzclose(void *cookie)
24 {
25   return gzclose((gzFile *)cookie);
26 }
27
28 static FILE *mygzfopen(gzFile* gzf)
29 {
30 #ifdef HAVE_FUNOPEN
31   return funopen(
32       gzf, (int (*)(void *, char *, int))cookie_gzread,
33       (int (*)(void *, const char *, int))NULL, /* writefn */
34       (fpos_t (*)(void *, fpos_t, int))NULL, /* seekfn */
35       cookie_gzclose
36       );
37 #elif defined(HAVE_FOPENCOOKIE)
38   cookie_io_functions_t cio;
39   memset(&cio, 0, sizeof(cio));
40   cio.read = cookie_gzread;
41   cio.close = cookie_gzclose;
42   return  fopencookie(gzf, "r", cio);
43 #else
44 # error Need to implement custom I/O
45 #endif
46 }
47
48 FILE *
49 sat_xfopen(const char *fn, const char *mode)
50 {
51   char *suf;
52   gzFile *gzf;
53
54   if (!fn)
55     return 0;
56   if (!mode)
57     mode = "r";
58   suf = strrchr(fn, '.');
59   if (!suf || strcmp(suf, ".gz") != 0)
60     return fopen(fn, mode);
61   gzf = gzopen(fn, mode);
62   if (!gzf)
63     return 0;
64   return mygzfopen(gzf);
65 }
66
67 FILE *
68 sat_xfopen_fd(const char *fn, int fd, const char *mode)
69 {
70   char *suf;
71   gzFile *gzf;
72
73   suf = fn ? strrchr(fn, '.') : 0;
74   if (!mode)
75     {
76       int fl = fcntl(fd, F_GETFL, 0);
77       if (fl == -1)
78         return 0;
79       fl &= O_RDONLY|O_WRONLY|O_RDWR;
80       if (fl == O_WRONLY)
81         mode = "w";
82       else if (fl == O_RDWR)
83         mode = "r+";
84       else
85         mode = "r";
86     }
87   if (!suf || strcmp(suf, ".gz") != 0)
88     return fdopen(fd, mode);
89   gzf = gzdopen(fd, mode);
90   if (!gzf)
91     return 0;
92   return mygzfopen(gzf);
93 }
94