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

Generated by: LCOV version 1.10