LCOV - code coverage report
Current view: top level - src/server - dpth.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 83 95 87.4 %
Date: 2022-12-03 01:09:05 Functions: 9 10 90.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../cmd.h"
       4             : #include "../fzp.h"
       5             : #include "../handy.h"
       6             : #include "../lock.h"
       7             : #include "../log.h"
       8             : #include "dpth.h"
       9             : 
      10          39 : struct dpth *dpth_alloc(void)
      11             : {
      12          39 :         return (struct dpth *)calloc_w(1, sizeof(struct dpth), __func__);
      13             : }
      14             : 
      15          44 : void dpth_free(struct dpth **dpth)
      16             : {
      17          44 :         if(!dpth || !*dpth) return;
      18          39 :         dpth_release_all(*dpth);
      19          39 :         fzp_close(&(*dpth)->cfile_fzp);
      20          39 :         free_w(&((*dpth)->base_path));
      21          39 :         free_v((void **)dpth);
      22             : }
      23             : 
      24           0 : int dpth_release_and_move_to_next_in_list(struct dpth *dpth)
      25             : {
      26           0 :         int ret=0;
      27           0 :         struct dpth_lock *next=NULL;
      28             : 
      29             :         // Try to release (and unlink) the lock even if fzp_close failed, just
      30             :         // to be tidy.
      31           0 :         if(fzp_close(&dpth->fzp)) ret=-1;
      32           0 :         if(lock_release(dpth->head->lock)) ret=-1;
      33           0 :         lock_free(&dpth->head->lock);
      34             : 
      35           0 :         next=dpth->head->next;
      36           0 :         if(dpth->head==dpth->tail) dpth->tail=next;
      37           0 :         free_v((void **)&dpth->head);
      38           0 :         dpth->head=next;
      39           0 :         return ret;
      40             : }
      41             : 
      42          39 : int dpth_release_all(struct dpth *dpth)
      43             : {
      44          39 :         int ret=0;
      45          39 :         if(!dpth) return 0;
      46          39 :         if(dpth->fzp && fzp_close(&dpth->fzp)) ret=-1;
      47          39 :         while(dpth->head)
      48           0 :                 if(dpth_release_and_move_to_next_in_list(dpth)) ret=-1;
      49             :         return ret;
      50             : }
      51             : 
      52             : #define MAX_FILES_PER_DIR       0xFFFF
      53             : 
      54             : static int incr(uint16_t *component, uint16_t max)
      55             : {
      56          42 :         if((*component)++<max) return 1;
      57          18 :         *component=0;
      58             :         return 0;
      59             : }
      60             : 
      61             : // Three levels with 65535 entries each gives
      62             : // 65535^3 = 281,462,092,005,375 data entries
      63             : // recommend a filesystem with lots of inodes?
      64             : // Hmm, but ext3 only allows 32000 subdirs, although that many files are OK.
      65          26 : int dpth_incr(struct dpth *dpth)
      66             : {
      67          52 :         if(incr(&dpth->comp[2], MAX_FILES_PER_DIR)
      68          20 :           || incr(&dpth->comp[1], dpth->max_storage_subdirs)
      69          12 :           || incr(&dpth->comp[0], dpth->max_storage_subdirs))
      70             :                 return 0;
      71           2 :         logp("No free data file entries out of the %d*%d*%d available!\n",
      72             :                 MAX_FILES_PER_DIR,
      73             :                 dpth->max_storage_subdirs, dpth->max_storage_subdirs);
      74           2 :         logp("Maybe move the storage directory aside and start again.\n");
      75           2 :         return -1;
      76             : }
      77             : 
      78          11 : char *dpth_mk(struct dpth *dpth, int compression, enum cmd cmd)
      79             : {
      80             :         static char path[32];
      81             :         // File data.
      82          44 :         snprintf(path, sizeof(path), "%04X/%04X/%04X%s",
      83          33 :                 dpth->comp[0], dpth->comp[1], dpth->comp[2],
      84             :                 // Because of the way EFS works, it cannot be compressed.
      85          11 :                 (compression && cmd!=CMD_EFS_FILE)?".gz":"");
      86          11 :         return path;
      87             : }
      88             : 
      89             : static char *dpth_mk_prim(struct dpth *dpth)
      90             : {
      91             :         static char path[5];
      92          19 :         snprintf(path, sizeof(path), "%04X", dpth->comp[0]);
      93             :         return path;
      94             : }
      95             : 
      96             : static char *dpth_mk_seco(struct dpth *dpth)
      97             : {
      98             :         static char path[10];
      99          19 :         snprintf(path, sizeof(path), "%04X/%04X", dpth->comp[0], dpth->comp[1]);
     100             :         return path;
     101             : }
     102             : 
     103          57 : static void get_highest_entry(const char *path, uint16_t *max)
     104             : {
     105          57 :         int ent=0;
     106          57 :         DIR *d=NULL;
     107          57 :         struct dirent *dp=NULL;
     108             : 
     109          57 :         *max=0;
     110          57 :         if(!(d=opendir(path))) return;
     111          88 :         while((dp=readdir(d)))
     112             :         {
     113          66 :                 if(!dp->d_ino
     114          66 :                   || !strcmp(dp->d_name, ".")
     115          44 :                   || !strcmp(dp->d_name, ".."))
     116          44 :                         continue;
     117          22 :                 ent=strtol(dp->d_name, NULL, 16);
     118          22 :                 if(ent>*max) *max=ent;
     119             :         }
     120          22 :         closedir(d);
     121             : }
     122             : 
     123          57 : static int get_next_comp(const char *currentdata,
     124             :         const char *path, uint16_t *comp)
     125             : {
     126          57 :         int ret=-1;
     127          57 :         char *tmp=NULL;
     128          57 :         if(path)
     129          38 :                 tmp=prepend_s(currentdata, path);
     130             :         else
     131          19 :                 tmp=strdup_w(currentdata, __func__);
     132          57 :         if(!tmp) goto end;
     133             : 
     134          57 :         get_highest_entry(tmp, comp);
     135          57 :         ret=0;
     136             : end:
     137          57 :         free_w(&tmp);
     138          57 :         return ret;
     139             : }
     140             : 
     141          19 : int dpth_init(struct dpth *dpth, const char *basepath,
     142             :         int max_storage_subdirs)
     143             : {
     144          19 :         int ret=0;
     145          19 :         dpth->savepath=0;
     146          19 :         dpth->max_storage_subdirs=max_storage_subdirs;
     147             : 
     148          19 :         if((ret=get_next_comp(basepath,
     149             :                 NULL, &dpth->comp[0]))) goto end;
     150             : 
     151          38 :         if((ret=get_next_comp(basepath,
     152          19 :                 dpth_mk_prim(dpth), &dpth->comp[1]))) goto end;
     153             : 
     154          38 :         if((ret=get_next_comp(basepath,
     155          19 :                 dpth_mk_seco(dpth), &dpth->comp[2]))) goto end;
     156             : 
     157             :         // At this point, we have the latest data file. Increment to get the
     158             :         // next free one.
     159          19 :         ret=dpth_incr(dpth);
     160             : 
     161             : end:
     162          19 :         switch(ret)
     163             :         {
     164             :                 case -1: return -1;
     165          18 :                 default: return 0;
     166             :         }
     167             : }
     168             : 
     169          12 : int dpth_set_from_string(struct dpth *dpth, const char *datapath)
     170             : {
     171          12 :         unsigned int a=0;
     172          12 :         unsigned int b=0;
     173          12 :         unsigned int c=0;
     174             : 
     175          12 :         if(!datapath
     176          12 :           || *datapath=='t') // The path used the tree style structure.
     177             :                 return 0;
     178             : 
     179          11 :         if((sscanf(datapath, "%04X/%04X/%04X", &a, &b, &c))!=3)
     180             :                 return -1;
     181           9 :         if(dpth->comp[0]==(int)a
     182           4 :           && dpth->comp[1]==(int)b
     183           2 :           && dpth->comp[2] > (int)c)
     184             :                 return 0;
     185           8 :         if(dpth->comp[0]==(int)a
     186           3 :           && dpth->comp[1] > (int)b)
     187             :                 return 0;
     188           7 :         if(dpth->comp[0] > (int)a)
     189             :                 return 0;
     190             : 
     191           4 :         dpth->comp[0]=a;
     192           4 :         dpth->comp[1]=b;
     193           4 :         dpth->comp[2]=c;
     194           4 :         return 0;
     195             : }

Generated by: LCOV version 1.13