LCOV - code coverage report
Current view: top level - src/server/monitor - json_output.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 123 264 46.6 %
Date: 2020-11-06 04:06:22 Functions: 14 20 70.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../asfd.h"
       4             : #include "../../async.h"
       5             : #include "../../bu.h"
       6             : #include "../../cmd.h"
       7             : #include "../../cstat.h"
       8             : #include "../../fzp.h"
       9             : #include "../../handy.h"
      10             : #include "../../iobuf.h"
      11             : #include "../../prepend.h"
      12             : #include "../../strlist.h"
      13             : #include "../../yajl_gen_w.h"
      14             : #include "../timestamp.h"
      15             : #include "browse.h"
      16             : #include "json_output.h"
      17             : 
      18             : static int pretty_print=1;
      19             : static long version_2_1_8=0;
      20             : 
      21           8 : void json_set_pretty_print(int value)
      22             : {
      23           8 :         pretty_print=value;
      24           8 : }
      25             : 
      26           8 : static int write_all(struct asfd *asfd)
      27             : {
      28           8 :         int ret=-1;
      29           8 :         size_t w=0;
      30           8 :         size_t len=0;
      31             :         const unsigned char *buf;
      32             :         struct iobuf wbuf;
      33             : 
      34           8 :         yajl_gen_get_buf(yajl, &buf, &len);
      35          24 :         while(len)
      36             :         {
      37           8 :                 w=len;
      38           8 :                 if(w>ASYNC_BUF_LEN) w=ASYNC_BUF_LEN;
      39           8 :                 iobuf_set(&wbuf, CMD_GEN /* not used */, (char *)buf, w);
      40           8 :                 if((ret=asfd->write(asfd, &wbuf)))
      41             :                         break;
      42           8 :                 buf+=w;
      43           8 :                 len-=w;
      44             :         }
      45           8 :         if(!ret && !pretty_print)
      46             :         {
      47           1 :                 iobuf_set(&wbuf, CMD_GEN /* not used */, (char *)"\n", 1);
      48           1 :                 ret=asfd->write(asfd, &wbuf);
      49             :         }
      50             : 
      51           8 :         yajl_gen_clear(yajl);
      52           8 :         return ret;
      53             : }
      54             : 
      55           8 : static int json_start(void)
      56             : {
      57           8 :         if(!yajl)
      58             :         {
      59           8 :                 if(!(yajl=yajl_gen_alloc(NULL)))
      60             :                         return -1;
      61           8 :                 yajl_gen_config(yajl, yajl_gen_beautify, pretty_print);
      62           8 :                 if(!version_2_1_8)
      63           8 :                         version_2_1_8=version_to_long("2.1.8");
      64             :         }
      65           8 :         if(yajl_map_open_w()) return -1;
      66           8 :         return 0;
      67             : }
      68             : 
      69           7 : static int json_clients(void)
      70             : {
      71           7 :         if(yajl_gen_str_w("clients")
      72           7 :           || yajl_array_open_w())
      73             :                 return -1;
      74             :         return 0;
      75             : }
      76             : 
      77             : static int json_clients_end(void)
      78             : {
      79           7 :         if(yajl_array_close_w()) return -1;
      80             :         return 0;
      81             : }
      82             : 
      83           8 : static int json_end(struct asfd *asfd)
      84             : {
      85           8 :         int ret=-1;
      86           8 :         if(yajl_map_close_w())
      87             :                 goto end;
      88           8 :         ret=write_all(asfd);
      89             : end:
      90           8 :         yajl_gen_free(yajl);
      91           8 :         yajl=NULL;
      92           8 :         return ret;
      93             : }
      94             : 
      95             : static int flag_matches(struct bu *bu, uint16_t flag)
      96             : {
      97         138 :         return (bu && (bu->flags & flag));
      98             : }
      99             : 
     100             : static int flag_wrap_str(struct bu *bu, uint16_t flag, const char *field)
     101             : {
     102         276 :         if(!flag_matches(bu, flag)) return 0;
     103          36 :         return yajl_gen_str_w(field);
     104             : }
     105             : 
     106           0 : static struct fzp *open_backup_log(struct bu *bu, const char *logfile)
     107             : {
     108           0 :         char *path=NULL;
     109           0 :         struct fzp *fzp=NULL;
     110             : 
     111           0 :         char logfilereal[32]="";
     112           0 :         if(!strcmp(logfile, "backup"))
     113           0 :                 snprintf(logfilereal, sizeof(logfilereal), "log");
     114           0 :         else if(!strcmp(logfile, "restore"))
     115           0 :                 snprintf(logfilereal, sizeof(logfilereal), "restorelog");
     116           0 :         else if(!strcmp(logfile, "verify"))
     117           0 :                 snprintf(logfilereal, sizeof(logfilereal), "verifylog");
     118           0 :         else if(!strcmp(logfile, "backup_stats"))
     119           0 :                 snprintf(logfilereal, sizeof(logfilereal), "backup_stats");
     120           0 :         else if(!strcmp(logfile, "restore_stats"))
     121           0 :                 snprintf(logfilereal, sizeof(logfilereal), "restore_stats");
     122           0 :         else if(!strcmp(logfile, "verify_stats"))
     123           0 :                 snprintf(logfilereal, sizeof(logfilereal), "verify_stats");
     124             : 
     125           0 :         if(!(path=prepend_s(bu->path, logfilereal)))
     126             :                 goto end;
     127           0 :         if(!(fzp=fzp_gzopen(path, "rb")))
     128             :         {
     129           0 :                 if(astrcat(&path, ".gz", __func__)
     130           0 :                   || !(fzp=fzp_gzopen(path, "rb")))
     131             :                         goto end;
     132             :         }
     133             : end:
     134           0 :         free_w(&path);
     135           0 :         return fzp;
     136             : 
     137             : }
     138             : 
     139           0 : static int flag_wrap_str_zp(struct bu *bu, uint16_t flag, const char *field,
     140             :         const char *logfile)
     141             : {
     142           0 :         int ret=-1;
     143           0 :         struct fzp *fzp=NULL;
     144           0 :         if(!flag_matches(bu, flag)
     145           0 :           || !logfile || strcmp(logfile, field))
     146             :                 return 0;
     147           0 :         if(!(fzp=open_backup_log(bu, logfile))) goto end;
     148           0 :         if(yajl_gen_str_w(field)) goto end;
     149           0 :         if(yajl_array_open_w()) goto end;
     150           0 :         if(fzp)
     151             :         {
     152           0 :                 char *cp=NULL;
     153           0 :                 char buf[1024]="";
     154           0 :                 while(fzp_gets(fzp, buf, sizeof(buf)))
     155             :                 {
     156           0 :                         if((cp=strrchr(buf, '\n'))) *cp='\0';
     157           0 :                         if(yajl_gen_str_w(buf))
     158             :                                 goto end;
     159             :                 }
     160             :         }
     161           0 :         if(yajl_array_close_w()) goto end;
     162           0 :         ret=0;
     163             : end:
     164           0 :         fzp_close(&fzp);
     165           0 :         return ret;
     166             : }
     167             : 
     168           0 : static int do_counters(struct cntr *cntr)
     169             : {
     170             :         static char type[2];
     171             :         struct cntr_ent *e;
     172             : 
     173             : #ifndef UTEST
     174             :         cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=(uint64_t)time(NULL);
     175             : #endif
     176           0 :         if(yajl_gen_str_w("counters")
     177           0 :           || yajl_array_open_w()) return -1;
     178           0 :         for(e=cntr->list; e; e=e->next)
     179             :         {
     180           0 :                 if(e->flags & CNTR_SINGLE_FIELD)
     181             :                 {
     182           0 :                         if(!e->count) continue;
     183           0 :                         snprintf(type, sizeof(type), "%c", e->cmd);
     184           0 :                         if(yajl_map_open_w()
     185           0 :                           || yajl_gen_str_pair_w("name", e->field)
     186           0 :                           || yajl_gen_str_pair_w("type", type)
     187           0 :                           || yajl_gen_int_pair_w("count", e->count)
     188           0 :                           || yajl_map_close_w())
     189             :                                 return -1;
     190             :                 }
     191           0 :                 else if(e->flags & CNTR_TABULATE)
     192             :                 {
     193           0 :                         if(!e->count
     194           0 :                           && !e->changed
     195           0 :                           && !e->same
     196           0 :                           && !e->deleted
     197           0 :                           && !e->phase1)
     198           0 :                                 continue;
     199           0 :                         snprintf(type, sizeof(type), "%c", e->cmd);
     200           0 :                         if(yajl_map_open_w()
     201           0 :                           || yajl_gen_str_pair_w("name", e->field)
     202           0 :                           || yajl_gen_str_pair_w("type", type)
     203           0 :                           || yajl_gen_int_pair_w("count", e->count)
     204           0 :                           || yajl_gen_int_pair_w("changed", e->changed)
     205           0 :                           || yajl_gen_int_pair_w("same", e->same)
     206           0 :                           || yajl_gen_int_pair_w("deleted", e->deleted)
     207           0 :                           || yajl_gen_int_pair_w("scanned", e->phase1)
     208           0 :                           || yajl_map_close_w())
     209             :                                 return -1;
     210             :                 }
     211             :         }
     212             : 
     213           0 :         if(yajl_array_close_w())
     214             :                 return -1;
     215             :         return 0;
     216             : }
     217             : 
     218          35 : static int json_send_backup(struct cstat *cstat, struct bu *bu,
     219             :         int print_flags, const char *logfile, const char *browse,
     220             :         int use_cache, long peer_version)
     221             : {
     222          35 :         long long bno=0;
     223          35 :         long long timestamp=0;
     224          35 :         if(!bu) return 0;
     225          23 :         bno=(long long)bu->bno;
     226          23 :         timestamp=(long long)timestamp_to_long(bu->timestamp);
     227             : 
     228          23 :         if(yajl_map_open_w()
     229          23 :           || yajl_gen_int_pair_w("number", bno)
     230          23 :           || yajl_gen_int_pair_w("timestamp", timestamp)
     231          23 :           || yajl_gen_str_w("flags")
     232          23 :           || yajl_array_open_w()
     233          23 :           || flag_wrap_str(bu, BU_HARDLINKED, "hardlinked")
     234          23 :           || flag_wrap_str(bu, BU_DELETABLE, "deletable")
     235          23 :           || flag_wrap_str(bu, BU_WORKING, "working")
     236          23 :           || flag_wrap_str(bu, BU_FINISHING, "finishing")
     237          23 :           || flag_wrap_str(bu, BU_CURRENT, "current")
     238          23 :           || flag_wrap_str(bu, BU_MANIFEST, "manifest")
     239          23 :           || yajl_array_close_w())
     240             :                 return -1;
     241          23 :         if(bu->flags & (BU_WORKING|BU_FINISHING))
     242             :         {
     243           6 :                 if(peer_version<=version_2_1_8)
     244             :                 {
     245           0 :                         if(do_counters(cstat->cntrs))
     246             :                                 return -1;
     247             :                 }
     248             :         }
     249          23 :         if(print_flags
     250          23 :           && (bu->flags & (BU_LOG_BACKUP|BU_LOG_RESTORE|BU_LOG_VERIFY
     251             :                 |BU_STATS_BACKUP|BU_STATS_RESTORE|BU_STATS_VERIFY)))
     252             :         {
     253           0 :                 if(yajl_gen_str_w("logs")
     254           0 :                   || yajl_map_open_w()
     255           0 :                   || yajl_gen_str_w("list")
     256           0 :                   || yajl_array_open_w()
     257           0 :                   || flag_wrap_str(bu, BU_LOG_BACKUP, "backup")
     258           0 :                   || flag_wrap_str(bu, BU_LOG_RESTORE, "restore")
     259           0 :                   || flag_wrap_str(bu, BU_LOG_VERIFY, "verify")
     260           0 :                   || flag_wrap_str(bu, BU_STATS_BACKUP, "backup_stats")
     261           0 :                   || flag_wrap_str(bu, BU_STATS_RESTORE, "restore_stats")
     262           0 :                   || flag_wrap_str(bu, BU_STATS_VERIFY, "verify_stats")
     263           0 :                   || yajl_array_close_w())
     264             :                         return -1;
     265           0 :                 if(logfile)
     266             :                 {
     267           0 :                         if(flag_wrap_str_zp(bu,
     268             :                                 BU_LOG_BACKUP, "backup", logfile)
     269           0 :                           || flag_wrap_str_zp(bu,
     270             :                                 BU_LOG_RESTORE, "restore", logfile)
     271           0 :                           || flag_wrap_str_zp(bu,
     272             :                                 BU_LOG_VERIFY, "verify", logfile)
     273           0 :                           || flag_wrap_str_zp(bu,
     274             :                                 BU_STATS_BACKUP, "backup_stats", logfile)
     275           0 :                           || flag_wrap_str_zp(bu,
     276             :                                 BU_STATS_RESTORE, "restore_stats", logfile)
     277           0 :                           || flag_wrap_str_zp(bu,
     278             :                                 BU_STATS_VERIFY, "verify_stats", logfile))
     279             :                                         return -1;
     280             :                 }
     281           0 :                 if(yajl_map_close_w())
     282             :                         return -1;
     283           0 :                 if(browse)
     284             :                 {
     285           0 :                         if(yajl_gen_str_w("browse")) return -1;
     286           0 :                         if(yajl_map_open_w()) return -1;
     287           0 :                         if(yajl_gen_str_pair_w("directory", browse)) return -1;
     288           0 :                         if(yajl_gen_str_w("entries")) return -1;
     289           0 :                         if(yajl_array_open_w()) return -1;
     290           0 :                         if(browse_manifest(cstat, bu, browse, use_cache))
     291             :                                 return -1;
     292           0 :                         if(yajl_array_close_w()) return -1;
     293           0 :                         if(yajl_map_close_w()) return -1;
     294             : 
     295             :                 }
     296             :         }
     297          23 :         if(yajl_gen_map_close(yajl)!=yajl_gen_status_ok)
     298             :                 return -1;
     299             : 
     300          23 :         return 0;
     301             : }
     302             : 
     303          16 : static int str_array(const char *field, struct cstat *cstat)
     304             : {
     305          16 :         struct strlist *s=NULL;
     306          16 :         if(!cstat->labels) return 0;
     307           3 :         if(yajl_gen_str_w(field)
     308           3 :           || yajl_array_open_w())
     309             :                 return -1;
     310           9 :         for(s=cstat->labels; s; s=s->next)
     311           6 :                 if(yajl_gen_str_w(s->path))
     312             :                         return -1;
     313           3 :         if(yajl_array_close_w())
     314             :                 return -1;
     315             :         return 0;
     316             : }
     317             : 
     318           0 : static int do_children(struct cntr *cntrs)
     319             : {
     320             :         struct cntr *c;
     321           0 :         if(yajl_gen_str_w("children")
     322           0 :           || yajl_array_open_w())
     323             :                 return -1;
     324           0 :         for(c=cntrs; c; c=c->next)
     325             :         {
     326           0 :                 if(yajl_map_open_w()
     327           0 :                   || yajl_gen_int_pair_w("pid", c->pid)
     328           0 :                   || yajl_gen_int_pair_w("backup", c->bno)
     329           0 :                   || yajl_gen_str_pair_w("action", cntr_status_to_action_str(c))
     330           0 :                   || yajl_gen_str_pair_w("phase", cntr_status_to_str(c)))
     331             :                         return -1;
     332           0 :                 if(do_counters(c))
     333             :                         return -1;
     334           0 :                 if(yajl_map_close_w())
     335             :                         return -1;
     336             :         }
     337           0 :         if(yajl_array_close_w())
     338             :                 return -1;
     339           0 :         return 0;
     340             : }
     341             : 
     342          16 : static int json_send_client_start(struct cstat *cstat, long peer_version)
     343             : {
     344          16 :         const char *run_status=run_status_to_str(cstat);
     345             : 
     346          16 :         if(yajl_map_open_w()
     347          16 :           || yajl_gen_str_pair_w("name", cstat->name))
     348             :                 return -1;
     349          16 :         if(str_array("labels", cstat))
     350             :                 return -1;
     351          16 :         if(yajl_gen_str_pair_w("run_status", run_status))
     352             :                 return -1;
     353          16 :         if(yajl_gen_int_pair_w("protocol", cstat->protocol))
     354             :                 return -1;
     355          16 :         if(peer_version>version_2_1_8)
     356             :         {
     357          16 :                 if(cstat->cntrs
     358           0 :                   && do_children(cstat->cntrs))
     359             :                         return -1;
     360             :         }
     361           0 :         else if(cstat->cntrs)
     362             :         {
     363             :                 // Best effort.
     364           0 :                 if(yajl_gen_str_pair_w("phase",
     365             :                         cntr_status_to_str(cstat->cntrs)))
     366             :                                 return -1;
     367             :         }
     368          16 :         if(yajl_gen_str_w("backups")
     369          16 :           || yajl_array_open_w())
     370             :                 return -1;
     371             :         return 0;
     372             : }
     373             : 
     374          16 : static int json_send_client_end(void)
     375             : {
     376          16 :         if(yajl_array_close_w()
     377          16 :           || yajl_map_close_w())
     378             :                 return -1;
     379             :         return 0;
     380             : }
     381             : 
     382          15 : static int json_send_client_backup(struct cstat *cstat, struct bu *bu1,
     383             :         struct bu *bu2, const char *logfile, const char *browse, int use_cache,
     384             :         long peer_version)
     385             : {
     386          15 :         int ret=-1;
     387          15 :         if(json_send_client_start(cstat, peer_version))
     388             :                 return -1;
     389          15 :         if((ret=json_send_backup(cstat, bu1,
     390             :                 1 /* print flags */, logfile, browse, use_cache, peer_version)))
     391             :                         goto end;
     392          15 :         if((ret=json_send_backup(cstat, bu2,
     393             :                 1 /* print flags */, logfile, browse, use_cache, peer_version)))
     394             :                         goto end;
     395             : end:
     396          15 :         if(json_send_client_end()) ret=-1;
     397             :         return ret;
     398             : }
     399             : 
     400           1 : static int json_send_client_backup_list(struct cstat *cstat, int use_cache,
     401             :         long peer_version)
     402             : {
     403           1 :         int ret=-1;
     404             :         struct bu *bu;
     405           1 :         if(json_send_client_start(cstat, peer_version))
     406             :                 return -1;
     407           6 :         for(bu=cstat->bu; bu; bu=bu->prev)
     408             :         {
     409           5 :                 if(json_send_backup(cstat, bu,
     410             :                         1 /* print flags */, NULL, NULL,
     411             :                         use_cache, peer_version))
     412             :                                 goto end;
     413             :         }
     414             :         ret=0;
     415             : end:
     416           1 :         if(json_send_client_end()) ret=-1;
     417             :         return ret;
     418             : }
     419             : 
     420           7 : int json_send(struct asfd *asfd, struct cstat *clist, struct cstat *cstat,
     421             :         struct bu *bu, const char *logfile, const char *browse,
     422             :         int use_cache, long peer_version)
     423             : {
     424           7 :         int ret=-1;
     425             :         struct cstat *c;
     426             : 
     427           7 :         if(json_start()
     428           7 :           || json_clients())
     429             :                 goto end;
     430             : 
     431           7 :         if(cstat && bu)
     432             :         {
     433           0 :                 if(json_send_client_backup(cstat, bu, NULL,
     434             :                         logfile, browse, use_cache, peer_version))
     435             :                                 goto end;
     436             :         }
     437           7 :         else if(cstat)
     438             :         {
     439           1 :                 if(json_send_client_backup_list(cstat,
     440             :                         use_cache, peer_version))
     441             :                                 goto end;
     442             :         }
     443          15 :         else for(c=clist; c; c=c->next)
     444             :         {
     445          15 :                 if(!c->permitted) continue;
     446          15 :                 if(json_send_client_backup(c,
     447             :                         bu_find_current(c->bu),
     448             :                         bu_find_working_or_finishing(c->bu),
     449             :                         NULL, NULL, use_cache, peer_version))
     450             :                                 goto end;
     451             :         }
     452             : 
     453             :         ret=0;
     454             : end:
     455           7 :         if(json_clients_end()
     456           7 :           || json_end(asfd)) return -1;
     457             :         return ret;
     458             : }
     459             : 
     460           0 : int json_cntr(struct asfd *asfd, struct cntr *cntr)
     461             : {
     462           0 :         int ret=-1;
     463           0 :         if(json_start()
     464           0 :           || do_counters(cntr))
     465             :                 goto end;
     466           0 :         ret=0;
     467             : end:
     468           0 :         if(json_end(asfd)) return -1;
     469           0 :         return ret;
     470             : }
     471             : 
     472           0 : int json_from_entry(const char *path, const char *link, struct stat *statp)
     473             : {
     474           0 :         return yajl_map_open_w()
     475           0 :           || yajl_gen_str_pair_w("name", path)
     476           0 :           || yajl_gen_str_pair_w("link", link? link:"")
     477           0 :           || yajl_gen_int_pair_w("dev", statp->st_dev)
     478           0 :           || yajl_gen_int_pair_w("ino", statp->st_ino)
     479           0 :           || yajl_gen_int_pair_w("mode", statp->st_mode)
     480           0 :           || yajl_gen_int_pair_w("nlink", statp->st_nlink)
     481           0 :           || yajl_gen_int_pair_w("uid", statp->st_uid)
     482           0 :           || yajl_gen_int_pair_w("gid", statp->st_gid)
     483           0 :           || yajl_gen_int_pair_w("rdev", statp->st_rdev)
     484           0 :           || yajl_gen_int_pair_w("size", statp->st_size)
     485           0 :           || yajl_gen_int_pair_w("blksize", statp->st_blksize)
     486           0 :           || yajl_gen_int_pair_w("blocks", statp->st_blocks)
     487           0 :           || yajl_gen_int_pair_w("atime", statp->st_atime)
     488           0 :           || yajl_gen_int_pair_w("ctime", statp->st_ctime)
     489           0 :           || yajl_gen_int_pair_w("mtime", statp->st_mtime)
     490           0 :           || yajl_map_close_w();
     491             : }
     492             : 
     493           1 : int json_send_msg(struct asfd *asfd, const char *field, const char *msg)
     494             : {
     495             :         int save;
     496           1 :         int ret=0;
     497             : 
     498             :         // Turn off pretty printing so that we get it on one line.
     499           1 :         save=pretty_print;
     500           1 :         pretty_print=0;
     501             : 
     502           1 :         if(json_start()
     503           1 :           || yajl_gen_str_pair_w(field, msg)
     504           1 :           || json_end(asfd))
     505             :                 ret=-1;
     506             : 
     507           1 :         pretty_print=save;
     508             : 
     509           1 :         return ret;
     510             : }
     511             : 
     512           1 : int json_send_warn(struct asfd *asfd, const char *msg)
     513             : {
     514           1 :         return json_send_msg(asfd, "warning", msg);
     515             : }

Generated by: LCOV version 1.13