2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2007 Free Software Foundation Europe e.V.
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
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.
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
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.
29 * Bacula File Daemon Status routines
31 * Kern Sibbald, August MMI
40 extern void *start_heap;
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);
47 /* Static variables */
48 static char qstatus[] = ".status %s\n";
50 static char OKqstatus[] = "2000 OK .status\n";
51 static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n";
53 #if defined(HAVE_WIN32)
59 extern VSSClient *g_pVSSClient;
65 * General status generator
67 void output_status(void sendit(const char *msg, int len, void *sarg), void *arg)
70 POOL_MEM msg(PM_MESSAGE);
71 char b1[32], b2[32], b3[32], b4[32], b5[35];
75 char dt[MAX_TIME_LENGTH];
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) {
87 privs = enable_backup_privileges(NULL, 1);
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?"":"!",
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",
101 p_GetFileAttributesA?"":"!",
102 p_GetFileAttributesW?"":"!",
103 p_GetFileAttributesExA?"":"!",
104 p_GetFileAttributesExW?"":"!",
105 p_SetFileAttributesA?"":"!",
106 p_SetFileAttributesW?"":"!",
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);
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);
143 Dmsg0(1000, "Begin status jcr loop.\n");
144 len = Mmsg(msg, _("\nRunning Jobs:\n"));
145 sendit(msg.c_str(), len, arg);
148 if (g_pVSSClient && g_pVSSClient->IsInitialized()) {
153 bstrftime_nc(dt, sizeof(dt), njcr->start_time);
154 if (njcr->JobId == 0) {
155 len = Mmsg(msg, _("Director connected at: %s\n"), dt);
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);
163 sendit(msg.c_str(), len, arg);
164 if (njcr->JobId == 0) {
167 sec = time(NULL) - njcr->start_time;
171 bps = (int)(njcr->JobBytes / sec);
172 len = Mmsg(msg, _(" Files=%s Bytes=%s Bytes/sec=%s Errors=%d\n"),
173 edit_uint64_with_commas(njcr->JobFiles, b1),
174 edit_uint64_with_commas(njcr->JobBytes, b2),
175 edit_uint64_with_commas(bps, b3),
177 sendit(msg.c_str(), len, arg);
178 len = Mmsg(msg, _(" Files Examined=%s\n"),
179 edit_uint64_with_commas(njcr->num_files_examined, b1));
180 sendit(msg.c_str(), len, arg);
181 if (njcr->JobFiles > 0) {
183 len = Mmsg(msg, _(" Processing file: %s\n"), njcr->last_fname);
185 sendit(msg.c_str(), len, arg);
189 if (njcr->store_bsock) {
190 len = Mmsg(msg, " SDReadSeqNo=%" lld " fd=%d\n",
191 njcr->store_bsock->read_seqno, njcr->store_bsock->m_fd);
192 sendit(msg.c_str(), len, arg);
194 len = Mmsg(msg, _(" SDSocket closed.\n"));
195 sendit(msg.c_str(), len, arg);
201 len = Mmsg(msg, _("No Jobs running.\n"));
202 sendit(msg.c_str(), len, arg);
204 sendit(_("====\n"), 5, arg);
206 list_terminated_jobs(sendit, arg);
209 static void list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg)
211 char dt[MAX_TIME_LENGTH], b1[30], b2[30];
213 struct s_last_job *je;
216 msg = _("\nTerminated Jobs:\n");
217 sendit(msg, strlen(msg), arg);
219 if (last_jobs->size() == 0) {
220 sendit(_("====\n"), 5, arg);
223 lock_last_jobs_list();
224 msg = _(" JobId Level Files Bytes Status Finished Name \n");
225 sendit(msg, strlen(msg), arg);
226 msg = _("======================================================================\n");
227 sendit(msg, strlen(msg), arg);
228 foreach_dlist(je, last_jobs) {
229 char JobName[MAX_NAME_LENGTH];
230 const char *termstat;
233 bstrftime_nc(dt, sizeof(dt), je->end_time);
234 switch (je->JobType) {
237 bstrncpy(level, " ", sizeof(level));
240 bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
244 switch (je->JobStatus) {
246 termstat = _("Created");
249 case JS_ErrorTerminated:
250 termstat = _("Error");
253 termstat = _("Diffs");
256 termstat = _("Cancel");
262 termstat = _("Other");
265 bstrncpy(JobName, je->Job, sizeof(JobName));
266 /* There are three periods after the Job name */
268 for (int i=0; i<3; i++) {
269 if ((p=strrchr(JobName, '.')) != NULL) {
273 bsnprintf(buf, sizeof(buf), _("%6d %-6s %8s %10s %-7s %-8s %s\n"),
276 edit_uint64_with_commas(je->JobFiles, b1),
277 edit_uint64_with_suffix(je->JobBytes, b2),
280 sendit(buf, strlen(buf), arg);
282 sendit(_("====\n"), 5, arg);
283 unlock_last_jobs_list();
288 * Send to bsock (Director or Console)
290 static void bsock_sendit(const char *msg, int len, void *arg)
292 BSOCK *user = (BSOCK *)arg;
294 user->msg = check_pool_memory_size(user->msg, len+1);
295 memcpy(user->msg, msg, len+1);
296 user->msglen = len+1;
301 * Status command from Director
303 int status_cmd(JCR *jcr)
305 BSOCK *user = jcr->dir_bsock;
307 bnet_fsend(user, "\n");
308 output_status(bsock_sendit, (void *)user);
310 bnet_sig(user, BNET_EOD);
315 * .status command from Director
317 int qstatus_cmd(JCR *jcr)
319 BSOCK *dir = jcr->dir_bsock;
324 time = get_memory(dir->msglen+1);
326 if (sscanf(dir->msg, qstatus, time) != 1) {
327 pm_strcpy(&jcr->errmsg, dir->msg);
328 Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
329 bnet_fsend(dir, _("2900 Bad .status command, missing argument.\n"));
330 bnet_sig(dir, BNET_EOD);
336 if (strcmp(time, "current") == 0) {
337 bnet_fsend(dir, OKqstatus, time);
339 if (njcr->JobId != 0) {
340 bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
344 } else if (strcmp(time, "last") == 0) {
345 bnet_fsend(dir, OKqstatus, time);
346 if ((last_jobs) && (last_jobs->size() > 0)) {
347 job = (s_last_job*)last_jobs->last();
348 bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
351 pm_strcpy(&jcr->errmsg, dir->msg);
352 Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
353 bnet_fsend(dir, _("2900 Bad .status command, wrong argument.\n"));
354 bnet_sig(dir, BNET_EOD);
359 bnet_sig(dir, BNET_EOD);
365 * Convert Job Level into a string
367 static const char *level_to_str(int level)
378 str = _("Incremental");
381 str = _("Differential");
386 case L_VERIFY_CATALOG:
387 str = _("Verify Catalog");
390 str = _("Init Catalog");
392 case L_VERIFY_VOLUME_TO_CATALOG:
393 str = _("Volume to Catalog");
395 case L_VERIFY_DISK_TO_CATALOG:
396 str = _("Disk to Catalog");
405 str = _("Unknown Job Level");
412 #if defined(HAVE_WIN32)
416 * Put message in Window List Box
418 char *bac_status(char *buf, int buf_len)
421 const char *termstat = _("Bacula Client: Idle");
422 struct s_last_job *job;
423 int stat = 0; /* Idle */
428 Dmsg0(1000, "Begin bac_status jcr loop.\n");
430 if (njcr->JobId != 0) {
432 termstat = _("Bacula Client: Running");
441 if (last_jobs->size() > 0) {
442 job = (struct s_last_job *)last_jobs->last();
443 stat = job->JobStatus;
444 switch (job->JobStatus) {
446 termstat = _("Bacula Client: Last Job Canceled");
448 case JS_ErrorTerminated:
450 termstat = _("Bacula Client: Last Job Failed");
454 termstat = _("Bacula Client: Last Job had Warnings");
459 Dmsg0(1000, "End bac_status jcr loop.\n");
463 bstrncpy(buf, termstat, buf_len);
468 #endif /* HAVE_WIN32 */