LCOV - code coverage report
Current view: top level - src/server - run_action.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 201 278 72.3 %
Date: 2021-05-02 03:18:47 Functions: 13 15 86.7 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../action.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../cmd.h"
       6             : #include "../cntr.h"
       7             : #include "../handy.h"
       8             : #include "../fsops.h"
       9             : #include "../iobuf.h"
      10             : #include "../lock.h"
      11             : #include "../log.h"
      12             : #include "../regexp.h"
      13             : #include "../run_script.h"
      14             : #include "main.h"
      15             : #include "backup.h"
      16             : #include "delete.h"
      17             : #include "diff.h"
      18             : #include "list.h"
      19             : #include "protocol2/restore.h"
      20             : #include "restore.h"
      21             : #include "rubble.h"
      22             : #include "sdirs.h"
      23             : #include "run_action.h"
      24             : #include "timestamp.h"
      25             : 
      26             : // FIX THIS: Somewhat haphazard.
      27             : /* Return 0 for everything OK. -1 for error, or 1 to mean that there was
      28             :    another process that has the lock. */
      29           2 : static int get_lock_sdirs_for_write(struct asfd *asfd, struct sdirs *sdirs)
      30             : {
      31             :         struct stat statp;
      32             : 
      33             :         // Make sure the lock directory exists.
      34           2 :         if(mkpath(&sdirs->lock_storage_for_write->path, sdirs->lockdir))
      35             :         {
      36           0 :                 asfd->write_str(asfd, CMD_ERROR, "problem with lock directory");
      37           0 :                 goto error;
      38             :         }
      39             : 
      40           2 :         lock_get(sdirs->lock_storage_for_write);
      41           2 :         switch(sdirs->lock_storage_for_write->status)
      42             :         {
      43             :                 case GET_LOCK_GOT: break;
      44             :                 case GET_LOCK_NOT_GOT:
      45           0 :                         if(!lstat(sdirs->finishing, &statp))
      46             :                         {
      47           0 :                                 char msg[256]="";
      48           0 :                                 logp("finalising previous backup\n");
      49           0 :                                 snprintf(msg, sizeof(msg),
      50             :                                         "Finalising previous backup of client. "
      51             :                                         "Please try again later.");
      52           0 :                                 asfd->write_str(asfd, CMD_ERROR, msg);
      53             :                         }
      54             :                         else
      55             :                         {
      56           0 :                                 logp("Another instance of client is already running.\n");
      57           0 :                                 asfd->write_str(asfd, CMD_ERROR,
      58             :                                         "another instance is already running");
      59             :                         }
      60             :                         goto lockedout;
      61             :                 case GET_LOCK_ERROR:
      62             :                 default:
      63           0 :                         logp("Problem with lock file on server: %s\n",
      64             :                                 sdirs->lock_storage_for_write->path);
      65           0 :                         asfd->write_str(asfd, CMD_ERROR,
      66             :                                 "problem with lock file on server");
      67           0 :                         goto error;
      68             :         }
      69             : 
      70             :         return 0;
      71             : lockedout:
      72             :         return 1;
      73             : error:
      74             :         return -1;
      75             : }
      76             : 
      77             : static int client_can_generic(struct conf **cconfs, enum conf_opt o)
      78             : {
      79           5 :         return get_int(cconfs[o]);
      80             : }
      81             : 
      82           0 : int client_can_monitor(struct conf **cconfs)
      83             : {
      84           0 :         return client_can_generic(cconfs, OPT_CLIENT_CAN_MONITOR);
      85             : }
      86             : 
      87           1 : static int client_can_restore(struct conf **cconfs)
      88             : {
      89           1 :         const char *restore_path=get_string(cconfs[OPT_RESTORE_PATH]);
      90             : 
      91             :         // If there is a restore file on the server, it is always OK.
      92           1 :         if(restore_path && is_reg_lstat(restore_path)==1)
      93             :         {
      94             :                 // Remove the file.
      95           0 :                 unlink(restore_path);
      96           0 :                 return 1;
      97             :         }
      98             : 
      99           1 :         return client_can_generic(cconfs, OPT_CLIENT_CAN_RESTORE);
     100             : }
     101             : 
     102           1 : void maybe_do_notification(struct asfd *asfd,
     103             :         int status, const char *clientdir,
     104             :         const char *storagedir, const char *filename,
     105             :         const char *brv, struct conf **cconfs)
     106             : {
     107           1 :         int a=0;
     108             :         const char *args[12];
     109           1 :         struct cntr *cntr=get_cntr(cconfs);
     110           1 :         args[a++]=NULL; // Fill in the script name later.
     111           1 :         args[a++]=get_string(cconfs[OPT_CNAME]);
     112           1 :         args[a++]=clientdir;
     113           1 :         args[a++]=storagedir;
     114           1 :         args[a++]=filename;
     115           1 :         args[a++]=brv;
     116           1 :         if(status)
     117             :         {
     118           1 :                 args[0]=get_string(cconfs[OPT_N_FAILURE_SCRIPT]);
     119           1 :                 args[a++]="0";
     120           1 :                 args[a++]=NULL;
     121           1 :                 run_script(asfd, args, get_strlist(cconfs[OPT_N_FAILURE_ARG]),
     122             :                         cconfs, 1, 1, 1);
     123             :         }
     124           0 :         else if((get_int(cconfs[OPT_N_SUCCESS_WARNINGS_ONLY])
     125           0 :                 && cntr->ent[CMD_WARNING]->count > 0)
     126           0 :           || (get_int(cconfs[OPT_N_SUCCESS_CHANGES_ONLY])
     127           0 :                 && cntr->ent[CMD_TOTAL]->changed > 0)
     128           0 :           || (!get_int(cconfs[OPT_N_SUCCESS_WARNINGS_ONLY])
     129           0 :                 && !get_int(cconfs[OPT_N_SUCCESS_CHANGES_ONLY])))
     130             :         {
     131           0 :                 char warnings[32]="";
     132           0 :                 snprintf(warnings, sizeof(warnings), "%" PRIu64,
     133           0 :                         cntr->ent[CMD_WARNING]->count);
     134           0 :                 args[0]=get_string(cconfs[OPT_N_SUCCESS_SCRIPT]);
     135           0 :                 args[a++]=warnings;
     136           0 :                 args[a++]=NULL;
     137           0 :                 run_script(asfd, args, get_strlist(cconfs[OPT_N_SUCCESS_ARG]),
     138             :                         cconfs, 1, 1, 1);
     139             :         }
     140           1 : }
     141             : 
     142          18 : static int parse_restore_str(
     143             :         const char *str,
     144             :         enum action *act,
     145             :         int *input,
     146             :         char **backupnostr,
     147             :         char **restoreregex
     148             : ) {
     149          18 :         int ret=-1;
     150          18 :         char *cp=NULL;
     151          18 :         char *copy=NULL;
     152             : 
     153          18 :         if(!str)
     154             :         {
     155           1 :                 logp("NULL passed to %s\n", __func__);
     156           1 :                 goto end;
     157             :         }
     158             : 
     159          17 :         if(!(copy=strdup_w(str, __func__)))
     160             :                 goto end;
     161             : 
     162          17 :         if(!strncmp_w(copy, "restore "))
     163           7 :                 *act=ACTION_RESTORE;
     164          10 :         else if(!strncmp_w(copy, "verify "))
     165           7 :                 *act=ACTION_VERIFY;
     166             :         else
     167             :         {
     168           3 :                 logp("Could not parse %s in %s\n", copy, __func__);
     169           3 :                 goto end;
     170             :         }
     171             : 
     172          14 :         if(!(cp=strchr(copy, ' ')))
     173             :         {
     174           0 :                 logp("Could not parse %s in %s\n", copy, __func__);
     175           0 :                 goto end;
     176             :         }
     177          14 :         cp++;
     178          14 :         *input=0;
     179          14 :         if(!strncmp_w(cp, "restore_list "))
     180             :         {
     181           6 :                 cp+=strlen("restore_list ");
     182           6 :                 *input=1;
     183             :         }
     184          14 :         if(!(*backupnostr=strdup_w(cp, __func__)))
     185             :                 goto end;
     186          14 :         if((cp=strchr(*backupnostr, ':')))
     187             :         {
     188           8 :                 *cp='\0';
     189           8 :                 cp++;
     190           8 :                 if(!(*restoreregex=strdup_w(cp, __func__)))
     191             :                         goto end;
     192             :         }
     193             : 
     194             :         ret=0;
     195             : end:
     196          18 :         free_w(&copy);
     197          18 :         return ret;
     198             : }
     199             : 
     200             : #ifndef UTEST
     201             : static
     202             : #endif
     203          18 : int parse_restore_str_and_set_confs(const char *str, enum action *act,
     204             :         struct conf **cconfs)
     205             : {
     206          18 :         int ret=-1;
     207          18 :         int input=0;
     208          18 :         char *backupnostr=NULL;
     209          18 :         char *restoreregex=NULL;
     210             : 
     211          18 :         if(parse_restore_str(str, act, &input, &backupnostr, &restoreregex))
     212             :                 goto end;
     213             : 
     214          14 :         if(set_string(cconfs[OPT_RESTORE_LIST], input?"":NULL))
     215             :                 goto end;
     216          14 :         if(set_string(cconfs[OPT_BACKUP], backupnostr))
     217             :                 goto end;
     218          14 :         if(restoreregex && *restoreregex
     219           4 :           && set_string(cconfs[OPT_REGEX], restoreregex))
     220             :                 goto end;
     221             :         ret=0;
     222             : end:
     223          18 :         free_w(&backupnostr);
     224          18 :         free_w(&restoreregex);
     225          18 :         return ret;
     226             : }
     227             : 
     228           2 : static int run_restore(struct asfd *asfd,
     229             :         struct sdirs *sdirs, struct conf **cconfs, int srestore)
     230             : {
     231           2 :         int ret=-1;
     232           2 :         char *dir_for_notify=NULL;
     233           2 :         enum action act=ACTION_RESTORE;
     234           2 :         struct iobuf *rbuf=asfd->rbuf;
     235           2 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     236             : 
     237           2 :         if(parse_restore_str_and_set_confs(rbuf->buf, &act, cconfs))
     238             :                 goto end;
     239             : 
     240           2 :         iobuf_free_content(rbuf);
     241             : 
     242           2 :         if(act==ACTION_RESTORE)
     243             :         {
     244             :                 int r;
     245           1 :                 if((r=client_can_restore(cconfs))<0)
     246             :                         goto end;
     247           1 :                 else if(!r)
     248             :                 {
     249           0 :                         logp("Not allowing restore of %s\n", cname);
     250           0 :                         if(!asfd->write_str(asfd, CMD_GEN,
     251           0 :                                 "Client restore is not allowed")) ret=0;
     252             :                         goto end;
     253             :                 }
     254             :         }
     255           2 :         if(act==ACTION_VERIFY
     256           1 :           && !(client_can_generic(cconfs, OPT_CLIENT_CAN_VERIFY)))
     257             :         {
     258           0 :                 logp("Not allowing verify of %s\n", cname);
     259           0 :                 if(!asfd->write_str(asfd, CMD_GEN,
     260           0 :                         "Client verify is not allowed")) ret=0;
     261             :                 goto end;
     262             :         }
     263             : 
     264           2 :         if(get_string(cconfs[OPT_RESTORE_LIST]))
     265             :         {
     266             :                 // Should start receiving the input file here.
     267           0 :                 if(asfd->write_str(asfd, CMD_GEN, "ok restore_list"))
     268             :                         goto end;
     269           0 :                 if(receive_a_file(asfd, sdirs->restore_list, get_cntr(cconfs)))
     270             :                 {
     271             :                         goto end;
     272             :                 }
     273             :         }
     274             :         else
     275             :         {
     276           2 :                 if(asfd->write_str(asfd, CMD_GEN, "ok"))
     277             :                         goto end;
     278             :         }
     279             : 
     280           2 :         ret=do_restore_server(asfd, sdirs, act,
     281             :                 srestore, &dir_for_notify, cconfs);
     282           2 :         if(dir_for_notify)
     283           0 :                 maybe_do_notification(asfd, ret,
     284           0 :                         sdirs->client, dir_for_notify,
     285             :                         act==ACTION_RESTORE?"restorelog":"verifylog",
     286           0 :                         act==ACTION_RESTORE?"restore":"verify",
     287             :                         cconfs);
     288             : end:
     289           2 :         free_w(&dir_for_notify);
     290           2 :         return ret;
     291             : }
     292             : 
     293           1 : static int run_delete(struct asfd *asfd,
     294             :         struct sdirs *sdirs, struct conf **cconfs)
     295             : {
     296           1 :         char *backupno=NULL;
     297           1 :         struct iobuf *rbuf=asfd->rbuf;
     298           1 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     299           1 :         if(!client_can_generic(cconfs, OPT_CLIENT_CAN_DELETE))
     300             :         {
     301           0 :                 logp("Not allowing delete of %s\n", cname);
     302           0 :                 asfd->write_str(asfd, CMD_GEN, "Client delete is not allowed");
     303           0 :                 return -1;
     304             :         }
     305           1 :         backupno=rbuf->buf+strlen("delete ");
     306           1 :         return do_delete_server(asfd, sdirs,
     307             :                 cconfs, cname, backupno,
     308           1 :                 get_string(cconfs[OPT_MANUAL_DELETE]));
     309             : }
     310             : 
     311           1 : static int run_list(struct asfd *asfd,
     312             :         struct sdirs *sdirs, struct conf **cconfs)
     313             : {
     314           1 :         int ret=-1;
     315           1 :         char *cp=NULL;
     316           1 :         char *backupno=NULL;
     317           1 :         char *browsedir=NULL;
     318           1 :         char *listregex=NULL;
     319           1 :         struct iobuf *rbuf=asfd->rbuf;
     320             : 
     321           1 :         if(!client_can_generic(cconfs, OPT_CLIENT_CAN_LIST))
     322             :         {
     323           0 :                 logp("Not allowing list of %s\n",
     324             :                         get_string(cconfs[OPT_CNAME]));
     325           0 :                 asfd->write_str(asfd, CMD_GEN, "Client list is not allowed");
     326           0 :                 goto end;
     327             :         }
     328             : 
     329           1 :         if(!strncmp_w(rbuf->buf, "list "))
     330             :         {
     331           1 :                 if((cp=strchr(rbuf->buf, ':')))
     332             :                 {
     333           0 :                         *cp='\0';
     334           0 :                         if(!(listregex=strdup_w(cp+1, __func__)))
     335             :                                 goto end;
     336             :                 }
     337           1 :                 if(!(backupno=strdup_w(rbuf->buf+strlen("list "), __func__)))
     338             :                         goto end;
     339             :                 
     340             :         }
     341           0 :         else if(!strncmp_w(rbuf->buf, "listb "))
     342             :         {
     343           0 :                 if((cp=strchr(rbuf->buf, ':')))
     344             :                 {
     345           0 :                         *cp='\0';
     346           0 :                         if(!(browsedir=strdup_w(cp+1, __func__)))
     347             :                                 goto end;
     348             :                 }
     349           0 :                 strip_trailing_slashes(&browsedir);
     350           0 :                 if(!(backupno=strdup_w(rbuf->buf+strlen("listb "), __func__)))
     351             :                         goto end;
     352             :         }
     353           1 :         if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;
     354             : 
     355           1 :         iobuf_free_content(asfd->rbuf);
     356             : 
     357           1 :         if(list_server_init(asfd, sdirs, cconfs,
     358             :                 get_protocol(cconfs), backupno, listregex, browsedir))
     359             :                         goto end;
     360           1 :         ret=do_list_server();
     361             : end:
     362           1 :         free_w(&backupno);
     363           1 :         free_w(&browsedir);
     364           1 :         free_w(&listregex);
     365           1 :         list_server_free();
     366           1 :         return ret;
     367             : }
     368             : 
     369           1 : static int run_diff(struct asfd *asfd,
     370             :         struct sdirs *sdirs, struct conf **cconfs)
     371             : {
     372           1 :         int ret=-1;
     373           1 :         char *backup1=NULL;
     374           1 :         char *backup2=NULL;
     375           1 :         struct iobuf *rbuf=asfd->rbuf;
     376             : 
     377           1 :         if(!client_can_generic(cconfs, OPT_CLIENT_CAN_DIFF))
     378             :         {
     379           0 :                 logp("Not allowing diff of %s\n",
     380             :                         get_string(cconfs[OPT_CNAME]));
     381           0 :                 asfd->write_str(asfd, CMD_GEN, "Client diff is not allowed");
     382           0 :                 goto end;
     383             :         }
     384             : 
     385           1 :         if(!strncmp_w(rbuf->buf, "diff "))
     386             :         {
     387             :                 char *cp;
     388           1 :                 if((cp=strchr(rbuf->buf, ':')))
     389             :                 {
     390           0 :                         *cp='\0';
     391           0 :                         if(!(backup2=strdup_w(cp+1, __func__)))
     392             :                                 goto end;
     393             :                 }
     394           1 :                 if(!(backup1=strdup_w(rbuf->buf+strlen("diff "), __func__)))
     395             :                         goto end;
     396             :         }
     397           1 :         if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;
     398             : 
     399           1 :         iobuf_free_content(asfd->rbuf);
     400             : 
     401           1 :         ret=do_diff_server(asfd, sdirs,
     402             :                 cconfs, get_protocol(cconfs), backup1, backup2);
     403             : end:
     404           1 :         free_w(&backup1);
     405           1 :         free_w(&backup2);
     406           1 :         return ret;
     407             : }
     408             : 
     409             : static int unknown_command(struct asfd *asfd, const char *func)
     410             : {
     411           2 :         iobuf_log_unexpected(asfd->rbuf, func);
     412           2 :         asfd->write_str(asfd, CMD_ERROR, "unknown command");
     413             :         return -1;
     414             : }
     415             : 
     416           0 : static const char *buf_to_notify_str(struct iobuf *rbuf)
     417             : {
     418           0 :         const char *buf=rbuf->buf;
     419           0 :         if(!strncmp_w(buf, "backup")) return "backup";
     420           0 :         else if(!strncmp_w(buf, "delete")) return "delete";
     421           0 :         else if(!strncmp_w(buf, "diff")) return "diff";
     422           0 :         else if(!strncmp_w(buf, "list")) return "list";
     423           0 :         else if(!strncmp_w(buf, "restore")) return "restore";
     424           0 :         else if(!strncmp_w(buf, "verify")) return "verify";
     425             :         else return "unknown";
     426             : }
     427             : 
     428           9 : static int maybe_write_first_created_file(struct sdirs *sdirs,
     429             :         const char *tstmp)
     430             : {
     431           9 :         if(is_reg_lstat(sdirs->created)>0
     432           9 :           || is_lnk_lstat(sdirs->current)>0
     433           9 :           || is_lnk_lstat(sdirs->currenttmp)>0
     434           9 :           || is_lnk_lstat(sdirs->working)>0
     435           9 :           || is_lnk_lstat(sdirs->finishing)>0)
     436             :                 return 0;
     437             : 
     438           9 :         return timestamp_write(sdirs->created, tstmp);
     439             : }
     440             : 
     441           9 : static int log_command(struct async *as,
     442             :         struct sdirs *sdirs, struct conf **cconfs, const char *tstmp)
     443             : {
     444           9 :         struct fzp *fzp=NULL;
     445           9 :         struct asfd *asfd=as->asfd;
     446           9 :         struct iobuf *rbuf=asfd->rbuf;
     447           9 :         char *cname=get_string(cconfs[OPT_CONNECT_CLIENT]);
     448             : 
     449           9 :         if(rbuf->cmd!=CMD_GEN)
     450             :                 return 0;
     451             : 
     452           8 :         if(!(fzp=fzp_open(sdirs->command, "a")))
     453             :                 return -1;
     454           8 :         fzp_printf(fzp, "%s %s %s %s\n", tstmp, asfd->peer_addr, cname,
     455             :                 iobuf_to_printable(rbuf));
     456           8 :         if(fzp_close(&fzp))
     457             :                 return -1;
     458             : 
     459             :         return 0;
     460             : }
     461             : 
     462          10 : static int run_action_server_do(struct async *as, struct sdirs *sdirs,
     463             :         const char *incexc, int srestore, int *timer_ret, struct conf **cconfs)
     464             : {
     465             :         int max_parallel_backups;
     466          10 :         int working=0;
     467             :         int ret;
     468          10 :         int resume=0;
     469          10 :         char msg[256]="";
     470          10 :         char tstmp[48]="";
     471          10 :         struct iobuf *rbuf=as->asfd->rbuf;
     472             : 
     473             :         // Make sure some directories exist.
     474          10 :         if(mkpath(&sdirs->current, sdirs->dedup))
     475             :         {
     476           1 :                 snprintf(msg, sizeof(msg),
     477             :                         "could not mkpath %s", sdirs->current);
     478           1 :                 log_and_send(as->asfd, msg);
     479           1 :                 return -1;
     480             :         }
     481             : 
     482           9 :         if(timestamp_get_new(/*index*/0,
     483             :                 tstmp, sizeof(tstmp),
     484             :                 /*bufforfile*/NULL, /*bs*/0,
     485             :                 /*format*/NULL))
     486             :                         return -1;
     487             : 
     488             :         // Carry on if these fail, otherwise you will not be able to restore
     489             :         // from readonly backups.
     490           9 :         maybe_write_first_created_file(sdirs, tstmp);
     491           9 :         log_command(as, sdirs, cconfs, tstmp);
     492             : 
     493           9 :         if(rbuf->cmd!=CMD_GEN)
     494           2 :                 return unknown_command(as->asfd, __func__);
     495             : 
     496             :         // List and diff should work well enough without needing to lock
     497             :         // anything.
     498           8 :         if(!strncmp_w(rbuf->buf, "list ")
     499           7 :           || !strncmp_w(rbuf->buf, "listb "))
     500           1 :                 return run_list(as->asfd, sdirs, cconfs);
     501             : 
     502           7 :         if(!strncmp_w(rbuf->buf, "diff "))
     503           1 :                 return run_diff(as->asfd, sdirs, cconfs);
     504             : 
     505             :         // Old clients will send 'delete', possibly accidentally due to the
     506             :         // user trying to use the new diff/long diff options.
     507             :         // Stop them from working, just to be safe.
     508           6 :         if(!strncmp_w(rbuf->buf, "delete "))
     509             :         {
     510           1 :                 logp("old style delete from %s denied\n",
     511             :                         get_string(cconfs[OPT_CNAME]));
     512           1 :                 as->asfd->write_str(as->asfd, CMD_ERROR,
     513             :                         "old style delete is not supported on this server");
     514           1 :                 return -1;
     515             :         }
     516             : 
     517             :         // Restore and verify should work well enough by locking only the
     518             :         // backup directory they are interested in.
     519           5 :         if(!strncmp_w(rbuf->buf, "restore ")
     520           4 :           || !strncmp_w(rbuf->buf, "verify "))
     521             :         {
     522           2 :                 ret=run_restore(as->asfd, sdirs, cconfs, srestore);
     523           2 :                 unlink(sdirs->restore_list);
     524           2 :                 return ret;
     525             :         }
     526             : 
     527           3 :         if(strncmp_w(rbuf->buf, "backup")
     528           2 :           && strncmp_w(rbuf->buf, "Delete "))
     529           2 :                 return unknown_command(as->asfd, __func__);
     530             : 
     531             :         // Beyond this point, only need to deal with backup and delete.
     532             :         // These require locking out all other backups and deletes.
     533             : 
     534           2 :         switch((ret=get_lock_sdirs_for_write(as->asfd, sdirs)))
     535             :         {
     536             :                 case 0: break; // OK.
     537             :                 case 1: return 1; // Locked out.
     538             :                 default: // Error.
     539           0 :                         maybe_do_notification(as->asfd, ret,
     540             :                                 "", "error in get_lock_sdirs()",
     541             :                                 "", buf_to_notify_str(rbuf), cconfs);
     542           0 :                         return -1;
     543             :         }
     544             : 
     545           2 :         switch((ret=check_for_rubble_and_clean(as, sdirs,
     546             :                 incexc, &resume, cconfs)))
     547             :         {
     548             :                 case 0: break; // OK.
     549             :                 case 1: return 1; // Now finalising.
     550             :                 default: // Error.
     551           0 :                         maybe_do_notification(as->asfd, ret,
     552             :                                 "", "error in check_for_rubble()",
     553             :                                 "", buf_to_notify_str(rbuf), cconfs);
     554           0 :                         return -1;
     555             :         }
     556             : 
     557           2 :         if(!strncmp_w(rbuf->buf, "Delete "))
     558           1 :                 return run_delete(as->asfd, sdirs, cconfs);
     559             : 
     560             :         // Only backup action left to deal with.
     561           1 :         working = server_get_working(NULL);
     562           1 :         max_parallel_backups = get_int(cconfs[OPT_MAX_PARALLEL_BACKUPS]);
     563             : 
     564           1 :         logp("%d/%d working (cur/max)\n", working, max_parallel_backups);
     565             : 
     566           1 :         if(max_parallel_backups && working >= max_parallel_backups)
     567             :         {
     568           0 :                 struct asfd *asfd=as->asfd;
     569           0 :                 logp("max parallel backups reached\n");
     570           0 :                 return asfd->write_str(asfd, CMD_GEN, "max parallel backups");
     571             :         }
     572             : 
     573           1 :         ret=run_backup(as, sdirs,
     574             :                 cconfs, incexc, timer_ret, resume);
     575             : 
     576             :         // If this is a backup failure and the client has more servers
     577             :         // to failover to, do not notify.
     578           1 :         if(ret
     579           1 :           && get_int(cconfs[OPT_N_FAILURE_BACKUP_FAILOVERS_LEFT])
     580           1 :           && get_int(cconfs[OPT_BACKUP_FAILOVERS_LEFT]))
     581             :                 return ret;
     582             : 
     583           1 :         if(*timer_ret<0)
     584           0 :                 maybe_do_notification(as->asfd, ret,
     585             :                         "", "error running timer script",
     586             :                         "", "backup", cconfs);
     587           1 :         else if(!*timer_ret)
     588           1 :                 maybe_do_notification(as->asfd, ret,
     589           1 :                         sdirs->client, sdirs->current,
     590             :                         "log", "backup", cconfs);
     591             :         return ret;
     592             : }
     593             : 
     594          10 : int run_action_server(struct async *as,
     595             :         const char *incexc, int srestore, int *timer_ret, struct conf **cconfs)
     596             : {
     597          10 :         int ret=-1;
     598          10 :         struct sdirs *sdirs=NULL;
     599          10 :         if((sdirs=sdirs_alloc())
     600          10 :           && !sdirs_init_from_confs(sdirs, cconfs))
     601          10 :                 ret=run_action_server_do(as,
     602             :                         sdirs, incexc, srestore, timer_ret, cconfs);
     603          10 :         if(sdirs) lock_release(sdirs->lock_storage_for_write);
     604          10 :         sdirs_free(&sdirs);
     605          10 :         return ret;
     606             : }

Generated by: LCOV version 1.13