]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/verify_vol.c
Tweak accurate code to avoid useless memcpy()
[bacula/bacula] / bacula / src / filed / verify_vol.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *  Bacula File Daemon  verify-vol.c Verify files on a Volume
30  *    versus attributes in Catalog
31  *
32  *    Kern Sibbald, July MMII
33  *
34  */
35
36 #include "bacula.h"
37 #include "filed.h"
38
39 /* Data received from Storage Daemon */
40 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
41
42 /* Forward referenced functions */
43
44
45 /*
46  * Verify attributes of the requested files on the Volume
47  *
48  */
49 void do_verify_volume(JCR *jcr)
50 {
51    BSOCK *sd, *dir;
52    POOLMEM *fname;                    /* original file name */
53    POOLMEM *lname;                    /* link name */
54    int32_t stream;
55    uint32_t size;
56    uint32_t VolSessionId, VolSessionTime, file_index;
57    uint32_t record_file_index;
58    char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
59    int type, stat;
60
61    sd = jcr->store_bsock;
62    if (!sd) {
63       Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n"));
64       set_jcr_job_status(jcr, JS_FatalError);
65       return;
66    }
67    dir = jcr->dir_bsock;
68    set_jcr_job_status(jcr, JS_Running);
69
70    LockRes();
71    CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
72    UnlockRes();
73    uint32_t buf_size;
74    if (client) {
75       buf_size = client->max_network_buffer_size;
76    } else {
77       buf_size = 0;                   /* use default */
78    }
79    if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
80       set_jcr_job_status(jcr, JS_FatalError);
81       return;
82    }
83    jcr->buf_size = sd->msglen;
84
85    fname = get_pool_memory(PM_FNAME);
86    lname = get_pool_memory(PM_FNAME);
87
88    /*
89     * Get a record from the Storage daemon
90     */
91    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
92       /*
93        * First we expect a Stream Record Header
94        */
95       if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
96           &stream, &size) != 5) {
97          Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
98          goto bail_out;
99       }
100       Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
101
102       /*
103        * Now we expect the Stream Data
104        */
105       if (bget_msg(sd) < 0) {
106          Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
107          goto bail_out;
108       }
109       if (size != ((uint32_t)sd->msglen)) {
110          Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
111          goto bail_out;
112       }
113       Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
114
115       /* File Attributes stream */
116       switch (stream) {
117       case STREAM_UNIX_ATTRIBUTES:
118       case STREAM_UNIX_ATTRIBUTES_EX:
119          char *ap, *lp, *fp;
120
121          Dmsg0(400, "Stream=Unix Attributes.\n");
122
123          if ((int)sizeof_pool_memory(fname) < sd->msglen) {
124             fname = realloc_pool_memory(fname, sd->msglen + 1);
125          }
126
127          if ((int)sizeof_pool_memory(lname) < sd->msglen) {
128             lname = realloc_pool_memory(lname, sd->msglen + 1);
129          }
130          *fname = 0;
131          *lname = 0;
132
133          /*
134           * An Attributes record consists of:
135           *    File_index
136           *    Type   (FT_types)
137           *    Filename
138           *    Attributes
139           *    Link name (if file linked i.e. FT_LNK)
140           *    Extended Attributes (if Win32)
141           */
142          if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
143             Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg);
144             Dmsg0(0, "\nError scanning header\n");
145             goto bail_out;
146          }
147          Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
148          ap = sd->msg;
149          while (*ap++ != ' ')         /* skip record file index */
150             ;
151          while (*ap++ != ' ')         /* skip type */
152             ;
153          /* Save filename and position to attributes */
154          fp = fname;
155          while (*ap != 0) {
156             *fp++  = *ap++;           /* copy filename to fname */
157          }
158          *fp = *ap++;                 /* terminate filename & point to attribs */
159
160          Dmsg1(200, "Attr=%s\n", ap);
161          /* Skip to Link name */
162          if (type == FT_LNK || type == FT_LNKSAVED) {
163             lp = ap;
164             while (*lp++ != 0) {
165                ;
166             }
167             pm_strcat(lname, lp);        /* "save" link name */
168          } else {
169             *lname = 0;
170          }
171          jcr->lock();
172          jcr->JobFiles++;
173          jcr->num_files_examined++;
174          pm_strcpy(jcr->last_fname, fname); /* last file examined */
175          jcr->unlock();
176
177          /*
178           * Send file attributes to Director
179           *   File_index
180           *   Stream
181           *   Verify Options
182           *   Filename (full path)
183           *   Encoded attributes
184           *   Link name (if type==FT_LNK)
185           * For a directory, link is the same as fname, but with trailing
186           * slash. For a linked file, link is the link.
187           */
188          /* Send file attributes to Director */
189          Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname);
190          if (type == FT_LNK || type == FT_LNKSAVED) {
191             stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
192                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
193                           0, ap, 0, lname, 0);
194          /* for a deleted record, we set fileindex=0 */
195          } else if (type == FT_DELETED)  {
196             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", 0,
197                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
198                           0, ap, 0, 0);
199          } else {
200             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
201                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
202                           0, ap, 0, 0);
203          }
204          Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
205          if (!stat) {
206             Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
207             goto bail_out;
208          }
209          break;
210
211       case STREAM_MD5_DIGEST:
212          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
213          Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
214          bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
215                     jcr->JobFiles);
216          Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
217          break;
218
219       case STREAM_SHA1_DIGEST:
220          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
221          Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
222          bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
223                     digest, jcr->JobFiles);
224          Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
225          break;
226
227       case STREAM_SHA256_DIGEST:
228          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
229          Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
230          bnet_fsend(dir, "%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
231                     digest, jcr->JobFiles);
232          Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
233          break;
234
235       case STREAM_SHA512_DIGEST:
236          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
237          Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
238          bnet_fsend(dir, "%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
239                     digest, jcr->JobFiles);
240          Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
241          break;
242
243       /* Ignore everything else */
244       default:
245          break;
246
247       } /* end switch */
248    } /* end while bnet_get */
249    set_jcr_job_status(jcr, JS_Terminated);
250    goto ok_out;
251
252 bail_out:
253    set_jcr_job_status(jcr, JS_ErrorTerminated);
254
255 ok_out:
256    if (jcr->compress_buf) {
257       free(jcr->compress_buf);
258       jcr->compress_buf = NULL;
259    }
260    free_pool_memory(fname);
261    free_pool_memory(lname);
262    Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
263       jcr->JobBytes);
264 }