LCOV - code coverage report
Current view: top level - src - fzp.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 157 216 72.7 %
Date: 2022-12-03 01:09:05 Functions: 26 27 96.3 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "alloc.h"
       3             : #include "cmd.h"
       4             : #include "fsops.h"
       5             : #include "fzp.h"
       6             : #include "log.h"
       7             : #include "prepend.h"
       8             : #ifndef HAVE_WIN32
       9             : #include "server/compress.h"
      10             : #include "server/zlibio.h"
      11             : #endif
      12             : 
      13             : static struct fzp *fzp_alloc(void)
      14             : {
      15        1931 :         return (struct fzp *)calloc_w(1, sizeof(struct fzp), __func__);
      16             : }
      17             : 
      18        1931 : static void fzp_free(struct fzp **fzp)
      19             : {
      20        1931 :         if(!fzp || !*fzp) return;
      21        1931 :         free_w(&(*fzp)->buf);
      22        1931 :         free_v((void **)fzp);
      23             : }
      24             : 
      25        1597 : static FILE *open_fp(const char *fname, const char *mode)
      26             : {
      27        1597 :         FILE *fp=NULL;
      28        1597 :         if(!(fp=fopen(fname, mode)))
      29          47 :                 logp("could not open %s: %s\n", fname, strerror(errno));
      30        1597 :         return fp;
      31             : }
      32             : 
      33         332 : static gzFile open_zp(const char *fname, const char *mode)
      34             : {
      35         332 :         gzFile zp=NULL;
      36             : 
      37         332 :         if(!(zp=gzopen(fname, mode)))
      38           1 :                 logp("could not open %s: %s\n", fname, strerror(errno));
      39         332 :         return zp;
      40             : }
      41             : 
      42        1599 : static int close_fp(FILE **fp)
      43             : {
      44        1599 :         int ret=0;
      45        1599 :         if(!*fp) return ret;
      46        1552 :         if(fclose(*fp))
      47             :         {
      48           0 :                 logp("fclose failed: %s\n", strerror(errno));
      49           0 :                 ret=-1;
      50             :         }
      51        1552 :         *fp=NULL;
      52        1552 :         return ret;
      53             : }
      54             : 
      55         332 : static int close_zp(gzFile *zp)
      56             : {
      57             :         int e;
      58         332 :         int ret=0;
      59         332 :         if(!*zp) return ret;
      60         331 :         if((e=gzclose(*zp))
      61             :         // Can return Z_BUF_ERROR if the last read ended in the middle
      62             :         // of a gzip stream. I saw this happening in utests on OpenBSD.
      63           0 :           && e!=Z_BUF_ERROR)
      64             :         {
      65           0 :                 const char *str=NULL;
      66           0 :                 if(e==Z_ERRNO)
      67           0 :                         str=strerror(errno);
      68           0 :                 logp("gzclose failed: %d (%s)\n", e, str?:"");
      69           0 :                 ret=-1;
      70             :         }
      71             :         return ret;
      72             : }
      73             : 
      74             : static void unknown_type(enum fzp_type type, const char *func)
      75             : {
      76           0 :         logp("unknown type in %s: %d\n", func, type);
      77             : }
      78             : 
      79             : static void not_open(const char *func)
      80             : {
      81          11 :         logp("File pointer not open in %s\n", func);
      82             : }
      83             : 
      84        1929 : static struct fzp *fzp_do_open(const char *path, const char *mode,
      85             :         enum fzp_type type)
      86             : {
      87        1929 :         struct fzp *fzp=NULL;
      88             : 
      89        1929 :         if(!(fzp=fzp_alloc())) goto error;
      90        1929 :         fzp->type=type;
      91        1929 :         switch(type)
      92             :         {
      93             :                 case FZP_FILE:
      94        1597 :                         if(!(fzp->fp=open_fp(path, mode)))
      95             :                                 goto error;
      96        1550 :                         return fzp;
      97             :                 case FZP_COMPRESSED:
      98         332 :                         if(!(fzp->zp=open_zp(path, mode)))
      99             :                                 goto error;
     100         331 :                         return fzp;
     101             :                 default:
     102           0 :                         unknown_type(fzp->type, __func__);
     103             :                         goto error;
     104             :         }
     105             : error:
     106          48 :         fzp_close(&fzp);
     107          48 :         return NULL;
     108             : }
     109             : 
     110        1597 : struct fzp *fzp_open(const char *path, const char *mode)
     111             : {
     112        1597 :         return fzp_do_open(path, mode, FZP_FILE);
     113             : }
     114             : 
     115         332 : struct fzp *fzp_gzopen(const char *path, const char *mode)
     116             : {
     117         332 :         return fzp_do_open(path, mode, FZP_COMPRESSED);
     118             : }
     119             : 
     120      121398 : int fzp_close(struct fzp **fzp)
     121             : {
     122      121398 :         int ret=-1;
     123      121398 :         if(!fzp || !*fzp) return 0;
     124        1931 :         switch((*fzp)->type)
     125             :         {
     126             :                 case FZP_FILE:
     127        1599 :                         ret=close_fp(&((*fzp)->fp));
     128        1599 :                         break;
     129             :                 case FZP_COMPRESSED:
     130         332 :                         ret=close_zp(&((*fzp)->zp));
     131         332 :                         break;
     132             :                 default:
     133           0 :                         unknown_type((*fzp)->type, __func__);
     134             :                         break;
     135             :         }
     136        1931 :         fzp_free(fzp);
     137        1931 :         return ret;
     138             : }
     139             : 
     140       94600 : int fzp_read(struct fzp *fzp, void *ptr, size_t nmemb)
     141             : {
     142       94600 :         if(fzp) switch(fzp->type)
     143             :         {
     144             :                 case FZP_FILE:
     145       63696 :                         return (int)fread(ptr, 1, nmemb, fzp->fp);
     146             :                 case FZP_COMPRESSED:
     147       30903 :                         return gzread(fzp->zp, ptr, (unsigned)nmemb);
     148             :                 default:
     149           0 :                         unknown_type(fzp->type, __func__);
     150             :                         goto error;
     151             :         }
     152             :         not_open(__func__);
     153             : error:
     154             :         return 0;
     155             : }
     156             : 
     157       38155 : size_t fzp_write(struct fzp *fzp, const void *ptr, size_t nmemb)
     158             : {
     159       38155 :         if(fzp) switch(fzp->type)
     160             :         {
     161             :                 case FZP_FILE:
     162       23990 :                         return fwrite(ptr, 1, nmemb, fzp->fp);
     163             :                 case FZP_COMPRESSED:
     164       14164 :                         return gzwrite(fzp->zp, ptr, (unsigned)nmemb);
     165             :                 default:
     166           0 :                         unknown_type(fzp->type, __func__);
     167             :                         goto error;
     168             :         }
     169             :         not_open(__func__);
     170             : error:
     171             :         return 0;
     172             : }
     173             : 
     174         171 : int fzp_eof(struct fzp *fzp)
     175             : {
     176         171 :         if(fzp) switch(fzp->type)
     177             :         {
     178             :                 case FZP_FILE:
     179         137 :                         return feof(fzp->fp);
     180             :                 case FZP_COMPRESSED:
     181          33 :                         return gzeof(fzp->zp);
     182             :                 default:
     183           0 :                         unknown_type(fzp->type, __func__);
     184             :                         goto error;
     185             :         }
     186             :         not_open(__func__);
     187             : error:
     188             :         // Non-zero means end of file. Should be OK to use -1 here.
     189             :         return -1;
     190             : }
     191             : 
     192          13 : int fzp_flush(struct fzp *fzp)
     193             : {
     194          13 :         if(fzp) switch(fzp->type)
     195             :         {
     196             :                 case FZP_FILE:
     197           6 :                         return fflush(fzp->fp);
     198             :                 case FZP_COMPRESSED:
     199           6 :                         return gzflush(fzp->zp, Z_FINISH);
     200             :                 default:
     201           0 :                         unknown_type(fzp->type, __func__);
     202             :                         goto error;
     203             :         }
     204             :         not_open(__func__);
     205             : error:
     206             :         return EOF;
     207             : }
     208             : 
     209         144 : int fzp_seek(struct fzp *fzp, off_t offset, int whence)
     210             : {
     211         144 :         if(fzp) switch(fzp->type)
     212             :         {
     213             :                 case FZP_FILE:
     214          15 :                         return fseeko(fzp->fp, offset, whence);
     215             :                 case FZP_COMPRESSED:
     216             :                         // Notice that gzseek returns the new offset.
     217         128 :                         if(gzseek(fzp->zp, offset, whence)==offset)
     218             :                                 return 0;
     219             :                         goto error;
     220             :                 default:
     221           0 :                         unknown_type(fzp->type, __func__);
     222             :                         goto error;
     223             :         }
     224             :         not_open(__func__);
     225             : error:
     226             :         return -1;
     227             : }
     228             : 
     229        7360 : off_t fzp_tell(struct fzp *fzp)
     230             : {
     231        7360 :         if(fzp) switch(fzp->type)
     232             :         {
     233             :                 case FZP_FILE:
     234        6432 :                         return ftello(fzp->fp);
     235             :                 case FZP_COMPRESSED:
     236         927 :                         return gztell(fzp->zp);
     237             :                 default:
     238           0 :                         unknown_type(fzp->type, __func__);
     239             :                         goto error;
     240             :         }
     241             :         not_open(__func__);
     242             : error:
     243             :         return -1;
     244             : }
     245             : 
     246             : #ifndef HAVE_WIN32
     247             : // There is no zlib gztruncate. Inflate it, truncate it, recompress it.
     248           4 : static int gztruncate(const char *path, off_t length, int compression)
     249             : {
     250           4 :         int ret=1;
     251             :         char tmp[16];
     252           4 :         char *dest=NULL;
     253           4 :         char *dest2=NULL;
     254           4 :         snprintf(tmp, sizeof(tmp), ".%d", getpid());
     255           4 :         if(!(dest=prepend(path, tmp))
     256           4 :           || !(dest2=prepend(dest, "-2"))
     257           4 :           || zlib_inflate(NULL, path, dest, NULL))
     258             :                 goto end;
     259           4 :         if(truncate(dest, length))
     260             :         {
     261           0 :                 logp("truncate of %s failed in %s\n", dest, __func__);
     262           0 :                 goto end;
     263             :         }
     264           4 :         if(compress_file(dest, dest2, compression))
     265             :                 goto end;
     266           4 :         unlink(dest);
     267           4 :         ret=do_rename(dest2, path);
     268             : end:
     269           4 :         if(dest) unlink(dest);
     270           4 :         if(dest2) unlink(dest2);
     271           4 :         free_w(&dest);
     272           4 :         free_w(&dest2);
     273           4 :         return ret;
     274             : }
     275             : 
     276         109 : int fzp_truncate(const char *path, enum fzp_type type, off_t length,
     277             :         int compression)
     278             : {
     279         109 :         if(!path)
     280             :         {
     281             :                 // Avoids a valgrind complaint in one of the tests.
     282           1 :                 errno=ENOENT;
     283           1 :                 goto error;
     284             :         }
     285         108 :         switch(type)
     286             :         {
     287             :                 case FZP_FILE:
     288         104 :                         return truncate(path, length);
     289             :                 case FZP_COMPRESSED:
     290           4 :                         return gztruncate(path, length, compression);
     291             :                 default:
     292             :                         unknown_type(type, __func__);
     293             :                         goto error;
     294             :         }
     295             : error:
     296             :         return -1;
     297             : }
     298             : #endif
     299             : 
     300       76808 : int fzp_printf(struct fzp *fzp, const char *format, ...)
     301             : {
     302       76808 :         int ret=-1;
     303             :         int n;
     304             : 
     305       76808 :         if(!fzp)
     306             :         {
     307           1 :                 not_open(__func__);
     308           1 :                 return ret;
     309             :         }
     310             : 
     311       76807 :         if(!fzp->buf)
     312             :         {
     313         642 :                 fzp->s=128;
     314         642 :                 if(!(fzp->buf=(char *)malloc_w(fzp->s, __func__)))
     315             :                         return ret;
     316             :         }
     317             : 
     318             :         // Avoid fixed size buffer.
     319             :         while(1)
     320             :         {
     321             :                 va_list ap;
     322       76807 :                 va_start(ap, format);
     323       76807 :                 n=vsnprintf(fzp->buf, fzp->s, format, ap);
     324       76807 :                 va_end(ap);
     325       76807 :                 if(n<0)
     326             :                 {
     327           0 :                         logp("Failed to vsnprintf in %s: %s\n",
     328           0 :                                 __func__, strerror(errno));
     329           0 :                         return ret;
     330             :                 }
     331       76807 :                 if(fzp->s<(size_t)n+1)
     332             :                 {
     333           0 :                         fzp->s*=2;
     334           0 :                         if(!(fzp->buf=(char *)
     335           0 :                                 realloc_w(fzp->buf, fzp->s, __func__)))
     336             :                                         return ret;
     337           0 :                         continue;
     338             :                 }
     339             : 
     340       76807 :                 break;
     341             :         }
     342             : 
     343       76807 :         switch(fzp->type)
     344             :         {
     345             :                 case FZP_FILE:
     346       48498 :                         ret=fprintf(fzp->fp, "%s", fzp->buf);
     347       48498 :                         break;
     348             :                 case FZP_COMPRESSED:
     349       28309 :                         ret=gzprintf(fzp->zp, "%s", fzp->buf);
     350       28309 :                         break;
     351             :                 default:
     352           0 :                         unknown_type(fzp->type, __func__);
     353             :                         break;
     354             :         }
     355             : 
     356             :         return ret;
     357             : }
     358             : 
     359           7 : void fzp_setlinebuf(struct fzp *fzp)
     360             : {
     361             : #ifndef HAVE_WIN32
     362           7 :         if(fzp) switch(fzp->type)
     363             :         {
     364             :                 case FZP_FILE:
     365           6 :                         setlinebuf(fzp->fp);
     366           6 :                         return;
     367             :                 case FZP_COMPRESSED:
     368           0 :                         logp("gzsetlinebuf() does not exist in %s\n", __func__);
     369           0 :                         return;
     370             :                 default:
     371           0 :                         unknown_type(fzp->type, __func__);
     372             :                         return;
     373             :         }
     374             :         not_open(__func__);
     375             : #endif
     376             : }
     377             : 
     378         661 : char *fzp_gets(struct fzp *fzp, char *s, int size)
     379             : {
     380         661 :         if(fzp) switch(fzp->type)
     381             :         {
     382             :                 case FZP_FILE:
     383         660 :                         return fgets(s, size, fzp->fp);
     384             :                 case FZP_COMPRESSED:
     385           0 :                         return gzgets(fzp->zp, s, size);
     386             :                 default:
     387           0 :                         unknown_type(fzp->type, __func__);
     388             :                         goto error;
     389             :         }
     390             :         not_open(__func__);
     391             : error:
     392             :         return NULL;
     393             : }
     394             : 
     395           3 : extern int fzp_fileno(struct fzp *fzp)
     396             : {
     397           3 :         if(fzp) switch(fzp->type)
     398             :         {
     399             :                 case FZP_FILE:
     400           2 :                         return fileno(fzp->fp);
     401             :                 case FZP_COMPRESSED:
     402           0 :                         logp("gzfileno() does not exist in %s\n", __func__);
     403           0 :                         goto error;
     404             :                 default:
     405           0 :                         unknown_type(fzp->type, __func__);
     406             :                         goto error;
     407             :         }
     408             :         not_open(__func__);
     409             : error:
     410             :         return -1;
     411             : }
     412             : 
     413           2 : static struct fzp *fzp_do_dopen(int fd, const char *mode,
     414             :         enum fzp_type type)
     415             : {
     416           2 :         struct fzp *fzp=NULL;
     417             : 
     418           2 :         if(!(fzp=fzp_alloc())) goto error;
     419           2 :         fzp->type=type;
     420           2 :         switch(type)
     421             :         {
     422             :                 case FZP_FILE:
     423           2 :                         if(!(fzp->fp=fdopen(fd, mode)))
     424             :                                 goto error;
     425           2 :                         return fzp;
     426             :                 case FZP_COMPRESSED:
     427           0 :                         if(!(fzp->zp=gzdopen(fd, mode)))
     428             :                                 goto error;
     429           0 :                         return fzp;
     430             :                 default:
     431           0 :                         unknown_type(fzp->type, __func__);
     432             :                         goto error;
     433             :         }
     434             : error:
     435           0 :         fzp_close(&fzp);
     436           0 :         return NULL;
     437             : }
     438             : 
     439           2 : struct fzp *fzp_dopen(int fd, const char *mode)
     440             : {
     441           2 :         return fzp_do_dopen(fd, mode, FZP_FILE);
     442             : }
     443             : 
     444           0 : struct fzp *fzp_gzdopen(int fd, const char *mode)
     445             : {
     446           0 :         return fzp_do_dopen(fd, mode, FZP_COMPRESSED);
     447             : }
     448             : 
     449           1 : void fzp_ERR_print_errors_fp(struct fzp *fzp)
     450             : {
     451           1 :         if(fzp) switch(fzp->type)
     452             :         {
     453             :                 case FZP_FILE:
     454           0 :                         ERR_print_errors_fp(fzp->fp);
     455           0 :                         break;
     456             :                 case FZP_COMPRESSED:
     457           0 :                         logp("ERR_print_errors_zp() does not exist in %s\n",
     458             :                                 __func__);
     459           0 :                         break;
     460             :                 default:
     461           0 :                         unknown_type(fzp->type, __func__);
     462             :                         break;
     463             :         }
     464           1 : }
     465             : 
     466           1 : X509 *fzp_PEM_read_X509(struct fzp *fzp)
     467             : {
     468           1 :         if(fzp) switch(fzp->type)
     469             :         {
     470             :                 case FZP_FILE:
     471           0 :                         return PEM_read_X509(fzp->fp, NULL, NULL, NULL);
     472             :                 case FZP_COMPRESSED:
     473           0 :                         logp("PEM_read_X509() does not exist in %s\n",
     474             :                                 __func__);
     475           0 :                         goto error;
     476             :                 default:
     477           0 :                         unknown_type(fzp->type, __func__);
     478             :                         goto error;
     479             :         }
     480             :         not_open(__func__);
     481             : error:
     482             :         return NULL;
     483             : }
     484             : 
     485             : static void pass_msg(size_t nmemb, size_t got, int pass)
     486             : {
     487          40 :         logp("Tried to read %lu bytes, got %lu by pass %d\n",
     488             :                 (unsigned long)nmemb, (unsigned long)got, pass);
     489             : }
     490             : 
     491       90822 : int fzp_read_ensure(struct fzp *fzp, void *ptr, size_t nmemb, const char *func)
     492             : {
     493             :         static int f;
     494             :         static int r;
     495             :         static size_t got;
     496             :         static int pass;
     497      181551 :         for(r=0, got=0, pass=0; got!=nmemb; pass++)
     498             :         {
     499       90862 :                 r=fzp_read(fzp, ((char *)ptr)+got, nmemb-got);
     500       90862 :                 if(r>0)
     501             :                 {
     502       90729 :                         got+=r;
     503       90729 :                         continue;
     504             :                 }
     505         133 :                 if(r<0)
     506             :                 {
     507           0 :                         pass_msg(nmemb, got, pass);
     508           0 :                         logp("Error in %s, called from %s: %s\n",
     509           0 :                                 __func__, func, strerror(errno));
     510           0 :                         return -1;
     511             :                 }
     512         133 :                 f=fzp_eof(fzp);
     513         133 :                 if(!f) continue; // Not yet end of file, keep trying.
     514         133 :                 if(f>0)
     515             :                 {
     516             :                         // End of file.
     517         133 :                         if(!got) return 1;
     518          80 :                         pass_msg(nmemb, got, pass);
     519          40 :                         logp("Error in %s, called from %s: %lu bytes, eof\n",
     520             :                                 __func__, func, (unsigned long)got);
     521          40 :                         return -1;
     522             :                 }
     523             :                 else
     524             :                 {
     525           0 :                         pass_msg(nmemb, got, pass);
     526           0 :                         logp("Error in %s by fzp_feof, called from %s: %s\n",
     527           0 :                                 __func__, func, strerror(errno));
     528           0 :                         return -1;
     529             :                 }
     530             :         }
     531             :         return 0;
     532             : }

Generated by: LCOV version 1.13