]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/status.c
Fix result return in compat readdir_r
[bacula/bacula] / bacula / src / filed / status.c
1 /*
2  *  Bacula File Daemon Status routines
3  *
4  *    Kern Sibbald, August MMI
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2003 Kern Sibbald and John Walker
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25    MA 02111-1307, USA.
26
27  */
28
29 #include "bacula.h"
30 #include "filed.h"
31
32 extern char my_name[];
33 extern struct s_last_job last_job;
34 extern time_t daemon_start_time;
35
36 /* Forward referenced functions */
37 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg);
38 static void bsock_sendit(const char *msg, int len, void *arg);
39 static char *level_to_str(int level);
40
41
42 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
43 static int privs = 0;
44 #endif
45
46 /*
47  * General status generator
48  */
49 static void do_status(void sendit(const char *msg, int len, void *sarg), void *arg) 
50 {
51    int sec, bps;
52    char *msg, b1[32], b2[32], b3[32];
53    int found, len;
54    JCR *njcr;
55    char dt[MAX_TIME_LENGTH];
56
57    msg = (char *)get_pool_memory(PM_MESSAGE);
58    found = 0;
59    len = Mmsg(&msg, "%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
60               HOST_OS, DISTNAME, DISTVER);
61    sendit(msg, len, arg);
62    bstrftime_nc(dt, sizeof(dt), daemon_start_time);
63    len = Mmsg(&msg, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
64         last_job.NumJobs == 1 ? "" : "s");
65    sendit(msg, len, arg);
66 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
67    if (debug_level > 0) {
68       if (!privs) {
69          privs = enable_backup_privileges(NULL, 1);
70       }
71       len = Mmsg(&msg, 
72          _("Priv 0x%x APIs=%sOPT,%sATP,%sLPV,%sGFAE,%sBR,%sBW,%sSPSP\n"), privs,
73          p_OpenProcessToken?"":"!",
74          p_AdjustTokenPrivileges?"":"!",
75          p_LookupPrivilegeValue?"":"!",
76          p_GetFileAttributesEx?"":"!",
77          p_BackupRead?"":"!",
78          p_BackupWrite?"":"!",
79          p_SetProcessShutdownParameters?"":"!");
80       sendit(msg, len, arg);
81    }
82 #endif
83
84    list_terminated_jobs(sendit, arg);
85
86 #ifdef xxx
87       char termstat[30];
88       struct s_last_job *je;
89       lock_last_jobs_list();
90       for (je=NULL; (je=(s_last_job *)last_jobs->next(je)); ) {
91          bstrftime_nc(dt, sizeof(dt), je->end_time);
92          len = Mmsg(&msg, _("Last Job %s finished at %s\n"), je->Job, dt);
93          sendit(msg, len, arg);
94
95          jobstatus_to_ascii(je->JobStatus, termstat, sizeof(termstat));
96          len = Mmsg(&msg, _("  Files=%s Bytes=%s Termination Status=%s\n"), 
97               edit_uint64_with_commas(je->JobFiles, b1),
98               edit_uint64_with_commas(je->JobBytes, b2),
99               termstat);
100          sendit(msg, len, arg);
101       }
102       unlock_last_jobs_list();
103 #endif
104
105    /*
106     * List running jobs  
107     */
108    Dmsg0(1000, "Begin status jcr loop.\n");
109    lock_jcr_chain();
110    for (njcr=NULL; (njcr=get_next_jcr(njcr)); ) {
111       bstrftime_nc(dt, sizeof(dt), njcr->start_time);
112       if (njcr->JobId == 0) {
113          len = Mmsg(&msg, _("Director connected at: %s\n"), dt);
114       } else {
115          len = Mmsg(&msg, _("JobId %d Job %s is running.\n"), 
116                     njcr->JobId, njcr->Job);
117          sendit(msg, len, arg);
118          len = Mmsg(&msg, _("    %s Job started: %s\n"), 
119                     job_type_to_str(njcr->JobType), dt);
120       }
121       sendit(msg, len, arg);
122       if (njcr->JobId == 0) {
123          free_locked_jcr(njcr);
124          continue;
125       }
126       sec = time(NULL) - njcr->start_time;
127       if (sec <= 0) {
128          sec = 1;
129       }
130       bps = njcr->JobBytes / sec;
131       len = Mmsg(&msg,  _("    Files=%s Bytes=%s Bytes/sec=%s\n"), 
132            edit_uint64_with_commas(njcr->JobFiles, b1),
133            edit_uint64_with_commas(njcr->JobBytes, b2),
134            edit_uint64_with_commas(bps, b3));
135       sendit(msg, len, arg);
136       len = Mmsg(&msg, _("    Files Examined=%s\n"), 
137            edit_uint64_with_commas(njcr->num_files_examined, b1));
138       sendit(msg, len, arg);
139       if (njcr->JobFiles > 0) {
140          P(njcr->mutex);
141          len = Mmsg(&msg, _("    Processing file: %s\n"), njcr->last_fname);
142          V(njcr->mutex);
143          sendit(msg, len, arg);
144       }
145
146       found = 1;
147       if (njcr->store_bsock) {
148          len = Mmsg(&msg, "    SDReadSeqNo=%" lld " fd=%d\n",
149              njcr->store_bsock->read_seqno, njcr->store_bsock->fd);
150          sendit(msg, len, arg);
151       } else {
152          len = Mmsg(&msg, _("    SDSocket closed.\n"));
153          sendit(msg, len, arg);
154       }
155       free_locked_jcr(njcr);
156    }
157    unlock_jcr_chain();
158    Dmsg0(1000, "Begin status jcr loop.\n");
159    if (!found) {
160       len = Mmsg(&msg, _("No jobs running.\n"));
161       sendit(msg, len, arg);
162    }
163    free_pool_memory(msg);
164 }
165
166 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg) 
167 {
168    char dt[MAX_TIME_LENGTH], b1[30], b2[30];
169    char level[10];
170    struct s_last_job *je;
171    const char *msg;
172
173    if (last_job.NumJobs == 0) {
174       msg = _("No Terminated Jobs.\n"); 
175       sendit(msg, strlen(msg), arg);
176       return;
177    }
178    lock_last_jobs_list();
179    sendit("\n", 1, arg);               /* send separately */
180    msg =  _("Terminated Jobs:\n"); 
181    sendit(msg, strlen(msg), arg);
182    msg =  _(" JobId  Level   Files          Bytes Status   Finished        Name \n");
183    sendit(msg, strlen(msg), arg);
184    msg = _("======================================================================\n"); 
185    sendit(msg, strlen(msg), arg);
186    for (je=NULL; (je=(s_last_job *)last_jobs->next(je)); ) {
187       char JobName[MAX_NAME_LENGTH];
188       char *termstat;
189       char buf[1000];
190
191       bstrftime_nc(dt, sizeof(dt), je->end_time);
192       switch (je->JobType) {
193       case JT_ADMIN:
194       case JT_RESTORE:
195          bstrncpy(level, "    ", sizeof(level));
196          break;
197       default:
198          bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
199          level[4] = 0;
200          break;
201       }
202       switch (je->JobStatus) {
203       case JS_Created:
204          termstat = "Created";
205          break;
206       case JS_FatalError:
207       case JS_ErrorTerminated:
208          termstat = "Error";
209          break;
210       case JS_Differences:
211          termstat = "Diffs";
212          break;
213       case JS_Canceled:
214          termstat = "Cancel";
215          break;
216       case JS_Terminated:
217          termstat = "OK";
218          break;
219       default:
220          termstat = "Other";
221          break;
222       }
223       bstrncpy(JobName, je->Job, sizeof(JobName));
224       /* There are three periods after the Job name */
225       char *p;
226       for (int i=0; i<3; i++) {
227          if ((p=strrchr(JobName, '.')) != NULL) {
228             *p = 0;
229          }
230       }
231       bsnprintf(buf, sizeof(buf), _("%6d  %-4s %8s %14s %-7s  %-8s %s\n"), 
232          je->JobId,
233          level, 
234          edit_uint64_with_commas(je->JobFiles, b1),
235          edit_uint64_with_commas(je->JobBytes, b2), 
236          termstat,
237          dt, JobName);
238       sendit(buf, strlen(buf), arg);
239    }
240    sendit("\n", 1, arg);
241    unlock_last_jobs_list();
242 }
243
244
245 /*
246  * Send to bsock (Director or Console)
247  */
248 static void bsock_sendit(const char *msg, int len, void *arg)
249 {
250    BSOCK *user = (BSOCK *)arg;
251
252    user->msg = check_pool_memory_size(user->msg, len+1);
253    memcpy(user->msg, msg, len+1);
254    user->msglen = len+1;
255    bnet_send(user);
256 }
257                                    
258 /*
259  * Status command from Director
260  */
261 int status_cmd(JCR *jcr)
262 {
263    BSOCK *user = jcr->dir_bsock;
264
265    bnet_fsend(user, "\n");
266    do_status(bsock_sendit, (void *)user);
267    bnet_fsend(user, "====\n");
268
269    bnet_sig(user, BNET_EOD);
270    return 1;
271 }
272
273
274 /*
275  * Convert Job Level into a string
276  */
277 static char *level_to_str(int level) 
278 {
279    char *str;
280
281    switch (level) {
282    case L_BASE:
283       str = _("Base");
284    case L_FULL:
285       str = _("Full");
286       break;
287    case L_INCREMENTAL:
288       str = _("Incremental");
289       break;
290    case L_DIFFERENTIAL:
291       str = _("Differential");
292       break;
293    case L_SINCE:
294       str = _("Since");
295       break;
296    case L_VERIFY_CATALOG:
297       str = _("Verify Catalog");
298       break;
299    case L_VERIFY_INIT:
300       str = _("Init Catalog");
301       break;
302    case L_VERIFY_VOLUME_TO_CATALOG:
303       str = _("Volume to Catalog");
304       break;
305    case L_VERIFY_DISK_TO_CATALOG:
306       str = _("Disk to Catalog");
307       break;
308    case L_VERIFY_DATA:
309       str = _("Data");
310       break;
311    case L_NONE:
312       str = " ";
313       break;
314    default:
315       str = _("Unknown Job Level");
316       break;
317    }
318    return str;
319 }
320
321
322 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
323 #include <windows.h>
324
325 static char buf[100];
326 int bacstat = 0;
327
328 struct s_win32_arg {
329    HWND hwnd;
330    int idlist;
331 };
332
333 /*
334  * Put message in Window List Box
335  */
336 static void win32_sendit(const char *msg, int len, void *marg)
337 {
338    struct s_win32_arg *arg = (struct s_win32_arg *)marg;
339
340    if (len > 0 && msg[len-1] == '\n') {
341        // when compiling with visual studio some strings are read-only 
342        // and cause access violations.  So we creat a tmp copy.
343        char *_msg = (char *)alloca(len);
344        strncpy(_msg, msg, len-1);
345        _msg[len-1] = 0;
346        msg = _msg;
347    }
348    SendDlgItemMessage(arg->hwnd, arg->idlist, LB_ADDSTRING, 0, (LONG)msg);
349    
350 }
351
352 void FillStatusBox(HWND hwnd, int idlist)
353 {
354    struct s_win32_arg arg;
355
356    arg.hwnd = hwnd;
357    arg.idlist = idlist;
358
359    /* Empty box */
360    for ( ; SendDlgItemMessage(hwnd, idlist, LB_DELETESTRING, 0, (LONG)0) > 0; )
361       { }
362    do_status(win32_sendit, (void *)&arg);
363 }
364
365 char *bac_status(int stat)
366 {
367    JCR *njcr;
368    char *termstat = _("Bacula Idle");
369
370    bacstat = 0;
371    if (last_job.NumJobs > 0) {
372       switch (last_job.JobStatus) {
373       case JS_Canceled:
374          bacstat = -1;
375          termstat = _("Last Job Canceled");
376          break;
377       case JS_ErrorTerminated:
378          bacstat = -1;
379          termstat = _("Last Job Failed");
380          break;
381       default:
382          break;
383       }
384    }
385    Dmsg0(1000, "Begin bac_status jcr loop.\n");
386    lock_jcr_chain();
387    for (njcr=NULL; (njcr=get_next_jcr(njcr)); ) {
388       if (njcr->JobId != 0) {
389          bacstat = 1;
390          termstat = _("Bacula Running");
391          free_locked_jcr(njcr);
392          break;
393       }
394       free_locked_jcr(njcr);
395    }
396    unlock_jcr_chain();
397    Dmsg0(1000, "End bac_status jcr loop.\n");
398    bstrncpy(buf, termstat, sizeof(buf));
399    return buf;
400 }
401
402 #endif /* HAVE_CYGWIN */