LCOV - code coverage report
Current view: top level - src/client - diff.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 198 0.0 %
Date: 2015-10-31 Functions: 0 14 0.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../action.h"
       3             : #include "../alloc.h"
       4             : #include "../asfd.h"
       5             : #include "../attribs.h"
       6             : #include "../cmd.h"
       7             : #include "../log.h"
       8             : 
       9             : /* Note: The chars in this function are not the same as in the CMD_ set.
      10             :    These are for printing to the screen only. */
      11           0 : static char *encode_mode(mode_t mode, char *buf)
      12             : {
      13           0 :         char *cp=buf;
      14           0 :         *cp++=S_ISDIR(mode)?'d':S_ISBLK(mode)?'b':S_ISCHR(mode)?'c':
      15           0 :               S_ISLNK(mode)?'l':S_ISFIFO(mode)?'p':S_ISSOCK(mode)?'s':'-';
      16           0 :         *cp++=mode&S_IRUSR?'r':'-';
      17           0 :         *cp++=mode&S_IWUSR?'w':'-';
      18           0 :         *cp++=(mode&S_ISUID?(mode&S_IXUSR?'s':'S'):(mode&S_IXUSR?'x':'-'));
      19           0 :         *cp++=mode&S_IRGRP?'r':'-';
      20           0 :         *cp++=mode&S_IWGRP?'w':'-';
      21           0 :         *cp++=(mode&S_ISGID?(mode&S_IXGRP?'s':'S'):(mode&S_IXGRP?'x':'-'));
      22           0 :         *cp++=mode&S_IROTH?'r':'-';
      23           0 :         *cp++=mode&S_IWOTH?'w':'-';
      24           0 :         *cp++=(mode&S_ISVTX?(mode&S_IXOTH?'t':'T'):(mode&S_IXOTH?'x':'-'));
      25           0 :         *cp='\0';
      26           0 :         return cp;
      27             : }
      28             : 
      29           0 : static char *encode_time(uint64_t utime, char *buf)
      30             : {
      31             :         const struct tm *tm;
      32           0 :         int n=0;
      33           0 :         time_t time=utime;
      34             : 
      35             : #ifdef HAVE_WIN32
      36             :         /* Avoid a seg fault in Microsoft's CRT localtime_r(),
      37             :          *  which incorrectly references a NULL returned from gmtime() if
      38             :          *  time is negative before or after the timezone adjustment. */
      39             :         struct tm *gtm;
      40             : 
      41             :         if(!(gtm=gmtime(&time))) return buf;
      42             : 
      43             :         if(gtm->tm_year==1970 && gtm->tm_mon==1 && gtm->tm_mday<3) return buf;
      44             : #endif
      45             : 
      46           0 :         if((tm=localtime(&time)))
      47             :                 n=sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
      48             :                         tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
      49           0 :                         tm->tm_hour, tm->tm_min, tm->tm_sec);
      50           0 :         return buf+n;
      51             : }
      52             : 
      53           0 : static void diff_to_buf(char *lsbuf, struct sbuf *sb)
      54             : {
      55             :         int n;
      56             :         char *p;
      57             :         time_t time;
      58             :         const char *f;
      59           0 :         struct stat *statp=&sb->statp;
      60           0 :         *lsbuf='\0';
      61             : 
      62           0 :         p=encode_mode(statp->st_mode, lsbuf);
      63           0 :         n=sprintf(p, " %2d ", (uint32_t)statp->st_nlink);
      64           0 :         p+=n;
      65             :         n=sprintf(p, "%5d %5d", (uint32_t)statp->st_uid,
      66           0 :                 (uint32_t)statp->st_gid);
      67           0 :         p+=n;
      68           0 :         n=sprintf(p, " %7lu ", (unsigned long)statp->st_size);
      69           0 :         p+=n;
      70           0 :         if(statp->st_ctime>statp->st_mtime) time=statp->st_ctime;
      71           0 :         else time=statp->st_mtime;
      72             : 
      73             :         // Display most recent time.
      74           0 :         p=encode_time(time, p);
      75           0 :         *p++=' ';
      76           0 :         for(f=sb->path.buf; *f; ) *p++=*f++;
      77           0 :         *p=0;
      78           0 : }
      79             : 
      80           0 : static void diff_long_output(struct sbuf *sb)
      81             : {
      82             :         static char lsbuf[2048];
      83           0 :         diff_to_buf(lsbuf, sb);
      84           0 :         printf("%s", lsbuf);
      85           0 :         if(sb->link.buf) printf(" -> %s", sb->link.buf);
      86           0 :         printf("\n");
      87           0 : }
      88             : 
      89           0 : static char *json_escape(const char *str)
      90             : {
      91             :         int i;
      92             :         int j;
      93           0 :         int n=0;
      94           0 :         char *estr=NULL;
      95           0 :         const char echars[]="\\\"";
      96             : 
      97           0 :         if(!str) return NULL;
      98             : 
      99           0 :         n=strlen(str);
     100           0 :         if(!(estr=(char *)malloc_w(2*n*sizeof(char), __func__)))
     101           0 :                 return NULL;
     102           0 :         for(i=0, j=0; i<n; i++, j++)
     103             :         {
     104           0 :                 int k=sizeof(echars);
     105           0 :                 for(; k && str[i]!=echars[k-1]; k--);
     106           0 :                 if(k) estr[j++]='\\';
     107           0 :                 estr[j]=str[i];
     108             :         }
     109           0 :         estr[j]='\0';
     110           0 :         return estr;
     111             : }
     112             : 
     113             : static int current_tag=-1;
     114             : 
     115           0 : static void print_spaces(int count)
     116             : {
     117             :         static int i;
     118           0 :         for(i=0; i<count; i++) printf(" ");
     119           0 : }
     120             : 
     121           0 : static void close_tag(int level)
     122             : {
     123           0 :         for(; current_tag>=level; current_tag--)
     124             :         {
     125           0 :                 printf("\n");
     126           0 :                 print_spaces(current_tag);
     127           0 :                 printf("%c", current_tag%2?']':'}');
     128             :         }
     129           0 : }
     130             : 
     131           0 : static void open_tag(int level, const char *tag)
     132             : {
     133           0 :         if(current_tag>level)
     134             :         {
     135           0 :                 close_tag(level);
     136           0 :                 printf(",\n");
     137             :         }
     138           0 :         if(current_tag==level)
     139             :         {
     140           0 :                 printf("\n");
     141           0 :                 print_spaces(current_tag);
     142           0 :                 printf("},\n");
     143           0 :                 print_spaces(current_tag);
     144           0 :                 printf("{\n");
     145             :         }
     146           0 :         for(; current_tag<level; current_tag++)
     147             :         {
     148           0 :                 if(tag)
     149             :                 {
     150           0 :                         print_spaces(current_tag+1);
     151           0 :                         printf("\"%s\":\n", tag);
     152             :                 }
     153           0 :                 print_spaces(current_tag+1);
     154           0 :                 printf("%c\n", current_tag%2?'{':'[');
     155             :         }
     156           0 : }
     157             : 
     158           0 : static void diff_long_output_json(struct sbuf *sb)
     159             : {
     160             :         static char buf[2048];
     161           0 :         char *esc_fname=NULL;
     162           0 :         char *esc_lname=NULL;
     163           0 :         char *fname=sb->path.buf;
     164           0 :         char *lname=sb->link.buf;
     165           0 :         struct stat *statp=&sb->statp;
     166           0 :         *buf='\0';
     167             : 
     168           0 :         if(fname) esc_fname=json_escape(fname);
     169           0 :         if(lname) esc_lname=json_escape(lname);
     170           0 :         open_tag(4, NULL);
     171             :         printf( "     \"name\": \"%s\",\n"
     172             :                 "     \"link\": \"%s\",\n"
     173             :                 "     \"st_dev\": %lu,\n"
     174             :                 "     \"st_ino\": %lu,\n"
     175             :                 "     \"st_mode\": %u,\n"
     176             :                 "     \"st_nlink\": %lu,\n"
     177             :                 "     \"st_uid\": %u,\n"
     178             :                 "     \"st_gid\": %u,\n"
     179             :                 "     \"st_rdev\": %lu,\n"
     180             :                 "     \"st_size\": %ld,\n"
     181             :                 "     \"st_atime\": %ld,\n"
     182             :                 "     \"st_mtime\": %ld,\n"
     183             :                 "     \"st_ctime\": %ld",
     184             :                 esc_fname?esc_fname:"",
     185             :                 esc_lname?esc_lname:"",
     186             :                 (long unsigned int)statp->st_dev,
     187             :                 (long unsigned int)statp->st_ino,
     188             :                 (unsigned int)statp->st_mode,
     189             :                 (long unsigned int)statp->st_nlink,
     190             :                 (unsigned int)statp->st_uid,
     191             :                 (unsigned int)statp->st_gid,
     192             :                 (long unsigned int)statp->st_rdev,
     193             :                 (long int)statp->st_size,
     194             :                 (long int)statp->st_atime,
     195             :                 (long int)statp->st_mtime,
     196           0 :                 (long int)statp->st_ctime);
     197           0 :         if(esc_fname) free(esc_fname);
     198           0 :         if(esc_lname) free(esc_lname);
     199           0 : }
     200             : 
     201           0 : static void json_backup(char *statbuf, struct conf **confs)
     202             : {
     203           0 :         char *cp=NULL;
     204           0 :         if((cp=strstr(statbuf, " (deletable)")))
     205             :         {
     206           0 :                 *cp='\0';
     207           0 :                 cp++;
     208             :         }
     209             : 
     210           0 :         open_tag(2, NULL);
     211           0 :         printf("   \"timestamp\": \"%s\",\n", statbuf);
     212           0 :         printf("   \"deletable\": \"%s\"", cp?"true":"false");
     213             : 
     214           0 :         if(get_string(confs[OPT_BACKUP]))
     215             :         {
     216           0 :                 const char *browsedir=get_string(confs[OPT_BROWSEDIR]);
     217           0 :                 const char *regex=get_string(confs[OPT_REGEX]);
     218           0 :                 printf(",\n");
     219           0 :                 printf("   \"directory\": \"%s\",\n", browsedir?browsedir:"");
     220           0 :                 printf("   \"regex\": \"%s\",\n", regex?regex:"");
     221           0 :                 open_tag(3, "items");
     222             :         }
     223           0 : }
     224             : 
     225           0 : static void diff_short_output(struct sbuf *sb)
     226             : {
     227           0 :         printf("%s\n", sb->path.buf);
     228           0 : }
     229             : 
     230           0 : static void diff_short_output_json(struct sbuf *sb)
     231             : {
     232           0 :         open_tag(4, NULL);
     233           0 :         printf("     \"%s\"", sb->path.buf);
     234           0 : }
     235             : 
     236           0 : static void diff_item(int json, enum action act, struct sbuf *sb)
     237             : {
     238           0 :         if(act==ACTION_LIST_LONG)
     239             :         {
     240           0 :                 if(json) diff_long_output_json(sb);
     241           0 :                 else diff_long_output(sb);
     242             :         }
     243             :         else
     244             :         {
     245           0 :                 if(json) diff_short_output_json(sb);
     246           0 :                 else diff_short_output(sb);
     247             :         }
     248           0 : }
     249             : 
     250           0 : int do_diff_client(struct asfd *asfd,
     251             :         enum action act, int json, struct conf **confs)
     252             : {
     253           0 :         int ret=-1;
     254           0 :         char msg[512]="";
     255           0 :         char *dpth=NULL;
     256           0 :         struct sbuf *sb=NULL;
     257           0 :         int json_started=0;
     258           0 :         struct iobuf *rbuf=asfd->rbuf;
     259           0 :         const char *backup=get_string(confs[OPT_BACKUP]);
     260           0 :         const char *browsedir=get_string(confs[OPT_BROWSEDIR]);
     261           0 :         const char *regex=get_string(confs[OPT_REGEX]);
     262             : //logp("in do_diff\n");
     263             : 
     264           0 :         snprintf(msg, sizeof(msg), "diff %s", backup?backup:"");
     265           0 :         if(asfd->write_str(asfd, CMD_GEN, msg)
     266           0 :           || asfd->read_expect(asfd, CMD_GEN, "ok"))
     267           0 :                 goto end;
     268             : 
     269           0 :         if(!(sb=sbuf_alloc(get_protocol(confs)))) goto end;
     270           0 :         iobuf_init(&sb->path);
     271           0 :         iobuf_init(&sb->link);
     272           0 :         iobuf_init(&sb->attr);
     273             : 
     274           0 :         if(json)
     275             :         {
     276           0 :                 open_tag(0, NULL);
     277           0 :                 open_tag(1, "backups");
     278           0 :                 json_started++;
     279             :         }
     280             : 
     281             :         // This should probably should use the sbuf stuff.
     282             :         while(1)
     283             :         {
     284           0 :                 sbuf_free_content(sb);
     285             : 
     286           0 :                 iobuf_free_content(rbuf);
     287           0 :                 if(asfd->read(asfd)) break;
     288           0 :                 if(rbuf->cmd==CMD_TIMESTAMP)
     289             :                 {
     290             :                         // A backup timestamp, just print it.
     291           0 :                         if(json) json_backup(rbuf->buf, confs);
     292             :                         else
     293             :                         {
     294           0 :                                 printf("Backup: %s\n", rbuf->buf);
     295           0 :                                 if(browsedir)
     296             :                                         printf("Listing directory: %s\n",
     297           0 :                                                browsedir);
     298           0 :                                 if(regex)
     299             :                                         printf("With regex: %s\n",
     300           0 :                                                regex);
     301             :                         }
     302           0 :                         continue;
     303             :                 }
     304           0 :                 else if(rbuf->cmd!=CMD_ATTRIBS)
     305             :                 {
     306           0 :                         iobuf_log_unexpected(rbuf, __func__);
     307           0 :                         goto end;
     308             :                 }
     309           0 :                 iobuf_copy(&sb->attr, rbuf);
     310           0 :                 iobuf_init(rbuf);
     311             : 
     312           0 :                 attribs_decode(sb);
     313             : 
     314           0 :                 if(asfd->read(asfd))
     315             :                 {
     316           0 :                         logp("got stat without an object\n");
     317           0 :                         goto end;
     318             :                 }
     319           0 :                 iobuf_copy(&sb->path, rbuf);
     320           0 :                 iobuf_init(rbuf);
     321             : 
     322           0 :                 if(sb->path.cmd==CMD_DIRECTORY
     323           0 :                         || sb->path.cmd==CMD_FILE
     324           0 :                         || sb->path.cmd==CMD_ENC_FILE
     325           0 :                         || sb->path.cmd==CMD_EFS_FILE
     326           0 :                         || sb->path.cmd==CMD_SPECIAL)
     327             :                 {
     328           0 :                         diff_item(json, act, sb);
     329             :                 }
     330           0 :                 else if(cmd_is_link(sb->path.cmd)) // symlink or hardlink
     331             :                 {
     332           0 :                         if(asfd->read(asfd)
     333           0 :                           || rbuf->cmd!=sb->path.cmd)
     334             :                         {
     335             :                                 logp("could not get link %c:%s\n",
     336           0 :                                         sb->path.cmd, sb->path.buf);
     337           0 :                                 goto end;
     338             :                         }
     339           0 :                         iobuf_copy(&sb->link, rbuf);
     340           0 :                         iobuf_init(rbuf);
     341           0 :                         diff_item(json, act, sb);
     342             :                 }
     343             :                 else
     344             :                 {
     345             :                         fprintf(stderr, "undiffable %c:%s\n",
     346           0 :                                 sb->path.cmd, sb->path.buf?sb->path.buf:"");
     347             :                 }
     348             :         }
     349             : 
     350           0 :         ret=0;
     351             : end:
     352           0 :         if(json && json_started) close_tag(0);
     353           0 :         printf("\n");
     354           0 :         iobuf_free_content(&sb->path);
     355           0 :         iobuf_free_content(&sb->link);
     356           0 :         iobuf_free_content(&sb->attr);
     357           0 :         if(dpth) free(dpth);
     358           0 :         sbuf_free(&sb);
     359           0 :         if(!ret) logp("List finished ok\n");
     360           0 :         return ret;
     361             : }

Generated by: LCOV version 1.10