]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/dircmd.c
relabel command, first cut label barcodes
[bacula/bacula] / bacula / src / stored / dircmd.c
1 /*
2  *  This file handles accepting Director Commands
3  *
4  *    Most Director commands are handled here, with the 
5  *    exception of the Job command command and subsequent 
6  *    subcommands that are handled
7  *    in job.c.  
8  *
9  *    N.B. in this file, in general we must use P(dev->mutex) rather
10  *      than lock_device(dev) so that we can examine the blocked
11  *      state rather than blocking ourselves. In some "safe" cases,
12  *      we can do things to a blocked device. CAREFUL!!!!
13  *
14  *    File daemon commands are handled in fdcmd.c
15  *
16  *     Kern Sibbald, May MMI
17  *
18  *   Version $Id$
19  *  
20  */
21 /*
22    Copyright (C) 2000-2003 Kern Sibbald and John Walker
23
24    This program is free software; you can redistribute it and/or
25    modify it under the terms of the GNU General Public License as
26    published by the Free Software Foundation; either version 2 of
27    the License, or (at your option) any later version.
28
29    This program is distributed in the hope that it will be useful,
30    but WITHOUT ANY WARRANTY; without even the implied warranty of
31    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32    General Public License for more details.
33
34    You should have received a copy of the GNU General Public
35    License along with this program; if not, write to the Free
36    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
37    MA 02111-1307, USA.
38
39  */
40
41 #include "bacula.h"
42 #include "stored.h"
43
44 /* Exported variables */
45
46 /* Imported variables */
47 extern BSOCK *filed_chan;
48 extern int r_first, r_last;
49 extern struct s_res resources[];
50 extern char my_name[];
51 extern time_t daemon_start_time;
52 extern struct s_last_job last_job;
53
54 /* Static variables */
55 static char derrmsg[]       = "3900 Invalid command\n";
56 static char OKsetdebug[]   = "3000 OK setdebug=%d\n";
57
58
59 /* Imported functions */
60 extern void terminate_child();
61 extern int job_cmd(JCR *jcr);
62
63 /* Forward referenced functions */
64 static int label_cmd(JCR *jcr);
65 static int relabel_cmd(JCR *jcr);
66 static int setdebug_cmd(JCR *jcr);
67 static int cancel_cmd(JCR *cjcr);
68 static int mount_cmd(JCR *jcr);
69 static int unmount_cmd(JCR *jcr);
70 static int status_cmd(JCR *sjcr);
71 static int autochanger_cmd(JCR *sjcr);
72 static int do_label(JCR *jcr, int relabel);
73 static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
74                                char *newname, char *poolname, 
75                                int Slot, int relabel);
76 static void send_blocked_status(JCR *jcr, DEVICE *dev);
77
78 struct s_cmds {
79    char *cmd;
80    int (*func)(JCR *jcr);
81 };
82
83 /*  
84  * The following are the recognized commands from the Director. 
85  */
86 static struct s_cmds cmds[] = {
87    {"JobId=",    job_cmd},            /* start Job */
88    {"setdebug=", setdebug_cmd},       /* set debug level */
89    {"cancel",    cancel_cmd},
90    {"label",     label_cmd},          /* label a tape */
91    {"relabel",   relabel_cmd},        /* relabel a tape */
92    {"mount",     mount_cmd},
93    {"unmount",   unmount_cmd},
94    {"status",    status_cmd},
95    {"autochanger", autochanger_cmd},
96    {NULL,        NULL}                /* list terminator */
97 };
98
99
100 /* 
101  * Connection request. We accept connections either from the 
102  *  Director or a Client.
103  * 
104  * Note, we are running as a seperate thread of the Storage daemon.
105  *  and it is because a Director has made a connection with
106  *  us on the "Message" channel.    
107  *
108  * Basic tasks done here:  
109  *  - Create a JCR record
110  *  - Authenticate the Director
111  *  - We wait for a command
112  *  - We execute the command
113  *  - We continue or exit depending on the return status
114  */
115 void *connection_request(void *arg)
116 {
117    BSOCK *bs = (BSOCK *)arg;
118    JCR *jcr;
119    int i, found, quit;
120    int bnet_stat = 0;
121    char name[MAX_NAME_LENGTH];
122
123    if (bnet_recv(bs) <= 0) {
124       Emsg0(M_ERROR, 0, "Connection request failed.\n");
125       return NULL;
126    }
127
128    /* 
129     * See if this is a File daemon connection
130     */
131    if (sscanf(bs->msg, "Hello Start Job %127s calling\n", name) == 1) {
132       handle_filed_connection(bs, name);
133       return NULL;
134    }
135    
136    jcr = new_jcr(sizeof(JCR), stored_free_jcr);     /* create Job Control Record */
137    jcr->dir_bsock = bs;               /* save Director bsock */
138
139    Dmsg0(1000, "stored in start_job\n");
140
141    /*
142     * Authenticate the Director
143     */
144    if (!authenticate_director(jcr)) {
145       Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate Director\n"));
146       free_jcr(jcr);
147       return NULL;
148    }
149    Dmsg0(90, "Message channel init completed.\n");
150
151    for (quit=0; !quit;) {
152
153       /* Read command */
154       if ((bnet_stat = bnet_recv(bs)) <= 0) {
155          break;                       /* connection terminated */
156       }
157       Dmsg1(9, "<dird: %s\n", bs->msg);
158       found = FALSE;
159       for (i=0; cmds[i].cmd; i++) {
160          if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
161             if (!cmds[i].func(jcr)) {    /* do command */
162                quit = TRUE;              /* error, get out */
163                Dmsg1(90, "Command %s requsts quit\n", cmds[i].cmd);
164             }
165             found = TRUE;            /* indicate command found */
166             break;
167          }
168       }
169       if (!found) {                   /* command not found */
170          bnet_fsend(bs, derrmsg);
171          quit = TRUE;
172          break;
173       }
174    }
175    if (bnet_stat != BNET_TERMINATE) {
176       bnet_sig(bs, BNET_TERMINATE);
177    }
178    free_jcr(jcr);
179    return NULL;
180 }
181
182 /*
183  * Set debug level as requested by the Director
184  *
185  */
186 static int setdebug_cmd(JCR *jcr)
187 {
188    BSOCK *dir = jcr->dir_bsock;
189    int level;
190
191    Dmsg1(10, "setdebug_cmd: %s", dir->msg);
192    if (sscanf(dir->msg, "setdebug=%d", &level) != 1 || level < 0) {
193       bnet_fsend(dir, "3991 Bad setdebug command: %s\n", dir->msg);
194       return 0;
195    }
196    debug_level = level;
197    return bnet_fsend(dir, OKsetdebug, level);
198 }
199
200
201 /*
202  * Cancel a Job
203  */
204 static int cancel_cmd(JCR *cjcr)
205 {
206    BSOCK *dir = cjcr->dir_bsock;
207    int oldStatus;
208    char Job[MAX_NAME_LENGTH];
209    JCR *jcr;
210
211    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
212       if (!(jcr=get_jcr_by_full_name(Job))) {
213          bnet_fsend(dir, _("3992 Job %s not found.\n"), Job);
214       } else {
215          P(jcr->mutex);
216          oldStatus = jcr->JobStatus;
217          set_jcr_job_status(jcr, JS_Cancelled);
218          if (!jcr->authenticated && oldStatus == JS_WaitFD) {
219             pthread_cond_signal(&jcr->job_start_wait); /* wake waiting thread */
220          }
221          V(jcr->mutex);
222          if (jcr->file_bsock) {
223             bnet_sig(jcr->file_bsock, BNET_TERMINATE);
224          }
225          /* If thread waiting on mount, wake him */
226          if (jcr->device && jcr->device->dev &&      
227               (jcr->device->dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
228                jcr->device->dev->dev_blocked == BST_UNMOUNTED ||
229                jcr->device->dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
230              pthread_cond_signal(&jcr->device->dev->wait_next_vol);
231          }
232          bnet_fsend(dir, _("3000 Job %s marked to be cancelled.\n"), jcr->Job);
233          free_jcr(jcr);
234       }
235    } else {
236       bnet_fsend(dir, _("3993 Error scanning cancel command.\n"));
237    }
238    bnet_sig(dir, BNET_EOD);
239    return 1;
240 }
241
242 /*
243  * Label a tape
244  *
245  */
246 static int label_cmd(JCR *jcr) 
247 {
248    return do_label(jcr, 0);
249 }
250
251 static int relabel_cmd(JCR *jcr) 
252 {
253    return do_label(jcr, 1);
254 }
255
256 static int do_label(JCR *jcr, int relabel)  
257 {
258    POOLMEM *dname, *newname, *oldname, *poolname, *mtype;
259    BSOCK *dir = jcr->dir_bsock;
260    DEVRES *device;
261    DEVICE *dev;
262    int found = 0, ok = 0;
263    int slot;    
264
265    dname = get_memory(dir->msglen+1);
266    newname = get_memory(dir->msglen+1);
267    oldname = get_memory(dir->msglen+1);
268    poolname = get_memory(dir->msglen+1);
269    mtype = get_memory(dir->msglen+1);
270    if (relabel) {
271       if (sscanf(dir->msg, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d",
272           dname, oldname, newname, poolname, mtype, &slot) == 6) {
273          ok = 1;
274       }
275    } else {
276       *oldname = 0;
277       if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d",
278           dname, newname, poolname, mtype, &slot) == 5) {
279          ok = 1;
280       }
281    }
282    if (ok) {
283       unbash_spaces(dname);
284       unbash_spaces(newname);
285       unbash_spaces(oldname);
286       unbash_spaces(poolname);
287       unbash_spaces(mtype);
288       device = NULL;
289       LockRes();
290       while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) {
291          /* Find resource, and make sure we were able to open it */
292          if (strcmp(device->hdr.name, dname) == 0 && device->dev) {
293             Dmsg1(20, "Found device %s\n", device->hdr.name);
294             found = 1;
295             break;
296          }
297       }
298       UnlockRes();
299       if (found) {
300          /******FIXME**** compare MediaTypes */
301          jcr->device = device;
302          dev = device->dev;
303
304          P(dev->mutex);               /* Use P to avoid indefinite block */
305          if (!(dev->state & ST_OPENED)) {
306             if (open_dev(dev, newname, READ_WRITE) < 0) {
307                bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev));
308             } else {
309                label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
310                force_close_dev(dev);
311             }
312          /* Under certain "safe" conditions, we can steal the lock */
313          } else if (dev->dev_blocked && 
314                     (dev->dev_blocked == BST_UNMOUNTED ||
315                      dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
316                      dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
317             label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
318          } else if (dev->state & ST_READ || dev->num_writers) {
319             if (dev->state & ST_READ) {
320                 bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"),
321                    dev_name(dev));
322             } else {
323                 bnet_fsend(dir, _("3902 Device %s is busy with %d writer(s).\n"),
324                    dev_name(dev), dev->num_writers);
325             }
326          } else {                     /* device not being used */
327             label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
328          }
329          V(dev->mutex);
330       } else {
331          bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
332       }
333    } else {
334       /* NB dir->msg gets clobbered in bnet_fsend, so save command */
335       strcpy(dname, dir->msg);
336       bnet_fsend(dir, _("3903 Error scanning label command: %s\n"), dname);
337    }
338    free_memory(dname);
339    free_memory(oldname);
340    free_memory(newname);
341    free_memory(poolname);
342    free_memory(mtype);
343    bnet_sig(dir, BNET_EOD);
344    return 1;
345 }
346
347 /* 
348  * Read the tape label and determine if we can safely
349  * label the tape (not a Bacula volume), then label it.
350  *
351  *  Enter with the mutex set
352  */
353 static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, 
354                                char *newname, char *poolname,
355                                int slot, int relabel)
356 {
357    BSOCK *dir = jcr->dir_bsock;
358    DEV_BLOCK *block;
359    bsteal_lock_t hold;
360    
361    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
362    
363    strcpy(jcr->VolumeName, newname);
364    jcr->VolCatInfo.Slot = slot;
365    autoload_device(jcr, dev, 0, dir);      /* autoload if possible */
366    block = new_block(dev);
367
368    /* Ensure that the device is open -- not autoload_device() closes it */
369    for ( ; !(dev->state & ST_OPENED); ) {
370        if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
371           if (dev->dev_errno == EAGAIN || dev->dev_errno == EBUSY) {
372              sleep(30);
373           }
374           bnet_fsend(dir, _("3903 Unable to open device %s. ERR=%s\n"), 
375              dev_name(dev), strerror_dev(dev));
376           goto bail_out;
377        }
378    }
379
380    /* See what we have for a Volume */
381    switch (read_dev_volume_label(jcr, dev, block)) {                
382       case VOL_NAME_ERROR:
383       case VOL_VERSION_ERROR:
384       case VOL_LABEL_ERROR:
385       case VOL_OK:
386          if (!relabel) {
387             bnet_fsend(dir, _(
388                "3901 Cannot label Volume because it is already labeled: %s\n"), 
389                 dev->VolHdr.VolName);
390             break;
391          }
392          /* Relabel request. If oldname matches, continue */
393          if (strcmp(oldname, dev->VolHdr.VolName) != 0) {
394             bnet_fsend(dir, _("Wrong volume mounted.\n"));
395             break;
396          }
397          /* Fall through wanted! */
398       case VOL_IO_ERROR:
399       case VOL_NO_LABEL:
400          if (!write_volume_label_to_dev(jcr, jcr->device, newname, poolname)) {
401             bnet_fsend(dir, _("3903 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
402             break;
403          }
404          strcpy(jcr->VolumeName, newname);
405          bnet_fsend(dir, _("3000 OK label. Volume=%s Device=%s\n"), 
406             newname, dev->dev_name);
407          break;
408       default:
409          bnet_fsend(dir, _("3902 Cannot label Volume. \
410 Unknown status %d from read_volume_label()\n"), jcr->label_status);
411          break;
412    }
413 bail_out:
414    free_block(block);
415    return_device_lock(dev, &hold);
416 }
417
418
419 /* 
420  * Read the tape label
421  *
422  *  Enter with the mutex set
423  */
424 static int read_label(JCR *jcr, DEVICE *dev)
425 {
426    int stat;
427    BSOCK *dir = jcr->dir_bsock;
428    DEV_BLOCK *block;
429 #ifndef NEW_LOCK
430    bsteal_lock_t hold;
431    
432    steal_device_lock(dev, &hold, BST_DOING_ACQUIRE);
433 #endif
434    
435    jcr->VolumeName[0] = 0;
436    block = new_block(dev);
437    dev->state &= ~ST_LABEL;           /* force read of label */
438    switch (read_dev_volume_label(jcr, dev, block)) {                
439       case VOL_OK:
440          bnet_fsend(dir, _("3001 Mounted Volume: %s\n"), dev->VolHdr.VolName);
441          stat = 1;
442          break;
443       default:
444          bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device \"%s\" because:\n%s\n"),
445             dev->dev_name, jcr->errmsg);
446          stat = 0;
447          break;
448    }
449    free_block(block);
450 #ifndef NEW_LOCK
451    return_device_lock(dev, &hold);
452 #endif
453    return stat;
454 }
455
456 /*
457  * Mount command from Director
458  */
459 static int mount_cmd(JCR *jcr)
460 {
461    char *dev_name;
462    BSOCK *dir = jcr->dir_bsock;
463    DEVRES *device;
464    DEVICE *dev;
465    int found = 0;
466
467    dev_name = (char *) get_memory(dir->msglen);
468    if (sscanf(dir->msg, "mount %s", dev_name) == 1) {
469       unbash_spaces(dev_name);
470       device = NULL;
471       LockRes();
472       while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) {
473          /* Find resource, and make sure we were able to open it */
474          if (strcmp(device->hdr.name, dev_name) == 0 && device->dev) {
475             Dmsg1(20, "Found device %s\n", device->hdr.name);
476             found = 1;
477             break;
478          }
479       }
480       UnlockRes();
481       if (found) {
482          jcr->device = device;
483          dev = device->dev;
484          P(dev->mutex);               /* Use P to avoid indefinite block */
485          switch (dev->dev_blocked) {         /* device blocked? */
486             DEV_BLOCK *block;
487             case BST_WAITING_FOR_SYSOP:
488                /* Someone is waiting, wake him */
489                Dmsg0(90, "Waiting for mount attempt to wake thread\n");
490                pthread_cond_signal(&dev->wait_next_vol);
491                bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev->dev_name);
492                break;
493
494             case BST_UNMOUNTED_WAITING_FOR_SYSOP:
495             case BST_UNMOUNTED:
496                /* We freed the device, so reopen it and wake any waiting threads */
497                if (open_dev(dev, NULL, READ_WRITE) < 0) {
498                   bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), 
499                      strerror_dev(dev));
500                   break;
501                }
502                block = new_block(dev);
503                read_dev_volume_label(jcr, dev, block);
504                free_block(block);
505                if (dev->dev_blocked == BST_UNMOUNTED) {
506                   Dmsg0(90, "Unmounted unblocking device\n");
507                   read_label(jcr, dev);
508                   unblock_device(dev);
509                } else {
510                   Dmsg0(90, "Unmounted waiting for mount attempt to wake thread\n");
511                   dev->dev_blocked = BST_WAITING_FOR_SYSOP;
512                   pthread_cond_signal(&dev->wait_next_vol);
513                }
514                if (dev->state & ST_LABEL) {
515                   bnet_fsend(dir, _("3001 Device %s is mounted with Volume %s\n"), 
516                      dev->dev_name, dev->VolHdr.VolName);
517                } else {
518                   bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
519                                     "Try unmounting and remounting the Volume.\n"),
520                              dev->dev_name);
521                }
522                break;
523
524             case BST_DOING_ACQUIRE:
525                bnet_fsend(dir, _("3001 Device %s is mounted; doing acquire.\n"), 
526                           dev->dev_name);
527                break;
528
529             case BST_WRITING_LABEL:
530                bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev->dev_name);
531                break;
532
533             case BST_NOT_BLOCKED:
534                if (dev->state & ST_OPENED) {
535                   if (dev->state & ST_LABEL) {
536                      bnet_fsend(dir, _("3001 Device %s is mounted with Volume %s\n"),
537                         dev->dev_name, dev->VolHdr.VolName);
538                   } else {
539                      bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"   
540                                     "Try unmounting and remounting the Volume.\n"),
541                                 dev->dev_name);
542                   }
543                } else {
544                   if (!dev_is_tape(dev)) {
545                      bnet_fsend(dir, _("3906 cannot mount non-tape.\n"));
546                      break;
547                   }
548                   if (open_dev(dev, NULL, READ_WRITE) < 0) {
549                      bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), 
550                         strerror_dev(dev));
551                      break;
552                   }
553                   read_label(jcr, dev);
554                   if (dev->state & ST_LABEL) {
555                      bnet_fsend(dir, _("3001 Device %s is mounted with Volume %s\n"), 
556                         dev->dev_name, dev->VolHdr.VolName);
557                   } else {
558                      bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
559                                        "Try unmounting and remounting the Volume.\n"),
560                                 dev->dev_name);
561                   }
562                }
563                break;
564
565             default:
566                bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked);
567                break;
568          }
569          V(dev->mutex);
570       } else {
571          bnet_fsend(dir, _("3999 Device %s not found\n"), dev_name);
572       }
573    } else {
574       strcpy(dev_name, dir->msg);
575       bnet_fsend(dir, _("3906 Error scanning mount command: %s\n"), dev_name);
576    }
577    free_memory(dev_name);
578    bnet_sig(dir, BNET_EOD);
579    return 1;
580 }
581
582 /*
583  * unmount command from Director
584  */
585 static int unmount_cmd(JCR *jcr)
586 {
587    char *dname;
588    BSOCK *dir = jcr->dir_bsock;
589    DEVRES *device;
590    DEVICE *dev;
591    int found = 0;
592
593    dname = (char *) get_memory(dir->msglen+1);
594    if (sscanf(dir->msg, "unmount %s", dname) == 1) {
595       unbash_spaces(dname);
596       device = NULL;
597       LockRes();
598       while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) {
599          /* Find resource, and make sure we were able to open it */
600          if (strcmp(device->hdr.name, dname) == 0 && device->dev) {
601             Dmsg1(20, "Found device %s\n", device->hdr.name);
602             found = 1;
603             break;
604          }
605       }
606       UnlockRes();
607       if (found) {
608          jcr->device = device;
609          dev = device->dev;
610          P(dev->mutex);               /* Use P to avoid indefinite block */
611          if (!(dev->state & ST_OPENED)) {
612             Dmsg0(90, "Device already unmounted\n");
613             bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), dev_name(dev));
614
615          } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
616             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
617                dev->dev_blocked);
618             if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
619                offline_dev(dev);
620             }
621             force_close_dev(dev);
622             dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
623             bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev_name(dev));
624
625          } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
626             bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"),
627                dev_name(dev));
628
629          } else if (dev->dev_blocked == BST_WRITING_LABEL) {
630             bnet_fsend(dir, _("3903 Device %s is being labeled.\n"),
631                dev_name(dev));
632
633          } else if (dev->state & ST_READ || dev->num_writers) {
634             if (dev->state & ST_READ) {
635                 Dmsg0(90, "Device in read mode\n");
636                 bnet_fsend(dir, _("3904 Device %s is busy with 1 reader.\n"),
637                    dev_name(dev));
638             } else {
639                 Dmsg1(90, "Device busy with %d writers\n", dev->num_writers);
640                 bnet_fsend(dir, _("3905 Device %s is busy with %d writer(s).\n"),
641                    dev_name(dev), dev->num_writers);
642             }
643
644          } else {                     /* device not being used */
645             Dmsg0(90, "Device not in use, unmounting\n");
646             block_device(dev, BST_UNMOUNTED);
647             if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
648                offline_dev(dev);
649             }
650             force_close_dev(dev);
651             bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev_name(dev));
652          }
653          V(dev->mutex);
654       } else {
655          bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
656       }
657    } else {
658       /* NB dir->msg gets clobbered in bnet_fsend, so save command */
659       strcpy(dname, dir->msg);
660       bnet_fsend(dir, _("3907 Error scanning unmount command: %s\n"), dname);
661    }
662    free_memory(dname);
663    bnet_sig(dir, BNET_EOD);
664    return 1;
665 }
666
667 /*
668  * Status command from Director
669  */
670 static int status_cmd(JCR *jcr)
671 {
672    DEVRES *device;
673    DEVICE *dev;
674    int found, bps, sec, bpb;
675    BSOCK *user = jcr->dir_bsock;
676    char dt[MAX_TIME_LENGTH];
677    char b1[30], b2[30], b3[30];
678
679    bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ")\n", my_name);
680    bstrftime(dt, sizeof(dt), daemon_start_time);
681    bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
682         last_job.NumJobs == 1 ? "" : "s");
683    if (last_job.NumJobs > 0) {
684       char termstat[30];
685
686       bstrftime(dt, sizeof(dt), last_job.end_time);
687       bnet_fsend(user, _("Last Job %s finished at %s\n"), last_job.Job, dt);
688
689       jobstatus_to_ascii(last_job.JobStatus, termstat, sizeof(termstat));
690       bnet_fsend(user, _("  Files=%s Bytes=%s Termination Status=%s\n"), 
691            edit_uint64_with_commas(last_job.JobFiles, b1),
692            edit_uint64_with_commas(last_job.JobBytes, b2),
693            termstat);
694    }
695
696    LockRes();
697    for (device=NULL;  (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
698       for (dev=device->dev; dev; dev=dev->next) {
699          if (dev->state & ST_OPENED) {
700             if (dev->state & ST_LABEL) {
701                bnet_fsend(user, _("Device %s is mounted with Volume %s\n"), 
702                   dev_name(dev), dev->VolHdr.VolName);
703             } else {
704                bnet_fsend(user, _("Device %s open but no Bacula volume is mounted.\n"), dev_name(dev));
705             }
706             send_blocked_status(jcr, dev);
707             bpb = dev->VolCatInfo.VolCatBlocks;
708             if (bpb <= 0) {
709                bpb = 1;
710             }
711             bpb = dev->VolCatInfo.VolCatBytes / bpb;
712             bnet_fsend(user, _("    Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
713                edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
714                edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), 
715                edit_uint64_with_commas(bpb, b3));
716             bnet_fsend(user, _("    Positioned at File=%s Block=%s\n"), 
717                edit_uint64_with_commas(dev->file, b1),
718                edit_uint64_with_commas(dev->block_num, b2));
719
720          } else {
721             bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev));
722             send_blocked_status(jcr, dev);
723          }
724       }
725    }
726    UnlockRes();
727
728    found = 0;
729    lock_jcr_chain();
730    /* NOTE, we reuse a calling argument jcr. Be warned! */ 
731    for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
732       if (jcr->JobStatus == JS_WaitFD) {
733          bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
734             job_type_to_str(jcr->JobType), jcr->Job);
735       }
736       if (jcr->device) {
737          bnet_fsend(user, _("%s %s job %s is using device %s volume %s\n"), 
738                    job_level_to_str(jcr->JobLevel),
739                    job_type_to_str(jcr->JobType),
740                    jcr->Job, jcr->device->device_name,
741                    jcr->VolumeName);
742          sec = time(NULL) - jcr->run_time;
743          if (sec <= 0) {
744             sec = 1;
745          }
746          bps = jcr->JobBytes / sec;
747          bnet_fsend(user, _("    Files=%s Bytes=%s Bytes/sec=%s\n"), 
748             edit_uint64_with_commas(jcr->JobFiles, b1),
749             edit_uint64_with_commas(jcr->JobBytes, b2),
750             edit_uint64_with_commas(bps, b3));
751          found = 1;
752 #ifdef DEBUG
753          if (jcr->file_bsock) {
754             bnet_fsend(user, "    FDReadSeqNo=%" lld " fd=%d\n", 
755                jcr->file_bsock->read_seqno, jcr->file_bsock->fd);
756          } else {
757             bnet_fsend(user, "    FDSocket closed\n");
758          }
759 #endif
760       }
761       free_locked_jcr(jcr);
762    }
763    unlock_jcr_chain();
764    if (!found) {
765       bnet_fsend(user, _("No jobs running.\n"));
766    }
767
768 #ifdef full_status
769    bnet_fsend(user, "\n\n");
770    dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user);
771 #endif
772    bnet_fsend(user, "====\n");
773
774    bnet_sig(user, BNET_EOD);
775    return 1;
776 }
777
778 static void send_blocked_status(JCR *jcr, DEVICE *dev) 
779 {
780    BSOCK *user = jcr->dir_bsock;
781
782    switch (dev->dev_blocked) {
783       case BST_UNMOUNTED:
784          bnet_fsend(user, _("    Device is BLOCKED. User unmounted.\n"));
785          break;
786       case BST_UNMOUNTED_WAITING_FOR_SYSOP:
787          bnet_fsend(user, _("    Device is BLOCKED. User unmounted during wait for media/mount.\n"));
788          break;
789       case BST_WAITING_FOR_SYSOP:
790          if (jcr->JobStatus == JS_WaitMount) {
791             bnet_fsend(user, _("    Device is BLOCKED waiting for mount.\n"));
792          } else {
793             bnet_fsend(user, _("    Device is BLOCKED waiting for appendable media.\n"));
794          }
795          break;
796       case BST_DOING_ACQUIRE:
797          bnet_fsend(user, _("    Device is being initialized.\n"));
798          break;
799       case BST_WRITING_LABEL:
800          bnet_fsend(user, _("    Device is blocked labeling a Volume.\n"));
801          break;
802       default:
803          break;
804    }
805 }
806
807 /*
808  * Autochanger command from Director
809  */
810 static int autochanger_cmd(JCR *jcr)
811 {
812    char *devname;
813    BSOCK *dir = jcr->dir_bsock;
814    DEVRES *device;
815    DEVICE *dev;
816    int found = 0;
817
818    devname = (char *)get_memory(dir->msglen);
819    if (sscanf(dir->msg, "autochanger list %s ", devname) == 1) {
820       unbash_spaces(devname);
821       device = NULL;
822       LockRes();
823       while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) {
824          /* Find resource, and make sure we were able to open it */
825          if (strcmp(device->hdr.name, devname) == 0 && device->dev) {
826             Dmsg1(20, "Found device %s\n", device->hdr.name);
827             found = 1;
828             break;
829          }
830       }
831       UnlockRes();
832       if (found) {
833          jcr->device = device;
834          dev = device->dev;
835          P(dev->mutex);               /* Use P to avoid indefinite block */
836          if (!(dev->state & ST_OPENED)) {
837             if (open_dev(dev, NULL, READ_WRITE) < 0) {
838                bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev));
839             } else {
840                autochanger_list(jcr, dev, dir);
841                force_close_dev(dev);
842             }
843          /* Under certain "safe" conditions, we can steal the lock */
844          } else if (dev->dev_blocked && 
845                     (dev->dev_blocked == BST_UNMOUNTED ||
846                      dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
847                      dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
848             autochanger_list(jcr, dev, dir);
849          } else if (dev->state & ST_READ || dev->num_writers) {
850             if (dev->state & ST_READ) {
851                 bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"),
852                    dev_name(dev));
853             } else {
854                 bnet_fsend(dir, _("3902 Device %s is busy with %d writer(s).\n"),
855                    dev_name(dev), dev->num_writers);
856             }
857          } else {                     /* device not being used */
858             autochanger_list(jcr, dev, dir);
859          }
860          V(dev->mutex);
861       } else {
862          bnet_fsend(dir, _("3999 Device %s not found\n"), devname);
863       }
864    } else {
865       strcpy(devname, dir->msg);
866       bnet_fsend(dir, _("3907 Error scanning autocharger list command: %s\n"), devname);
867    }
868    free_memory(devname);
869    bnet_sig(dir, BNET_EOD);
870    return 1;
871 }