]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/3.0.2-accurate.patch
Fix link rules
[bacula/bacula] / bacula / patches / 3.0.2-accurate.patch
1
2  This patch can be applied to version 3.0.2 and fixes
3  bug #1355 'bacula director crashes with double free
4  in Accurate SQL query'
5
6  Apply it to version 3.0.2 with:
7
8  cd <bacula-source>
9  patch -p2 <3.0.2-accurate.patch
10  ./configure <your-options>
11  make
12  ...
13  make install
14
15
16 diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h
17 index 2ff803f..be07e84 100644
18 --- a/bacula/src/cats/cats.h
19 +++ b/bacula/src/cats/cats.h
20 @@ -1037,6 +1037,16 @@ struct db_int64_ctx {
21     int count;                         /* number of values seen */
22  };
23  
24 +/* Call back context for getting a list of comma separated strings from the database */
25 +class db_list_ctx {
26 +public:
27 +   POOLMEM *list;                     /* list */
28 +   int count;                         /* number of values seen */
29 +
30 +   db_list_ctx() { list = get_pool_memory(PM_FNAME); *list = 0; count = 0; }
31 +   ~db_list_ctx() { free_pool_memory(list); list = NULL; }
32 +};
33 +
34  
35  #include "protos.h"
36  #include "jcr.h"
37 diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h
38 index ea03a3c..565526a 100644
39 --- a/bacula/src/cats/protos.h
40 +++ b/bacula/src/cats/protos.h
41 @@ -1,7 +1,7 @@
42  /*
43     Bacula® - The Network Backup Solution
44  
45 -   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
46 +   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
47  
48     The main author of Bacula is Kern Sibbald, with contributions from
49     many others, a complete list can be found in the file AUTHORS.
50 @@ -57,6 +57,7 @@ bool db_sql_query(B_DB *mdb, const char *cmd, DB_RESULT_HANDLER *result_handler,
51  void db_start_transaction(JCR *jcr, B_DB *mdb);
52  void db_end_transaction(JCR *jcr, B_DB *mdb);
53  int db_int64_handler(void *ctx, int num_fields, char **row);
54 +int db_list_handler(void *ctx, int num_fields, char **row);
55  void db_thread_cleanup();
56  void _dbg_print_db(JCR *jcr, FILE *fp);
57  
58 @@ -106,8 +107,8 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr);
59  int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
60  bool db_get_query_dbids(JCR *jcr, B_DB *mdb, POOL_MEM &query, dbid_list &ids);
61  bool db_get_file_list(JCR *jcr, B_DB *mdb, char *jobids, DB_RESULT_HANDLER *result_handler, void *ctx);
62 -bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *jobids);
63 -int db_get_int_handler(void *ctx, int num_fields, char **row);
64 +bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, JOB_DBR *jr, db_list_ctx *jobids);
65 +int db_get_int_handler(void *list, int num_fields, char **row);
66  
67  
68  /* sql_list.c */
69 diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c
70 index 324d017..e698b5a 100644
71 --- a/bacula/src/cats/sql.c
72 +++ b/bacula/src/cats/sql.c
73 @@ -144,7 +144,21 @@ int db_int64_handler(void *ctx, int num_fields, char **row)
74     return 0;
75  }
76  
77 -
78 +/*
79 + * Use to build a comma separated list of values from a query. "10,20,30"
80 + */
81 +int db_list_handler(void *ctx, int num_fields, char **row)
82 +{
83 +   db_list_ctx *lctx = (db_list_ctx *)ctx;
84 +   if (num_fields == 1 && row[0]) {
85 +      if (lctx->list[0]) {
86 +         pm_strcat(lctx->list, ",");
87 +      }
88 +      pm_strcat(lctx->list, row[0]);
89 +      lctx->count++;
90 +   }
91 +   return 0;
92 +}
93  
94  /* NOTE!!! The following routines expect that the
95   *  calling subroutine sets and clears the mutex
96 diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c
97 index b9d25bb..62cd07c 100644
98 --- a/bacula/src/cats/sql_get.c
99 +++ b/bacula/src/cats/sql_get.c
100 @@ -1,7 +1,7 @@
101  /*
102     Bacula® - The Network Backup Solution
103  
104 -   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
105 +   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
106  
107     The main author of Bacula is Kern Sibbald, with contributions from
108     many others, a complete list can be found in the file AUTHORS.
109 @@ -1100,7 +1100,7 @@ bool db_get_file_list(JCR *jcr, B_DB *mdb, char *jobids,
110   * TODO: look and merge from ua_restore.c
111   */
112  bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, 
113 -                            JOB_DBR *jr, POOLMEM *jobids)
114 +                            JOB_DBR *jr, db_list_ctx *jobids)
115  {
116     bool ret=false;
117     char clientid[50], jobid[50], filesetid[50];
118 @@ -1111,7 +1111,8 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb,
119     time_t StartTime = (jr->StartTime)?jr->StartTime:time(NULL);
120  
121     bstrutime(date, sizeof(date),  StartTime + 1);
122 -   jobids[0]='\0';
123 +   jobids->list[0] = 0;
124 +   jobids->count = 0;
125  
126     /* First, find the last good Full backup for this job/client/fileset */
127     Mmsg(query, 
128 @@ -1177,8 +1178,8 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb,
129  
130     /* build a jobid list ie: 1,2,3,4 */
131     Mmsg(query, "SELECT JobId FROM btemp3%s ORDER by JobTDate", jobid);
132 -   db_sql_query(mdb, query.c_str(), db_get_int_handler, jobids);
133 -   Dmsg1(1, "db_accurate_get_jobids=%s\n", jobids);
134 +   db_sql_query(mdb, query.c_str(), db_list_handler, jobids);
135 +   Dmsg1(1, "db_accurate_get_jobids=%s\n", jobids->list);
136     ret = true;
137  
138  bail_out:
139 @@ -1188,19 +1189,4 @@ bail_out:
140     return ret;
141  }
142  
143 -/*
144 - * Use to build a string of int list from a query. "10,20,30"
145 - */
146 -int db_get_int_handler(void *ctx, int num_fields, char **row)
147 -{
148 -   POOLMEM *ret = (POOLMEM *)ctx;
149 -   if (num_fields == 1) {
150 -      if (ret[0]) {
151 -         pm_strcat(ret, ",");
152 -      }
153 -      pm_strcat(ret, row[0]);
154 -   }
155 -   return 0;
156 -}
157 -
158  #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI */
159 diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c
160 index 029dfa0..1837a6b 100644
161 --- a/bacula/src/dird/backup.c
162 +++ b/bacula/src/dird/backup.c
163 @@ -131,42 +131,37 @@ static int accurate_list_handler(void *ctx, int num_fields, char **row)
164  bool send_accurate_current_files(JCR *jcr)
165  {
166     POOL_MEM buf;
167 +   db_list_ctx jobids;
168 +   db_list_ctx nb;
169  
170     if (!jcr->accurate || job_canceled(jcr) || jcr->get_JobLevel()==L_FULL) {
171        return true;
172     }
173 -   POOLMEM *jobids = get_pool_memory(PM_FNAME);
174  
175 -   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids);
176 -
177 -   if (*jobids == 0) {
178 -      free_pool_memory(jobids);
179 +   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids);
180 +   if (jobids.count == 0) {
181        Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
182        return false;
183     }
184 +
185     if (jcr->JobId) {            /* display the message only for real jobs */
186        Jmsg(jcr, M_INFO, 0, _("Sending Accurate information.\n"));
187     }
188     /* to be able to allocate the right size for htable */
189 -   POOLMEM *nb = get_pool_memory(PM_FNAME);
190 -   *nb = 0;                           /* clear buffer */
191 -   Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids);
192 -   db_sql_query(jcr->db, buf.c_str(), db_get_int_handler, nb);
193 -   Dmsg2(200, "jobids=%s nb=%s\n", jobids, nb);
194 -   jcr->file_bsock->fsend("accurate files=%s\n", nb); 
195 +   Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids.list);
196 +   db_sql_query(jcr->db, buf.c_str(), db_list_handler, &nb);
197 +   Dmsg2(200, "jobids=%s nb=%s\n", jobids.list, nb.list);
198 +   jcr->file_bsock->fsend("accurate files=%s\n", nb.list); 
199  
200     if (!db_open_batch_connexion(jcr, jcr->db)) {
201        Jmsg0(jcr, M_FATAL, 0, "Can't get dedicate sql connexion");
202        return false;
203     }
204  
205 -   db_get_file_list(jcr, jcr->db_batch, jobids, accurate_list_handler, (void *)jcr);
206 +   db_get_file_list(jcr, jcr->db_batch, jobids.list, accurate_list_handler, (void *)jcr);
207  
208     /* TODO: close the batch connexion ? (can be used very soon) */
209  
210 -   free_pool_memory(jobids);
211 -   free_pool_memory(nb);
212 -
213     jcr->file_bsock->signal(BNET_EOD);
214  
215     return true;
216 diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c
217 index 3d5fc1d..028be52 100644
218 --- a/bacula/src/dird/ua_output.c
219 +++ b/bacula/src/dird/ua_output.c
220 @@ -456,7 +456,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist)
221           }
222           list_nextvol(ua, n);
223        } else if (strcasecmp(ua->argk[i], NT_("copies")) == 0) {
224 -         char *jobids=NULL;
225 +         char *jobids = NULL;
226           uint32_t limit=0;
227           for (j=i+1; j<ua->argc; j++) {
228              if (strcasecmp(ua->argk[j], NT_("jobid")) == 0 && ua->argv[j]) {
229 diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c
230 index 366d9ed..16f5215 100644
231 --- a/bacula/src/dird/ua_restore.c
232 +++ b/bacula/src/dird/ua_restore.c
233 @@ -1,7 +1,7 @@
234  /*
235     Bacula® - The Network Backup Solution
236  
237 -   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
238 +   Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
239  
240     The main author of Bacula is Kern Sibbald, with contributions from
241     many others, a complete list can be found in the file AUTHORS.
242 @@ -556,6 +556,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
243        char *fname;
244        int len;
245        bool gui_save;
246 +      db_list_ctx jobids;
247  
248        start_prompt(ua, _("To select the JobIds, you have the following choices:\n"));
249        for (int i=0; list[i]; i++) {
250 @@ -752,9 +753,10 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
251              return 0;
252           }
253           jr.JobLevel = L_INCREMENTAL; /* Take Full+Diff+Incr */
254 -         if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, rx->JobIds)) {
255 +         if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, &jobids)) {
256              return 0;
257           }
258 +         pm_strcpy(rx->JobIds, jobids.list);
259           Dmsg1(30, "Item 12: jobids = %s\n", rx->JobIds);
260           break;
261        case 12:                        /* Cancel or quit */
262 diff --git a/bacula/src/dird/vbackup.c b/bacula/src/dird/vbackup.c
263 index 45a1f7e..e75d08d 100644
264 --- a/bacula/src/dird/vbackup.c
265 +++ b/bacula/src/dird/vbackup.c
266 @@ -50,7 +50,7 @@
267  
268  static const int dbglevel = 10;
269  
270 -static bool create_bootstrap_file(JCR *jcr, POOLMEM *jobids);
271 +static bool create_bootstrap_file(JCR *jcr, char *jobids);
272  void vbackup_cleanup(JCR *jcr, int TermCode);
273  
274  /* 
275 @@ -135,6 +135,7 @@ bool do_vbackup(JCR *jcr)
276     char ed1[100];
277     BSOCK *sd;
278     char *p;
279 +   db_list_ctx jobids;
280  
281     Dmsg2(100, "rstorage=%p wstorage=%p\n", jcr->rstorage, jcr->wstorage);
282     Dmsg2(100, "Read store=%s, write store=%s\n", 
283 @@ -157,28 +158,27 @@ bool do_vbackup(JCR *jcr)
284  _("This Job is not an Accurate backup so is not equivalent to a Full backup.\n"));
285     }
286  
287 -   POOLMEM *jobids = get_pool_memory(PM_FNAME);
288     jcr->jr.JobLevel = L_VIRTUAL_FULL;
289 -   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids);
290 -   jcr->jr.JobLevel = L_FULL;
291 -   Dmsg1(10, "Accurate jobids=%s\n", jobids);
292 -   if (*jobids == 0) {
293 -      free_pool_memory(jobids);
294 +   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids);
295 +   Dmsg1(10, "Accurate jobids=%s\n", jobids.list);
296 +   if (jobids.count == 0) {
297        Jmsg(jcr, M_FATAL, 0, _("No previous Jobs found.\n"));
298        return false;
299     }
300  
301 +   jcr->jr.JobLevel = L_FULL;
302 +
303     /*
304      * Now we find the last job that ran and store it's info in
305      *  the previous_jr record.  We will set our times to the
306      *  values from that job so that anything changed after that
307      *  time will be picked up on the next backup.
308      */
309 -   p = strrchr(jobids, ',');              /* find last jobid */
310 +   p = strrchr(jobids.list, ',');           /* find last jobid */
311     if (p != NULL) {
312        p++;
313     } else {
314 -      p = jobids;
315 +      p = jobids.list;
316     }
317     memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr));
318     jcr->previous_jr.JobId = str_to_int64(p);
319 @@ -189,12 +189,10 @@ _("This Job is not an Accurate backup so is not equivalent to a Full backup.\n")
320        return false;
321     }
322  
323 -   if (!create_bootstrap_file(jcr, jobids)) {
324 +   if (!create_bootstrap_file(jcr, jobids.list)) {
325        Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
326 -      free_pool_memory(jobids);
327        return false;
328     }
329 -   free_pool_memory(jobids);
330  
331     /*
332      * Open a message channel connection with the Storage
333 @@ -476,7 +474,7 @@ int insert_bootstrap_handler(void *ctx, int num_fields, char **row)
334  }
335  
336  
337 -static bool create_bootstrap_file(JCR *jcr, POOLMEM *jobids)
338 +static bool create_bootstrap_file(JCR *jcr, char *jobids)
339  {
340     RESTORE_CTX rx;
341     UAContext *ua;