LCOV - code coverage report
Current view: top level - src/server/protocol2 - dpth.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 136 148 91.9 %
Date: 2016-05-30 Functions: 15 15 100.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../cmd.h"
       4             : #include "../../fsops.h"
       5             : #include "../../hexmap.h"
       6             : #include "../../iobuf.h"
       7             : #include "../../lock.h"
       8             : #include "../../log.h"
       9             : #include "../../prepend.h"
      10             : #include "../../protocol2/blk.h"
      11             : #include "dpth.h"
      12             : 
      13          11 : static int get_data_lock(struct lock *lock, struct dpth *dpth, const char *path)
      14             : {
      15          11 :         int ret=-1;
      16          11 :         char *p=NULL;
      17          11 :         char *lockfile=NULL;
      18             :         // Use just the first three components, excluding sig number.
      19          22 :         if(!(p=prepend_slash(dpth->base_path, path, 14))
      20          11 :           || !(lockfile=prepend(p, ".lock")))
      21             :                 goto end;
      22          22 :         if(lock_init(lock, lockfile)
      23          11 :           || build_path_w(lock->path))
      24             :                 goto end;
      25          11 :         lock_get_quick(lock);
      26          11 :         ret=0;
      27             : end:
      28          11 :         free_w(&p);
      29          11 :         free_w(&lockfile);
      30          11 :         return ret;
      31             : }
      32             : 
      33             : static char *dpth_mk_prim(struct dpth *dpth)
      34             : {
      35             :         static char path[8];
      36          38 :         snprintf(path, sizeof(path), "%04X", dpth->comp[0]);
      37             :         return path;
      38             : }
      39             : 
      40             : static char *dpth_mk_seco(struct dpth *dpth)
      41             : {
      42             :         static char path[16];
      43          38 :         snprintf(path, sizeof(path), "%04X/%04X", dpth->comp[0], dpth->comp[1]);
      44             :         return path;
      45             : }
      46             : 
      47          10 : static struct dpth_lock *dpth_lock_alloc(const char *save_path)
      48             : {
      49             :         struct dpth_lock *dpth_lock;
      50          10 :         if(!(dpth_lock=(struct dpth_lock *)
      51             :                 calloc_w(1, sizeof(struct dpth_lock), __func__)))
      52             :                         return NULL;
      53             :         snprintf(dpth_lock->save_path, sizeof(dpth_lock->save_path),
      54          10 :                 "%s", save_path);
      55          10 :         return dpth_lock;
      56             : }
      57             : 
      58          10 : static int add_lock_to_list(struct dpth *dpth,
      59             :         struct lock *lock, const char *save_path)
      60             : {
      61             :         struct dpth_lock *dlnew;
      62          10 :         if(!(dlnew=dpth_lock_alloc(save_path))) return -1;
      63          10 :         dlnew->lock=lock;
      64             : 
      65             :         // Add to the end of the list.
      66          10 :         if(dpth->tail) dpth->tail->next=dlnew;
      67           7 :         else if(!dpth->head) dpth->head=dlnew;
      68          10 :         dpth->tail=dlnew;
      69             :         return 0;
      70             : }
      71             : 
      72       12545 : char *dpth_protocol2_get_save_path(struct dpth *dpth)
      73             : {
      74             :         static char save_path[32];
      75             :         snprintf(save_path, sizeof(save_path), "%04X/%04X/%04X/%04X",
      76       12545 :                 dpth->comp[0], dpth->comp[1], dpth->comp[2], dpth->comp[3]);
      77       12545 :         return save_path;
      78             : }
      79             : 
      80       12548 : char *dpth_protocol2_mk(struct dpth *dpth)
      81             : {
      82             :         static char *save_path=NULL;
      83             :         static struct lock *lock=NULL;
      84             :         while(1)
      85             :         {
      86       12538 :                 save_path=dpth_protocol2_get_save_path(dpth);
      87       12538 :                 if(!dpth->need_data_lock) return save_path;
      88             : 
      89          11 :                 if(!lock && !(lock=lock_alloc())) goto error;
      90          22 :                 if(get_data_lock(lock, dpth, save_path)) goto error;
      91          11 :                 switch(lock->status)
      92             :                 {
      93             :                         case GET_LOCK_GOT: break;
      94             :                         case GET_LOCK_NOT_GOT:
      95             :                                 // Increment and try again.
      96           1 :                                 if(dpth_incr(dpth)) goto error;
      97             :                                 continue;
      98             :                         case GET_LOCK_ERROR:
      99             :                         default:
     100             :                                 goto error;
     101             :                 }
     102             : 
     103          10 :                 dpth->need_data_lock=0; // Got it.
     104          10 :                 if(add_lock_to_list(dpth, lock, save_path)) goto error;
     105          10 :                 lock=NULL;
     106          10 :                 return save_path;
     107             :         }
     108             : error:
     109           0 :         lock_free(&lock);
     110           0 :         return NULL;
     111             : }
     112             : 
     113             : // Returns 0 on OK, -1 on error. *max gets set to the next entry.
     114         150 : int get_highest_entry(const char *path, int *max, size_t len)
     115             : {
     116         150 :         int ent=0;
     117         150 :         int ret=0;
     118         150 :         DIR *d=NULL;
     119         150 :         struct dirent *dp=NULL;
     120             : 
     121         150 :         *max=-1;
     122         150 :         if(!(d=opendir(path))) goto end;
     123         225 :         while((dp=readdir(d)))
     124             :         {
     125         171 :                 if(!dp->d_ino
     126         171 :                   || strlen(dp->d_name)!=len)
     127             :                         continue;
     128          24 :                 ent=strtol(dp->d_name, NULL, 16);
     129          24 :                 if(ent>*max) *max=ent;
     130             :         }
     131             : 
     132             : end:
     133         150 :         if(d) closedir(d);
     134         150 :         return ret;
     135             : }
     136             : 
     137       16641 : int dpth_protocol2_incr_sig(struct dpth *dpth)
     138             : {
     139       16641 :         if(++dpth->comp[3]<DATA_FILE_SIG_MAX) return 0;
     140           9 :         dpth->comp[3]=0;
     141           9 :         dpth->need_data_lock=1;
     142           9 :         return dpth_incr(dpth);
     143             : }
     144             : 
     145          38 : static int open_cfile_fzp(struct dpth *dpth,
     146             :         const char *cname, const char *cfiles)
     147             : {
     148             :         int fd;
     149          38 :         int ret=-1;
     150          38 :         char *fname=NULL;
     151          38 :         char *fullpath=NULL;
     152             : 
     153          38 :         if(!(fname=prepend(cname, "XXXXXX")))
     154             :                 goto end;
     155          38 :         if(!(fullpath=prepend_s(cfiles, fname)))
     156             :                 goto end;
     157          38 :         logp("cfile_fzp is %s\n", fullpath);
     158          38 :         if(build_path_w(fullpath))
     159             :                 goto end;
     160          38 :         if((fd=mkstemp(fullpath))<0)
     161             :         {
     162             :                 logp("Could not mkstemp from template %s: %s\n",
     163           0 :                         fullpath, strerror(errno));
     164             :                 goto end;
     165             :         }
     166          38 :         if(!(dpth->cfile_fzp=fzp_dopen(fd, "wb")))
     167             :                 goto end;
     168             : 
     169          38 :         ret=0;
     170             : end:
     171          38 :         free_w(&fname);
     172          38 :         free_w(&fullpath);
     173          38 :         return ret;
     174             : }
     175             : 
     176         114 : int dpth_protocol2_init(struct dpth *dpth, const char *base_path,
     177             :         const char *cname, const char *cfiles, int max_storage_subdirs)
     178             : {
     179             :         int max;
     180          38 :         int ret=0;
     181          38 :         char *tmp=NULL;
     182             : 
     183          38 :         if(!base_path)
     184             :         {
     185           0 :                 logp("No base_path supplied in %s()\n", __func__);
     186           0 :                 goto error;
     187             :         }
     188             : 
     189          38 :         if(open_cfile_fzp(dpth, cname, cfiles)) goto error;
     190             : 
     191          38 :         dpth->max_storage_subdirs=max_storage_subdirs;
     192             : 
     193          38 :         free_w(&dpth->base_path);
     194          38 :         if(!(dpth->base_path=strdup_w(base_path, __func__)))
     195             :                 goto error;
     196             : 
     197          38 :         dpth->savepath=0;
     198          38 :         dpth->need_data_lock=1;
     199             : 
     200          38 :         if(get_highest_entry(dpth->base_path, &max, 4))
     201             :                 goto error;
     202          38 :         if(max<0) max=0;
     203          38 :         dpth->comp[0]=max;
     204          76 :         tmp=dpth_mk_prim(dpth);
     205          38 :         if(!(tmp=prepend_s(dpth->base_path, tmp)))
     206             :                 goto error;
     207             : 
     208          38 :         if(get_highest_entry(tmp, &max, 4))
     209             :                 goto error;
     210          38 :         if(max<0) max=0;
     211          38 :         dpth->comp[1]=max;
     212          38 :         free_w(&tmp);
     213         114 :         tmp=dpth_mk_seco(dpth);
     214          38 :         if(!(tmp=prepend_s(dpth->base_path, tmp)))
     215             :                 goto error;
     216             : 
     217          38 :         if(get_highest_entry(tmp, &max, 4))
     218             :                 goto error;
     219          38 :         if(max<0)
     220             :         {
     221          30 :                 dpth->comp[2]=0;
     222             :         }
     223             :         else
     224             :         {
     225           8 :                 dpth->comp[2]=max;
     226           8 :                 if(dpth_incr(dpth)) goto error;
     227             :         }
     228             : 
     229             :         goto end;
     230             : error:
     231             :         ret=-1;
     232             : end:
     233          38 :         free_w(&tmp);
     234          38 :         return ret;
     235             : }
     236             : 
     237       16630 : static int fprint_tag(struct fzp *fzp, enum cmd cmd, unsigned int s)
     238             : {
     239       16630 :         if(fzp_printf(fzp, "%c%04X", cmd, s)!=5)
     240             :         {
     241           0 :                 logp("Short fprintf\n");
     242           0 :                 return -1;
     243             :         }
     244             :         return 0;
     245             : }
     246             : 
     247       16630 : static int fwrite_buf(enum cmd cmd,
     248             :         const char *buf, unsigned int s, struct fzp *fzp)
     249             : {
     250             :         static size_t bytes;
     251       16630 :         if(fprint_tag(fzp, cmd, s)) return -1;
     252       16630 :         if((bytes=fzp_write(fzp, buf, s))!=s)
     253             :         {
     254           0 :                 logp("Short write: %d\n", (int)bytes);
     255           0 :                 return -1;
     256             :         }
     257             :         return 0;
     258             : }
     259             : 
     260           9 : static struct fzp *file_open_w(const char *path, const char *mode)
     261             : {
     262           9 :         if(build_path_w(path)) return NULL;
     263           9 :         return fzp_open(path, "wb");
     264             : }
     265             : 
     266           9 : static int write_to_cfile(struct dpth *dpth, struct blk *blk)
     267             : {
     268             :         struct iobuf wbuf;
     269           9 :         blk_to_iobuf_savepath(blk, &wbuf);
     270           9 :         if(iobuf_send_msg_fzp(&wbuf, dpth->cfile_fzp))
     271             :                 return -1;
     272           9 :         if(fzp_flush(dpth->cfile_fzp))
     273             :                 return -1;
     274           9 :         if(fsync(fzp_fileno(dpth->cfile_fzp)))
     275             :         {
     276           0 :                 logp("fsync on cfile_fzp failed: %s\n", strerror(errno));
     277             :                 return -1;
     278             :         }
     279             :         return 0;
     280             : }
     281             : 
     282           9 : static struct fzp *open_data_file_for_write(struct dpth *dpth, struct blk *blk)
     283             : {
     284           9 :         char *path=NULL;
     285           9 :         struct fzp *fzp=NULL;
     286           9 :         char *savepathstr=NULL;
     287           9 :         struct dpth_lock *head=dpth->head;
     288             : 
     289           9 :         savepathstr=uint64_to_savepathstr(blk->savepath);
     290             : 
     291             :         // Sanity check. They should be coming through from the client
     292             :         // in the same order in which we locked them.
     293             :         // Remember that the save_path on the lock list is shorter than the
     294             :         // full save_path on the blk.
     295           9 :         if(!head
     296           9 :           || strncmp(head->save_path,
     297             :                 //FIX THIS
     298           9 :                 savepathstr, sizeof(head->save_path)-1))
     299             :         {
     300             :                 logp("lock and block save_path mismatch: %s %s\n",
     301           0 :                         head?head->save_path:"(null)", savepathstr);
     302           0 :                 goto end;
     303             :         }
     304             : 
     305           9 :         if(!(path=prepend_slash(dpth->base_path, savepathstr, 14)))
     306             :                 goto end;
     307           9 :         if(write_to_cfile(dpth, blk))
     308             :                 goto end;
     309           9 :         fzp=file_open_w(path, "wb");
     310             : end:
     311           9 :         free_w(&path);
     312           9 :         return fzp;
     313             : }
     314             : 
     315       16630 : int dpth_protocol2_fwrite(struct dpth *dpth,
     316             :         struct iobuf *iobuf, struct blk *blk)
     317             : {
     318             :         // Remember that the save_path on the lock list is shorter than the
     319             :         // full save_path on the blk.
     320       16630 :         if(dpth->fzp
     321       16623 :           && strncmp(dpth->head->save_path,
     322       16623 :                 uint64_to_savepathstr(blk->savepath),
     323       16623 :                 sizeof(dpth->head->save_path)-1)
     324       16632 :           && dpth_release_and_move_to_next_in_list(dpth))
     325             :                 return -1;
     326             : 
     327             :         // Open the current list head if we have no fzp.
     328       33260 :         if(!dpth->fzp
     329       16630 :           && !(dpth->fzp=open_data_file_for_write(dpth, blk))) return -1;
     330             : 
     331       16630 :         return fwrite_buf(CMD_DATA, iobuf->buf, iobuf->len, dpth->fzp);
     332             : }

Generated by: LCOV version 1.10