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 plus additions
11 that are listed in the file LICENSE.
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, "Priv 0x%x\n", 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\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) {
182 len = Mmsg(msg, _(" Processing file: %s\n"), njcr->last_fname);
184 sendit(msg.c_str(), len, arg);
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);
193 len = Mmsg(msg, _(" SDSocket closed.\n"));
194 sendit(msg.c_str(), len, arg);
200 len = Mmsg(msg, _("No Jobs running.\n"));
201 sendit(msg.c_str(), len, arg);
203 sendit(_("====\n"), 5, arg);
205 list_terminated_jobs(sendit, arg);
208 static void list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg)
210 char dt[MAX_TIME_LENGTH], b1[30], b2[30];
212 struct s_last_job *je;
215 msg = _("\nTerminated Jobs:\n");
216 sendit(msg, strlen(msg), arg);
218 if (last_jobs->size() == 0) {
219 sendit(_("====\n"), 5, arg);
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;
232 bstrftime_nc(dt, sizeof(dt), je->end_time);
233 switch (je->JobType) {
236 bstrncpy(level, " ", sizeof(level));
239 bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
243 switch (je->JobStatus) {
245 termstat = _("Created");
248 case JS_ErrorTerminated:
249 termstat = _("Error");
252 termstat = _("Diffs");
255 termstat = _("Cancel");
261 termstat = _("Other");
264 bstrncpy(JobName, je->Job, sizeof(JobName));
265 /* There are three periods after the Job name */
267 for (int i=0; i<3; i++) {
268 if ((p=strrchr(JobName, '.')) != NULL) {
272 bsnprintf(buf, sizeof(buf), _("%6d %-6s %8s %10s %-7s %-8s %s\n"),
275 edit_uint64_with_commas(je->JobFiles, b1),
276 edit_uint64_with_suffix(je->JobBytes, b2),
279 sendit(buf, strlen(buf), arg);
281 sendit(_("====\n"), 5, arg);
282 unlock_last_jobs_list();
287 * Send to bsock (Director or Console)
289 static void bsock_sendit(const char *msg, int len, void *arg)
291 BSOCK *user = (BSOCK *)arg;
293 user->msg = check_pool_memory_size(user->msg, len+1);
294 memcpy(user->msg, msg, len+1);
295 user->msglen = len+1;
300 * Status command from Director
302 int status_cmd(JCR *jcr)
304 BSOCK *user = jcr->dir_bsock;
306 bnet_fsend(user, "\n");
307 output_status(bsock_sendit, (void *)user);
309 bnet_sig(user, BNET_EOD);
314 * .status command from Director
316 int qstatus_cmd(JCR *jcr)
318 BSOCK *dir = jcr->dir_bsock;
323 time = get_memory(dir->msglen+1);
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);
335 if (strcmp(time, "current") == 0) {
336 bnet_fsend(dir, OKqstatus, time);
338 if (njcr->JobId != 0) {
339 bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
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);
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);
358 bnet_sig(dir, BNET_EOD);
364 * Convert Job Level into a string
366 static const char *level_to_str(int level)
377 str = _("Incremental");
380 str = _("Differential");
385 case L_VERIFY_CATALOG:
386 str = _("Verify Catalog");
389 str = _("Init Catalog");
391 case L_VERIFY_VOLUME_TO_CATALOG:
392 str = _("Volume to Catalog");
394 case L_VERIFY_DISK_TO_CATALOG:
395 str = _("Disk to Catalog");
404 str = _("Unknown Job Level");
411 #if defined(HAVE_WIN32)
415 * Put message in Window List Box
417 char *bac_status(char *buf, int buf_len)
420 const char *termstat = _("Bacula Client: Idle");
421 struct s_last_job *job;
422 int stat = 0; /* Idle */
427 Dmsg0(1000, "Begin bac_status jcr loop.\n");
429 if (njcr->JobId != 0) {
431 termstat = _("Bacula Client: Running");
440 if (last_jobs->size() > 0) {
441 job = (struct s_last_job *)last_jobs->last();
442 stat = job->JobStatus;
443 switch (job->JobStatus) {
445 termstat = _("Bacula Client: Last Job Canceled");
447 case JS_ErrorTerminated:
449 termstat = _("Bacula Client: Last Job Failed");
453 termstat = _("Bacula Client: Last Job had Warnings");
458 Dmsg0(1000, "End bac_status jcr loop.\n");
462 bstrncpy(buf, termstat, buf_len);
467 #endif /* HAVE_WIN32 */