]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/status.c
Add Swedish sv.po file
[bacula/bacula] / bacula / src / filed / status.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2007 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 two of the GNU 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 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 John Walker.
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 Status routines
30  *
31  *    Kern Sibbald, August MMI
32  *
33  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "filed.h"
39
40 extern void *start_heap;
41
42 /* Forward referenced functions */
43 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg);
44 static void bsock_sendit(const char *msg, int len, void *arg);
45 static const char *level_to_str(int level);
46
47 /* Static variables */
48 static char qstatus[] = ".status %s\n";
49
50 static char OKqstatus[]   = "2000 OK .status\n";
51 static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n";
52
53 #if defined(HAVE_WIN32)
54 static int privs = 0;
55 #endif
56 #ifdef WIN32_VSS
57 #include "vss.h"
58 #define VSS " VSS"
59 extern VSSClient *g_pVSSClient;
60 #else
61 #define VSS ""
62 #endif
63
64 /*
65  * General status generator
66  */
67 void output_status(void sendit(const char *msg, int len, void *sarg), void *arg)
68 {
69    int sec, bps;
70    POOL_MEM msg(PM_MESSAGE);
71    char b1[32], b2[32], b3[32], b4[32], b5[35];
72    int len;
73    bool found = false;
74    JCR *njcr;
75    char dt[MAX_TIME_LENGTH];
76
77    len = Mmsg(msg, _("%s Version: %s (%s) %s %s %s %s\n"), 
78               my_name, VERSION, BDATE, VSS, HOST_OS, DISTNAME, DISTVER);
79    sendit(msg.c_str(), len, arg);
80    bstrftime_nc(dt, sizeof(dt), daemon_start_time);
81    len = Mmsg(msg, _("Daemon started %s, %d Job%s run since started.\n"),
82         dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
83    sendit(msg.c_str(), len, arg);
84 #if defined(HAVE_WIN32)
85    if (debug_level > 0) {
86       if (!privs) {
87          privs = enable_backup_privileges(NULL, 1);
88       }
89       len = Mmsg(msg, "VSS %s, Priv 0x%x\n", g_pVSSClient?"enabled":"disabled", privs);
90       sendit(msg.c_str(), len, arg);
91       len = Mmsg(msg, "APIs=%sOPT,%sATP,%sLPV,%sCFA,%sCFW,\n",
92                  p_OpenProcessToken?"":"!",
93                  p_AdjustTokenPrivileges?"":"!",
94                  p_LookupPrivilegeValue?"":"!",
95                  p_CreateFileA?"":"!",
96                  p_CreateFileW?"":"!");
97       sendit(msg.c_str(), len, arg);
98       len = Mmsg(msg, " %sWUL,%sWMKD,%sGFAA,%sGFAW,%sGFAEA,%sGFAEW,%sSFAA,%sSFAW,%sBR,%sBW,%sSPSP,\n",
99                  p_wunlink?"":"!",
100                  p_wmkdir?"":"!",
101                  p_GetFileAttributesA?"":"!",
102                  p_GetFileAttributesW?"":"!",
103                  p_GetFileAttributesExA?"":"!",
104                  p_GetFileAttributesExW?"":"!",
105                  p_SetFileAttributesA?"":"!",
106                  p_SetFileAttributesW?"":"!",
107                  p_BackupRead?"":"!",
108                  p_BackupWrite?"":"!",
109                  p_SetProcessShutdownParameters?"":"!");
110       sendit(msg.c_str(), len, arg);
111       len = Mmsg(msg, " %sWC2MB,%sMB2WC,%sFFFA,%sFFFW,%sFNFA,%sFNFW,%sSCDA,%sSCDW,\n",
112                  p_WideCharToMultiByte?"":"!",
113                  p_MultiByteToWideChar?"":"!",
114                  p_FindFirstFileA?"":"!",
115                  p_FindFirstFileW?"":"!",
116                  p_FindNextFileA?"":"!",
117                  p_FindNextFileW?"":"!",
118                  p_SetCurrentDirectoryA?"":"!",
119                  p_SetCurrentDirectoryW?"":"!");
120       sendit(msg.c_str(), len, arg);
121       len = Mmsg(msg, " %sGCDA,%sGCDW,%sGVPNW,%sGVNFVMPW\n",  
122                  p_GetCurrentDirectoryA?"":"!",
123                  p_GetCurrentDirectoryW?"":"!",
124                  p_GetVolumePathNameW?"":"!",
125                  p_GetVolumeNameForVolumeMountPointW?"":"!");
126      sendit(msg.c_str(), len, arg);
127    }
128 #endif
129    len = Mmsg(msg, _(" Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
130          edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
131          edit_uint64_with_commas(sm_bytes, b2),
132          edit_uint64_with_commas(sm_max_bytes, b3),
133          edit_uint64_with_commas(sm_buffers, b4),
134          edit_uint64_with_commas(sm_max_buffers, b5));
135    sendit(msg.c_str(), len, arg);
136    len = Mmsg(msg, _(" Sizeof: boffset_t=%d size_t=%d debug=%d trace=%d\n"),
137          sizeof(boffset_t), sizeof(size_t), debug_level, get_trace());
138    sendit(msg.c_str(), len, arg);
139
140    /*
141     * List running jobs
142     */
143    Dmsg0(1000, "Begin status jcr loop.\n");
144    len = Mmsg(msg, _("\nRunning Jobs:\n"));
145    sendit(msg.c_str(), len, arg);
146    char *vss = "";
147 #ifdef WIN32_VSS
148    if (g_pVSSClient && g_pVSSClient->IsInitialized()) {
149       vss = "VSS ";
150    }
151 #endif
152    foreach_jcr(njcr) {
153       bstrftime_nc(dt, sizeof(dt), njcr->start_time);
154       if (njcr->JobId == 0) {
155          len = Mmsg(msg, _("Director connected at: %s\n"), dt);
156       } else {
157          len = Mmsg(msg, _("JobId %d Job %s is running.\n"),
158                     njcr->JobId, njcr->Job);
159          sendit(msg.c_str(), len, arg);
160          len = Mmsg(msg, _("    %s%s Job started: %s\n"),
161                     vss, job_type_to_str(njcr->JobType), dt);
162       }
163       sendit(msg.c_str(), len, arg);
164       if (njcr->JobId == 0) {
165          continue;
166       }
167       sec = time(NULL) - njcr->start_time;
168       if (sec <= 0) {
169          sec = 1;
170       }
171       bps = (int)(njcr->JobBytes / sec);
172       len = Mmsg(msg,  _("    Files=%s Bytes=%s Bytes/sec=%s\n"),
173            edit_uint64_with_commas(njcr->JobFiles, b1),
174            edit_uint64_with_commas(njcr->JobBytes, b2),
175            edit_uint64_with_commas(bps, b3));
176       sendit(msg.c_str(), len, arg);
177       len = Mmsg(msg, _("    Files Examined=%s\n"),
178            edit_uint64_with_commas(njcr->num_files_examined, b1));
179       sendit(msg.c_str(), len, arg);
180       if (njcr->JobFiles > 0) {
181          njcr->lock();
182          len = Mmsg(msg, _("    Processing file: %s\n"), njcr->last_fname);
183          njcr->unlock();
184          sendit(msg.c_str(), len, arg);
185       }
186
187       found = true;
188       if (njcr->store_bsock) {
189          len = Mmsg(msg, "    SDReadSeqNo=%" lld " fd=%d\n",
190              njcr->store_bsock->read_seqno, njcr->store_bsock->m_fd);
191          sendit(msg.c_str(), len, arg);
192       } else {
193          len = Mmsg(msg, _("    SDSocket closed.\n"));
194          sendit(msg.c_str(), len, arg);
195       }
196    }
197    endeach_jcr(njcr);
198
199    if (!found) {
200       len = Mmsg(msg, _("No Jobs running.\n"));
201       sendit(msg.c_str(), len, arg);
202    }
203    sendit(_("====\n"), 5, arg);
204
205    list_terminated_jobs(sendit, arg);
206 }
207
208 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg)
209 {
210    char dt[MAX_TIME_LENGTH], b1[30], b2[30];
211    char level[10];
212    struct s_last_job *je;
213    const char *msg;
214
215    msg =  _("\nTerminated Jobs:\n");
216    sendit(msg, strlen(msg), arg);
217
218    if (last_jobs->size() == 0) {
219       sendit(_("====\n"), 5, arg);
220       return;
221    }
222    lock_last_jobs_list();
223    msg =  _(" JobId  Level    Files      Bytes   Status   Finished        Name \n");
224    sendit(msg, strlen(msg), arg);
225    msg = _("======================================================================\n");
226    sendit(msg, strlen(msg), arg);
227    foreach_dlist(je, last_jobs) {
228       char JobName[MAX_NAME_LENGTH];
229       const char *termstat;
230       char buf[1000];
231
232       bstrftime_nc(dt, sizeof(dt), je->end_time);
233       switch (je->JobType) {
234       case JT_ADMIN:
235       case JT_RESTORE:
236          bstrncpy(level, "    ", sizeof(level));
237          break;
238       default:
239          bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
240          level[4] = 0;
241          break;
242       }
243       switch (je->JobStatus) {
244       case JS_Created:
245          termstat = _("Created");
246          break;
247       case JS_FatalError:
248       case JS_ErrorTerminated:
249          termstat = _("Error");
250          break;
251       case JS_Differences:
252          termstat = _("Diffs");
253          break;
254       case JS_Canceled:
255          termstat = _("Cancel");
256          break;
257       case JS_Terminated:
258          termstat = _("OK");
259          break;
260       default:
261          termstat = _("Other");
262          break;
263       }
264       bstrncpy(JobName, je->Job, sizeof(JobName));
265       /* There are three periods after the Job name */
266       char *p;
267       for (int i=0; i<3; i++) {
268          if ((p=strrchr(JobName, '.')) != NULL) {
269             *p = 0;
270          }
271       }
272       bsnprintf(buf, sizeof(buf), _("%6d  %-6s %8s %10s  %-7s  %-8s %s\n"),
273          je->JobId,
274          level,
275          edit_uint64_with_commas(je->JobFiles, b1),
276          edit_uint64_with_suffix(je->JobBytes, b2),
277          termstat,
278          dt, JobName);
279       sendit(buf, strlen(buf), arg);
280    }
281    sendit(_("====\n"), 5, arg);
282    unlock_last_jobs_list();
283 }
284
285
286 /*
287  * Send to bsock (Director or Console)
288  */
289 static void bsock_sendit(const char *msg, int len, void *arg)
290 {
291    BSOCK *user = (BSOCK *)arg;
292
293    user->msg = check_pool_memory_size(user->msg, len+1);
294    memcpy(user->msg, msg, len+1);
295    user->msglen = len+1;
296    bnet_send(user);
297 }
298
299 /*
300  * Status command from Director
301  */
302 int status_cmd(JCR *jcr)
303 {
304    BSOCK *user = jcr->dir_bsock;
305
306    bnet_fsend(user, "\n");
307    output_status(bsock_sendit, (void *)user);
308
309    bnet_sig(user, BNET_EOD);
310    return 1;
311 }
312
313 /*
314  * .status command from Director
315  */
316 int qstatus_cmd(JCR *jcr)
317 {
318    BSOCK *dir = jcr->dir_bsock;
319    POOLMEM *time;
320    JCR *njcr;
321    s_last_job* job;
322
323    time = get_memory(dir->msglen+1);
324
325    if (sscanf(dir->msg, qstatus, time) != 1) {
326       pm_strcpy(&jcr->errmsg, dir->msg);
327       Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
328       bnet_fsend(dir, _("2900 Bad .status command, missing argument.\n"));
329       bnet_sig(dir, BNET_EOD);
330       free_memory(time);
331       return 0;
332    }
333    unbash_spaces(time);
334
335    if (strcmp(time, "current") == 0) {
336       bnet_fsend(dir, OKqstatus, time);
337       foreach_jcr(njcr) {
338          if (njcr->JobId != 0) {
339             bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
340          }
341       }
342       endeach_jcr(njcr);
343    } else if (strcmp(time, "last") == 0) {
344       bnet_fsend(dir, OKqstatus, time);
345       if ((last_jobs) && (last_jobs->size() > 0)) {
346          job = (s_last_job*)last_jobs->last();
347          bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
348       }
349    } else {
350       pm_strcpy(&jcr->errmsg, dir->msg);
351       Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
352       bnet_fsend(dir, _("2900 Bad .status command, wrong argument.\n"));
353       bnet_sig(dir, BNET_EOD);
354       free_memory(time);
355       return 0;
356    }
357
358    bnet_sig(dir, BNET_EOD);
359    free_memory(time);
360    return 1;
361 }
362
363 /*
364  * Convert Job Level into a string
365  */
366 static const char *level_to_str(int level)
367 {
368    const char *str;
369
370    switch (level) {
371    case L_BASE:
372       str = _("Base");
373    case L_FULL:
374       str = _("Full");
375       break;
376    case L_INCREMENTAL:
377       str = _("Incremental");
378       break;
379    case L_DIFFERENTIAL:
380       str = _("Differential");
381       break;
382    case L_SINCE:
383       str = _("Since");
384       break;
385    case L_VERIFY_CATALOG:
386       str = _("Verify Catalog");
387       break;
388    case L_VERIFY_INIT:
389       str = _("Init Catalog");
390       break;
391    case L_VERIFY_VOLUME_TO_CATALOG:
392       str = _("Volume to Catalog");
393       break;
394    case L_VERIFY_DISK_TO_CATALOG:
395       str = _("Disk to Catalog");
396       break;
397    case L_VERIFY_DATA:
398       str = _("Data");
399       break;
400    case L_NONE:
401       str = " ";
402       break;
403    default:
404       str = _("Unknown Job Level");
405       break;
406    }
407    return str;
408 }
409
410
411 #if defined(HAVE_WIN32)
412 int bacstat = 0;
413
414 /*
415  * Put message in Window List Box
416  */
417 char *bac_status(char *buf, int buf_len)
418 {
419    JCR *njcr;
420    const char *termstat = _("Bacula Client: Idle");
421    struct s_last_job *job;
422    int stat = 0;                      /* Idle */
423
424    if (!last_jobs) {
425       goto done;
426    }
427    Dmsg0(1000, "Begin bac_status jcr loop.\n");
428    foreach_jcr(njcr) {
429       if (njcr->JobId != 0) {
430          stat = JS_Running;
431          termstat = _("Bacula Client: Running");
432          break;
433       }
434    }
435    endeach_jcr(njcr);
436
437    if (stat != 0) {
438       goto done;
439    }
440    if (last_jobs->size() > 0) {
441       job = (struct s_last_job *)last_jobs->last();
442       stat = job->JobStatus;
443       switch (job->JobStatus) {
444       case JS_Canceled:
445          termstat = _("Bacula Client: Last Job Canceled");
446          break;
447       case JS_ErrorTerminated:
448       case JS_FatalError:
449          termstat = _("Bacula Client: Last Job Failed");
450          break;
451       default:
452          if (job->Errors) {
453             termstat = _("Bacula Client: Last Job had Warnings");
454          }
455          break;
456       }
457    }
458    Dmsg0(1000, "End bac_status jcr loop.\n");
459 done:
460    bacstat = stat;
461    if (buf) {
462       bstrncpy(buf, termstat, buf_len);
463    }
464    return buf;
465 }
466
467 #endif /* HAVE_WIN32 */