]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/dircmd.c
Add wait on bad connection for security
[bacula/bacula] / bacula / src / stored / dircmd.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2012 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 three of the GNU Affero 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 Affero 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 Kern Sibbald.
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  *  This file handles accepting Director Commands
30  *
31  *    Most Director commands are handled here, with the
32  *    exception of the Job command command and subsequent
33  *    subcommands that are handled
34  *    in job.c.
35  *
36  *    N.B. in this file, in general we must use P(dev->mutex) rather
37  *      than dev->r_lock() so that we can examine the blocked
38  *      state rather than blocking ourselves because a Job
39  *      thread has the device blocked. In some "safe" cases,
40  *      we can do things to a blocked device. CAREFUL!!!!
41  *
42  *    File daemon commands are handled in fdcmd.c
43  *
44  *     Kern Sibbald, May MMI
45  *
46  */
47
48 #include "bacula.h"
49 #include "stored.h"
50
51 /* Exported variables */
52
53 /* Imported variables */
54 extern BSOCK *filed_chan;
55 extern struct s_last_job last_job;
56 extern bool init_done;
57
58 /* Static variables */
59 static char derrmsg[]     = "3900 Invalid command:";
60 static char OKsetdebug[]  = "3000 OK setdebug=%d\n";
61 static char invalid_cmd[] = "3997 Invalid command for a Director with Monitor directive enabled.\n";
62 static char OK_bootstrap[]    = "3000 OK bootstrap\n";
63 static char ERROR_bootstrap[] = "3904 Error bootstrap\n";
64
65 /* Imported functions */
66 extern void terminate_child();
67 extern bool job_cmd(JCR *jcr);
68 extern bool use_cmd(JCR *jcr);
69 extern bool run_cmd(JCR *jcr);
70 extern bool status_cmd(JCR *sjcr);
71 extern bool qstatus_cmd(JCR *jcr);
72 //extern bool query_cmd(JCR *jcr);
73
74 /* Forward referenced functions */
75 static bool label_cmd(JCR *jcr);
76 static bool die_cmd(JCR *jcr);
77 static bool relabel_cmd(JCR *jcr);
78 static bool readlabel_cmd(JCR *jcr);
79 static bool release_cmd(JCR *jcr);
80 static bool setdebug_cmd(JCR *jcr);
81 static bool cancel_cmd(JCR *cjcr);
82 static bool mount_cmd(JCR *jcr);
83 static bool unmount_cmd(JCR *jcr);
84 //static bool action_on_purge_cmd(JCR *jcr);
85 static bool bootstrap_cmd(JCR *jcr);
86 static bool changer_cmd(JCR *sjcr);
87 static bool do_label(JCR *jcr, int relabel);
88 static DCR *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
89 static void read_volume_label(JCR *jcr, DCR *dcr, DEVICE *dev, int Slot);
90 static void label_volume_if_ok(DCR *dcr, char *oldname,
91                                char *newname, char *poolname,
92                                int Slot, int relabel);
93 static bool try_autoload_device(JCR *jcr, DCR *dcr, int slot, const char *VolName);
94 static void send_dir_busy_message(BSOCK *dir, DEVICE *dev);
95
96 struct s_cmds {
97    const char *cmd;
98    bool (*func)(JCR *jcr);
99    bool monitoraccess;                      /* set if monitors can access this cmd */
100 };
101
102 /*
103  * The following are the recognized commands from the Director.
104  */
105 static struct s_cmds cmds[] = {
106    {"JobId=",      job_cmd,         0},     /* start Job */
107    {"autochanger", changer_cmd,     0},
108    {"bootstrap",   bootstrap_cmd,   0},
109    {"cancel",      cancel_cmd,      0},
110    {".die",        die_cmd,         0},
111    {"label",       label_cmd,       0},     /* label a tape */
112    {"mount",       mount_cmd,       0},
113    {"readlabel",   readlabel_cmd,   0},
114    {"release",     release_cmd,     0},
115    {"relabel",     relabel_cmd,     0},     /* relabel a tape */
116    {"setdebug=",   setdebug_cmd,    0},     /* set debug level */
117    {"status",      status_cmd,      1},
118    {".status",     qstatus_cmd,     1},
119    {"unmount",     unmount_cmd,     0},
120 //   {"action_on_purge",  action_on_purge_cmd,    0},
121    {"use storage=", use_cmd,        0},
122    {"run",         run_cmd,         0},
123 // {"query",       query_cmd,       0},
124    {NULL,        NULL}                      /* list terminator */
125 };
126
127
128 /*
129  * Connection request. We accept connections either from the
130  *  Director or a Client (File daemon).
131  *
132  * Note, we are running as a seperate thread of the Storage daemon.
133  *  and it is because a Director has made a connection with
134  *  us on the "Message" channel.
135  *
136  * Basic tasks done here:
137  *  - Create a JCR record
138  *  - If it was from the FD, call handle_filed_connection()
139  *  - Authenticate the Director
140  *  - We wait for a command
141  *  - We execute the command
142  *  - We continue or exit depending on the return status
143  */
144 void *handle_connection_request(void *arg)
145 {
146    BSOCK *bs = (BSOCK *)arg;
147    JCR *jcr;
148    int i;
149    bool found, quit;
150    int bnet_stat = 0;
151    char name[500];
152    char tbuf[100];
153
154    if (bs->recv() <= 0) {
155       Emsg1(M_ERROR, 0, _("Connection request from %s failed.\n"), bs->who());
156       bmicrosleep(5, 0);   /* make user wait 5 seconds */
157       bs->close();
158       return NULL;
159    }
160
161    /*
162     * Do a sanity check on the message received
163     */
164    if (bs->msglen < 25 || bs->msglen > (int)sizeof(name)) {
165       Dmsg1(000, "<filed: %s", bs->msg);
166       Emsg2(M_ERROR, 0, _("Invalid connection from %s. Len=%d\n"), bs->who(), bs->msglen);
167       bmicrosleep(5, 0);   /* make user wait 5 seconds */
168       bs->close();
169       return NULL;
170    }
171    /*
172     * See if this is a File daemon connection. If so
173     *   call FD handler.
174     */
175    Dmsg1(110, "Conn: %s", bs->msg);
176    if (debug_level == 3) {
177       Dmsg1(000, "<filed: %s", bs->msg);
178    }
179    if (sscanf(bs->msg, "Hello Start Job %127s", name) == 1) {
180       Dmsg1(110, "Got a FD connection at %s\n", bstrftimes(tbuf, sizeof(tbuf), 
181             (utime_t)time(NULL)));
182       Dmsg1(50, "%s", bs->msg);
183       handle_filed_connection(bs, name);
184       return NULL;
185    }
186
187    /* 
188     * This is a connection from the Director, so setup a JCR 
189     */
190    Dmsg1(110, "Got a DIR connection at %s\n", bstrftimes(tbuf, sizeof(tbuf), 
191          (utime_t)time(NULL)));
192    jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */
193    jcr->dir_bsock = bs;               /* save Director bsock */
194    jcr->dir_bsock->set_jcr(jcr);
195    jcr->dcrs = New(alist(10, not_owned_by_alist));
196    /* Initialize FD start condition variable */
197    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
198    if (errstat != 0) {
199       berrno be;
200       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
201       goto bail_out;
202    }
203
204    Dmsg0(1000, "stored in start_job\n");
205
206    /*
207     * Authenticate the Director
208     */
209    if (!authenticate_director(jcr)) {
210       Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate Director\n"));
211       goto bail_out;
212    }
213    Dmsg0(90, "Message channel init completed.\n");
214
215    for (quit=false; !quit;) {
216       /* Read command */
217       if ((bnet_stat = bs->recv()) <= 0) {
218          break;               /* connection terminated */
219       }
220       Dmsg1(199, "<dird: %s\n", bs->msg);
221       /* Ensure that device initialization is complete */
222       while (!init_done) {
223          bmicrosleep(1, 0);
224       }
225       found = false;
226       for (i=0; cmds[i].cmd; i++) {
227         if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
228            if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
229               Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
230               bs->fsend(invalid_cmd);
231               bs->signal(BNET_EOD);
232               break;
233            }
234            Dmsg1(200, "Do command: %s\n", cmds[i].cmd);
235            if (!cmds[i].func(jcr)) { /* do command */
236               quit = true; /* error, get out */
237               Dmsg1(190, "Command %s requests quit\n", cmds[i].cmd);
238            }
239            found = true;             /* indicate command found */
240            break;
241         }
242       }
243       if (!found) {                   /* command not found */
244         POOL_MEM err_msg;
245         Mmsg(err_msg, "%s %s\n", derrmsg, bs->msg);
246         bs->fsend(err_msg.c_str());
247         break;
248       }
249    }
250 bail_out:
251    generate_daemon_event(jcr, "JobEnd");
252    dequeue_messages(jcr);             /* send any queued messages */
253    bs->signal(BNET_TERMINATE);
254    free_jcr(jcr);
255    return NULL;
256 }
257
258
259 /*
260  * Force SD to die, and hopefully dump itself.  Turned on only
261  *  in development version.
262  */
263 static bool die_cmd(JCR *jcr)
264 {
265 #ifdef DEVELOPER
266    JCR *djcr = NULL;
267    int a;
268    BSOCK *dir = jcr->dir_bsock;
269    pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
270
271    if (strstr(dir->msg, "deadlock")) {
272       Pmsg0(000, "I have been requested to deadlock ...\n");
273       P(m);
274       P(m);
275    }
276    
277    Pmsg1(000, "I have been requested to die ... (%s)\n", dir->msg);
278    a = djcr->JobId;   /* ref NULL pointer */
279 #endif
280    return 0;
281 }
282
283      
284
285 /*
286  * Set debug level as requested by the Director
287  *
288  */
289 static bool setdebug_cmd(JCR *jcr)
290 {
291    BSOCK *dir = jcr->dir_bsock;
292    int32_t level, trace_flag;
293
294    Dmsg1(10, "setdebug_cmd: %s", dir->msg);
295    if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) {
296       dir->fsend(_("3991 Bad setdebug command: %s\n"), dir->msg);
297       return 0;
298    }
299    debug_level = level;
300    set_trace(trace_flag);
301    return dir->fsend(OKsetdebug, level);
302 }
303
304
305 /*
306  * Cancel a Job
307  *   Be careful, we switch to using the job's JCR! So, using
308  *   BSOCKs on that jcr can have two threads in the same code.
309  */
310 static bool cancel_cmd(JCR *cjcr)
311 {
312    BSOCK *dir = cjcr->dir_bsock;
313    int oldStatus;
314    char Job[MAX_NAME_LENGTH];
315    JCR *jcr;
316
317    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
318       if (!(jcr=get_jcr_by_full_name(Job))) {
319          dir->fsend(_("3904 Job %s not found.\n"), Job);
320       } else {
321          oldStatus = jcr->JobStatus;
322          jcr->setJobStatus(JS_Canceled);
323          Dmsg2(800, "Cancel JobId=%d %p\n", jcr->JobId, jcr);
324          if (!jcr->authenticated && oldStatus == JS_WaitFD) {
325             pthread_cond_signal(&jcr->job_start_wait); /* wake waiting thread */
326          }
327          if (jcr->file_bsock) {
328             jcr->file_bsock->set_terminated();
329             jcr->file_bsock->set_timed_out();
330             Dmsg2(800, "Term bsock jid=%d %p\n", jcr->JobId, jcr);
331          } else {
332             /* Still waiting for FD to connect, release it */
333             pthread_cond_signal(&jcr->job_start_wait); /* wake waiting job */
334             Dmsg2(800, "Signal FD connect jid=%d %p\n", jcr->JobId, jcr);
335          }
336          /* If thread waiting on mount, wake him */
337          if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->waiting_for_mount()) {
338             pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
339             Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
340             pthread_cond_broadcast(&wait_device_release);
341          }
342          if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->waiting_for_mount()) {
343             pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
344             Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
345             pthread_cond_broadcast(&wait_device_release);
346          }
347          dir->fsend(_("3000 JobId=%ld Job=\"%s\" marked to be canceled.\n"), jcr->JobId, jcr->Job);
348          free_jcr(jcr);
349       }
350    } else {
351       dir->fsend(_("3903 Error scanning cancel command.\n"));
352    }
353    dir->signal(BNET_EOD);
354    return 1;
355 }
356
357 /*
358  * Label a Volume
359  *
360  */
361 static bool label_cmd(JCR *jcr)
362 {
363    return do_label(jcr, 0);
364 }
365
366 static bool relabel_cmd(JCR *jcr)
367 {
368    return do_label(jcr, 1);
369 }
370
371 static bool do_label(JCR *jcr, int relabel)
372 {
373    POOLMEM *newname, *oldname, *poolname, *mtype;
374    POOL_MEM dev_name;
375    BSOCK *dir = jcr->dir_bsock;
376    DCR *dcr;
377    DEVICE *dev;
378    bool ok = false;
379    int32_t slot, drive;
380
381    newname = get_memory(dir->msglen+1);
382    oldname = get_memory(dir->msglen+1);
383    poolname = get_memory(dir->msglen+1);
384    mtype = get_memory(dir->msglen+1);
385    if (relabel) {
386       if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s "
387                  "MediaType=%127s Slot=%d drive=%d",
388                   dev_name.c_str(), oldname, newname, poolname, mtype, 
389                   &slot, &drive) == 7) {
390          ok = true;
391       }
392    } else {
393       *oldname = 0;
394       if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s "
395                  "MediaType=%127s Slot=%d drive=%d", 
396           dev_name.c_str(), newname, poolname, mtype, &slot, &drive) == 6) {
397          ok = true;
398       }
399    }
400    if (ok) {
401       unbash_spaces(newname);
402       unbash_spaces(oldname);
403       unbash_spaces(poolname);
404       unbash_spaces(mtype);
405       dcr = find_device(jcr, dev_name, drive);
406       if (dcr) {
407          dev = dcr->dev;
408          dev->dlock();                 /* Use P to avoid indefinite block */
409          if (!dev->is_open() && !dev->is_busy()) {
410             Dmsg1(400, "Can %slabel. Device is not open\n", relabel?"re":"");
411             label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
412             dev->close();
413          /* Under certain "safe" conditions, we can steal the lock */
414          } else if (dev->can_steal_lock()) {
415             Dmsg0(400, "Can relabel. can_steal_lock\n");
416             label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
417          } else if (dev->is_busy() || dev->is_blocked()) {
418             send_dir_busy_message(dir, dev);
419          } else {                     /* device not being used */
420             Dmsg0(400, "Can relabel. device not used\n");
421             label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
422          }
423          dev->dunlock();
424          free_dcr(dcr);
425       } else {
426          dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), dev_name.c_str());
427       }
428    } else {
429       /* NB dir->msg gets clobbered in bnet_fsend, so save command */
430       pm_strcpy(jcr->errmsg, dir->msg);
431       dir->fsend(_("3903 Error scanning label command: %s\n"), jcr->errmsg);
432    }
433    free_memory(oldname);
434    free_memory(newname);
435    free_memory(poolname);
436    free_memory(mtype);
437    dir->signal(BNET_EOD);
438    return true;
439 }
440
441 /*
442  * Read the tape label and determine if we can safely
443  * label the tape (not a Bacula volume), then label it.
444  *
445  *  Enter with the mutex set
446  */
447 static void label_volume_if_ok(DCR *dcr, char *oldname,
448                                char *newname, char *poolname,
449                                int slot, int relabel)
450 {
451    BSOCK *dir = dcr->jcr->dir_bsock;
452    bsteal_lock_t hold;
453    DEVICE *dev = dcr->dev;
454    int label_status;
455    int mode;
456    const char *volname = (relabel == 1) ? oldname : newname;
457    char ed1[50];
458
459    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
460    Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name());
461
462
463    Dmsg0(90, "try_autoload_device - looking for volume_info\n");
464    if (!try_autoload_device(dcr->jcr, dcr, slot, volname)) {
465       goto bail_out;                  /* error */
466    }
467
468    /* Ensure that the device is open -- autoload_device() closes it */
469    if (dev->is_tape()) {
470       mode = OPEN_READ_WRITE;
471    } else {
472       mode = CREATE_READ_WRITE;
473    }
474
475    if (relabel) {
476       dev->truncating = true;         /* let open() know we will truncate it */
477    }
478    /* Set old volume name for open if relabeling */
479    dcr->setVolCatName(volname);
480    if (dev->open(dcr, mode) < 0) {
481       dir->fsend(_("3910 Unable to open device \"%s\": ERR=%s\n"),
482          dev->print_name(), dev->bstrerror());
483       goto bail_out;      
484    }
485
486    /* See what we have for a Volume */
487    label_status = read_dev_volume_label(dcr);
488    
489    /* Set new volume name */
490    dcr->setVolCatName(newname);
491    switch(label_status) {
492    case VOL_NAME_ERROR:
493    case VOL_VERSION_ERROR:
494    case VOL_LABEL_ERROR:
495    case VOL_OK:
496       if (!relabel) {
497          dir->fsend(_(
498             "3920 Cannot label Volume because it is already labeled: \"%s\"\n"),
499              dev->VolHdr.VolumeName);
500          break;
501       }
502
503       /* Relabel request. If oldname matches, continue */
504       if (strcmp(oldname, dev->VolHdr.VolumeName) != 0) {
505          dir->fsend(_("3921 Wrong volume mounted.\n"));
506          break;
507       }
508       if (dev->label_type != B_BACULA_LABEL) {
509          dir->fsend(_("3922 Cannot relabel an ANSI/IBM labeled Volume.\n"));
510          break;
511       }
512       /* Fall through wanted! */
513    case VOL_IO_ERROR:
514    case VOL_NO_LABEL:
515       if (!write_new_volume_label_to_dev(dcr, newname, poolname, 
516            relabel, true /* write dvd now */)) {
517          dir->fsend(_("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
518          break;
519       }
520       bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
521       /* The following 3000 OK label. string is scanned in ua_label.c */
522       dir->fsend("3000 OK label. VolBytes=%s DVD=%d Volume=\"%s\" Device=%s\n",
523                  edit_uint64(dev->VolCatInfo.VolCatBytes, ed1),
524                  dev->is_dvd()?1:0, newname, dev->print_name());
525       break;
526    case VOL_NO_MEDIA:
527       dir->fsend(_("3914 Failed to label Volume (no media): ERR=%s\n"), dev->bstrerror());
528       break;
529    default:
530       dir->fsend(_("3913 Cannot label Volume. "
531 "Unknown status %d from read_volume_label()\n"), label_status);
532       break;
533    }
534
535 bail_out:
536    if (!dev->is_open()) {
537       dev->clear_volhdr();
538    }
539    volume_unused(dcr);                   /* no longer using volume */
540    give_back_device_lock(dev, &hold);
541    return;
542 }
543
544
545 /*
546  * Read the tape label
547  *
548  *  Enter with the mutex set
549  */
550 static bool read_label(DCR *dcr)
551 {
552    int ok;
553    JCR *jcr = dcr->jcr;
554    BSOCK *dir = jcr->dir_bsock;
555    bsteal_lock_t hold;
556    DEVICE *dev = dcr->dev;
557
558    steal_device_lock(dev, &hold, BST_DOING_ACQUIRE);
559
560    dcr->VolumeName[0] = 0;
561    dev->clear_labeled();              /* force read of label */
562    switch (read_dev_volume_label(dcr)) {
563    case VOL_OK:
564       dir->fsend(_("3001 Mounted Volume: %s\n"), dev->VolHdr.VolumeName);
565       ok = true;
566       break;
567    default:
568       dir->fsend(_("3902 Cannot mount Volume on Storage Device \"%s\" because:\n%s"),
569          dev->print_name(), jcr->errmsg);
570       ok = false;
571       break;
572    }
573    volume_unused(dcr);
574    give_back_device_lock(dev, &hold);
575    return ok;
576 }
577
578 /* 
579  * Searches for device by name, and if found, creates a dcr and
580  *  returns it.
581  */
582 static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive)
583 {
584    DEVRES *device;
585    AUTOCHANGER *changer;
586    bool found = false;
587    DCR *dcr = NULL;
588
589    unbash_spaces(devname);
590    foreach_res(device, R_DEVICE) {
591       /* Find resource, and make sure we were able to open it */
592       if (strcmp(device->hdr.name, devname.c_str()) == 0) {
593          if (!device->dev) {
594             device->dev = init_dev(jcr, device);
595          }
596          if (!device->dev) {
597             Jmsg(jcr, M_WARNING, 0, _("\n"
598                "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
599                  devname.c_str());
600             continue;
601          }
602          Dmsg1(20, "Found device %s\n", device->hdr.name);
603          found = true;
604          break;
605       }
606    }
607    if (!found) {
608       foreach_res(changer, R_AUTOCHANGER) {
609          /* Find resource, and make sure we were able to open it */
610          if (strcmp(devname.c_str(), changer->hdr.name) == 0) {
611             /* Try each device in this AutoChanger */
612             foreach_alist(device, changer->device) {
613                Dmsg1(100, "Try changer device %s\n", device->hdr.name);
614                if (!device->dev) {
615                   device->dev = init_dev(jcr, device);
616                }
617                if (!device->dev) {
618                   Dmsg1(100, "Device %s could not be opened. Skipped\n", devname.c_str());
619                   Jmsg(jcr, M_WARNING, 0, _("\n"
620                      "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
621                        device->hdr.name, devname.c_str());
622                   continue;
623                }
624                if (!device->dev->autoselect) {
625                   Dmsg1(100, "Device %s not autoselect skipped.\n", devname.c_str());
626                   continue;              /* device is not available */
627                }
628                if (drive < 0 || drive == (int)device->dev->drive_index) {
629                   Dmsg1(20, "Found changer device %s\n", device->hdr.name);
630                   found = true;
631                   break;
632                }
633                Dmsg3(100, "Device %s drive wrong: want=%d got=%d skipping\n",
634                   devname.c_str(), drive, (int)device->dev->drive_index);
635             }
636             break;                    /* we found it but could not open a device */
637          }
638       }
639    }
640
641    if (found) {
642       Dmsg1(100, "Found device %s\n", device->hdr.name);
643       dcr = new_dcr(jcr, NULL, device->dev);
644       dcr->device = device;
645    }
646    return dcr;
647 }
648
649
650 /*
651  * Mount command from Director
652  */
653 static bool mount_cmd(JCR *jcr)
654 {
655    POOL_MEM devname;
656    BSOCK *dir = jcr->dir_bsock;
657    DEVICE *dev;
658    DCR *dcr;
659    int32_t drive;
660    int32_t slot = 0;
661    bool ok;
662
663    ok = sscanf(dir->msg, "mount %127s drive=%d slot=%d", devname.c_str(), 
664                &drive, &slot) == 3;
665    if (!ok) {
666       ok = sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2;
667    }
668    Dmsg3(100, "ok=%d drive=%d slot=%d\n", ok, drive, slot);
669    if (ok) {
670       dcr = find_device(jcr, devname, drive);
671       if (dcr) {
672          dev = dcr->dev;
673          dev->dlock();                 /* Use P to avoid indefinite block */
674          Dmsg2(100, "mount cmd blocked=%d must_unload=%d\n", dev->blocked(), 
675             dev->must_unload());
676          switch (dev->blocked()) {         /* device blocked? */
677          case BST_WAITING_FOR_SYSOP:
678             /* Someone is waiting, wake him */
679             Dmsg0(100, "Waiting for mount. Attempting to wake thread\n");
680             dev->set_blocked(BST_MOUNT);
681             dir->fsend("3001 OK mount requested. %sDevice=%s\n", 
682                        slot>0?_("Specified slot ignored. "):"",
683                        dev->print_name());
684             pthread_cond_broadcast(&dev->wait_next_vol);
685             Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId);
686             pthread_cond_broadcast(&wait_device_release);
687             break;
688
689          /* In both of these two cases, we (the user) unmounted the Volume */
690          case BST_UNMOUNTED_WAITING_FOR_SYSOP:
691          case BST_UNMOUNTED:
692             Dmsg2(100, "Unmounted changer=%d slot=%d\n", dev->is_autochanger(), slot);
693             if (dev->is_autochanger() && slot > 0) {
694                try_autoload_device(jcr, dcr, slot, "");
695             }
696             /* We freed the device, so reopen it and wake any waiting threads */
697             if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
698                dir->fsend(_("3901 Unable to open device \"%s\": ERR=%s\n"),
699                   dev->print_name(), dev->bstrerror());
700                if (dev->blocked() == BST_UNMOUNTED) {
701                   /* We blocked the device, so unblock it */
702                   Dmsg0(100, "Unmounted. Unblocking device\n");
703                   unblock_device(dev);
704                }
705                break;
706             }
707             read_dev_volume_label(dcr);
708             if (dev->blocked() == BST_UNMOUNTED) {
709                /* We blocked the device, so unblock it */
710                Dmsg0(100, "Unmounted. Unblocking device\n");
711                read_label(dcr);       /* this should not be necessary */
712                unblock_device(dev);
713             } else {
714                Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n");
715                dev->set_blocked(BST_MOUNT);
716             }
717             if (dev->is_labeled()) {
718                dir->fsend(_("3001 Device \"%s\" is mounted with Volume \"%s\"\n"),
719                   dev->print_name(), dev->VolHdr.VolumeName);
720             } else {
721                dir->fsend(_("3905 Device \"%s\" open but no Bacula volume is mounted.\n"
722                                  "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
723                           dev->print_name());
724             }
725             pthread_cond_broadcast(&dev->wait_next_vol);
726             Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId);
727             pthread_cond_broadcast(&wait_device_release);
728             break;
729
730          case BST_DOING_ACQUIRE:
731             dir->fsend(_("3001 Device \"%s\" is doing acquire.\n"),
732                        dev->print_name());
733             break;
734
735          case BST_WRITING_LABEL:
736             dir->fsend(_("3903 Device \"%s\" is being labeled.\n"), 
737                dev->print_name());
738             break;
739
740          case BST_NOT_BLOCKED:
741             Dmsg2(100, "Not blocked changer=%d slot=%d\n", dev->is_autochanger(), slot);
742             if (dev->is_autochanger() && slot > 0) {
743                try_autoload_device(jcr, dcr, slot, "");
744             }
745             if (dev->is_open()) {
746                if (dev->is_labeled()) {
747                   dir->fsend(_("3001 Device \"%s\" is mounted with Volume \"%s\"\n"),
748                      dev->print_name(), dev->VolHdr.VolumeName);
749                } else {
750                   dir->fsend(_("3905 Device \"%s\" open but no Bacula volume is mounted.\n"
751                                  "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
752                              dev->print_name());
753                }
754             } else if (dev->is_tape()) {
755                if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
756                   dir->fsend(_("3901 Unable to open device \"%s\": ERR=%s\n"),
757                      dev->print_name(), dev->bstrerror());
758                   break;
759                }
760                read_label(dcr);
761                if (dev->is_labeled()) {
762                   dir->fsend(_("3001 Device \"%s\" is already mounted with Volume \"%s\"\n"),
763                      dev->print_name(), dev->VolHdr.VolumeName);
764                } else {
765                   dir->fsend(_("3905 Device \"%s\" open but no Bacula volume is mounted.\n"
766                                     "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
767                              dev->print_name());
768                }
769             } else if (dev->is_unmountable()) {
770                if (dev->mount(1)) {
771                   dir->fsend(_("3002 Device \"%s\" is mounted.\n"), dev->print_name());
772                } else {
773                   dir->fsend(_("3907 %s"), dev->bstrerror());
774                } 
775             } else { /* must be file */
776                dir->fsend(_("3906 File device \"%s\" is always mounted.\n"),
777                   dev->print_name());
778                pthread_cond_broadcast(&dev->wait_next_vol);
779                Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId);
780                pthread_cond_broadcast(&wait_device_release);
781             }
782             break;
783
784          case BST_RELEASING:
785             dir->fsend(_("3930 Device \"%s\" is being released.\n"), dev->print_name());
786             break;
787
788          default:
789             dir->fsend(_("3905 Unknown wait state %d\n"), dev->blocked());
790             break;
791          }
792          dev->dunlock();
793          free_dcr(dcr);
794       } else {
795          dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
796       }
797    } else {
798       pm_strcpy(jcr->errmsg, dir->msg);
799       dir->fsend(_("3909 Error scanning mount command: %s\n"), jcr->errmsg);
800    }
801    dir->signal(BNET_EOD);
802    return true;
803 }
804
805 /*
806  * unmount command from Director
807  */
808 static bool unmount_cmd(JCR *jcr)
809 {
810    POOL_MEM devname;
811    BSOCK *dir = jcr->dir_bsock;
812    DEVICE *dev;
813    DCR *dcr;
814    int32_t drive;
815
816    if (sscanf(dir->msg, "unmount %127s drive=%d", devname.c_str(), &drive) == 2) {
817       dcr = find_device(jcr, devname, drive);
818       if (dcr) {
819          dev = dcr->dev;
820          dev->dlock();                 /* Use P to avoid indefinite block */
821          if (!dev->is_open()) {
822             if (!dev->is_busy()) {
823                unload_autochanger(dcr, -1);          
824             }
825             if (dev->is_unmountable()) {
826                if (dev->unmount(0)) {
827                   dir->fsend(_("3002 Device \"%s\" unmounted.\n"), 
828                      dev->print_name());
829                } else {
830                   dir->fsend(_("3907 %s"), dev->bstrerror());
831                } 
832             } else {
833                Dmsg0(90, "Device already unmounted\n");
834                dir->fsend(_("3901 Device \"%s\" is already unmounted.\n"), 
835                   dev->print_name());
836             }
837          } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) {
838             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
839                dev->blocked());
840             if (!unload_autochanger(dcr, -1)) {
841                /* ***FIXME**** what is this ????  */
842                dev->close();
843                free_volume(dev);
844             }
845             if (dev->is_unmountable() && !dev->unmount(0)) {
846                dir->fsend(_("3907 %s"), dev->bstrerror());
847             } else {
848                dev->set_blocked(BST_UNMOUNTED_WAITING_FOR_SYSOP);
849                dir->fsend(_("3001 Device \"%s\" unmounted.\n"), 
850                   dev->print_name());
851             }
852
853          } else if (dev->blocked() == BST_DOING_ACQUIRE) {
854             dir->fsend(_("3902 Device \"%s\" is busy in acquire.\n"), 
855                dev->print_name());
856
857          } else if (dev->blocked() == BST_WRITING_LABEL) {
858             dir->fsend(_("3903 Device \"%s\" is being labeled.\n"), 
859                dev->print_name());
860
861          } else if (dev->is_busy()) {
862             send_dir_busy_message(dir, dev);
863          } else {                     /* device not being used */
864             Dmsg0(90, "Device not in use, unmounting\n");
865             /* On FreeBSD, I am having ASSERT() failures in block_device()
866              * and I can only imagine that the thread id that we are
867              * leaving in no_wait_id is being re-used. So here,
868              * we simply do it by hand.  Gross, but a solution.
869              */
870             /*  block_device(dev, BST_UNMOUNTED); replace with 2 lines below */
871             dev->set_blocked(BST_UNMOUNTED);
872             clear_thread_id(dev->no_wait_id);
873             if (!unload_autochanger(dcr, -1)) {
874                dev->close();
875                free_volume(dev);
876             }
877             if (dev->is_unmountable() && !dev->unmount(0)) {
878                dir->fsend(_("3907 %s"), dev->bstrerror());
879             } else {
880                dir->fsend(_("3002 Device \"%s\" unmounted.\n"), 
881                   dev->print_name());
882             }
883          }
884          dev->dunlock();
885          free_dcr(dcr);
886       } else {
887          dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
888       }
889    } else {
890       /* NB dir->msg gets clobbered in bnet_fsend, so save command */
891       pm_strcpy(jcr->errmsg, dir->msg);
892       dir->fsend(_("3907 Error scanning unmount command: %s\n"), jcr->errmsg);
893    }
894    dir->signal(BNET_EOD);
895    return true;
896 }
897
898 #if 0
899 /*
900  * The truncate command will recycle a volume. The director can call this
901  * after purging a volume so that disk space will not be wasted. Only useful
902  * for File Storage, of course.
903  *
904  *
905  * It is currently disabled
906  */
907 static bool action_on_purge_cmd(JCR *jcr)
908 {
909    BSOCK *dir = jcr->dir_bsock;
910
911    char devname[MAX_NAME_LENGTH];
912    char volumename[MAX_NAME_LENGTH];
913    int32_t action;
914
915    /* TODO: Need to find a free device and ask for slot to the director */
916    if (sscanf(dir->msg, 
917               "action_on_purge %127s vol=%127s action=%d",
918               devname, volumename, &action)!= 5) 
919    {
920       dir->fsend(_("3916 Error scanning action_on_purge command\n"));
921       goto done;
922    }
923    unbash_spaces(volumename);
924    unbash_spaces(devname);
925
926    /* Check if action is correct */
927    if (action & AOP_TRUNCTATE) {
928
929    } 
930    /* ... */
931
932 done:
933    dir->signal(BNET_EOD);
934    return true;
935 }
936 #endif
937
938 /*
939  * Release command from Director. This rewinds the device and if
940  *   configured does a offline and ensures that Bacula will
941  *   re-read the label of the tape before continuing. This gives
942  *   the operator the chance to change the tape anytime before the
943  *   next job starts.
944  */
945 static bool release_cmd(JCR *jcr)
946 {
947    POOL_MEM devname;
948    BSOCK *dir = jcr->dir_bsock;
949    DEVICE *dev;
950    DCR *dcr;
951    int32_t drive;
952
953    if (sscanf(dir->msg, "release %127s drive=%d", devname.c_str(), &drive) == 2) {
954       dcr = find_device(jcr, devname, drive);
955       if (dcr) {
956          dev = dcr->dev;
957          dev->dlock();                 /* Use P to avoid indefinite block */
958          if (!dev->is_open()) {
959             if (!dev->is_busy()) {
960                unload_autochanger(dcr, -1);
961             }
962             Dmsg0(90, "Device already released\n");
963             dir->fsend(_("3921 Device \"%s\" already released.\n"), 
964                dev->print_name());
965
966          } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) {
967             Dmsg2(90, "%d waiter dev_block=%d.\n", dev->num_waiting,
968                dev->blocked());
969             unload_autochanger(dcr, -1);
970             dir->fsend(_("3922 Device \"%s\" waiting for sysop.\n"), 
971                dev->print_name());
972
973          } else if (dev->blocked() == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
974             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
975                dev->blocked());
976             dir->fsend(_("3922 Device \"%s\" waiting for mount.\n"), 
977                dev->print_name());
978
979          } else if (dev->blocked() == BST_DOING_ACQUIRE) {
980             dir->fsend(_("3923 Device \"%s\" is busy in acquire.\n"), 
981                dev->print_name());
982
983          } else if (dev->blocked() == BST_WRITING_LABEL) {
984             dir->fsend(_("3914 Device \"%s\" is being labeled.\n"), 
985                dev->print_name());
986
987          } else if (dev->is_busy()) {
988             send_dir_busy_message(dir, dev);
989          } else {                     /* device not being used */
990             Dmsg0(90, "Device not in use, releasing\n");
991             dcr->release_volume();
992             dir->fsend(_("3022 Device \"%s\" released.\n"), 
993                dev->print_name());
994          }
995          dev->dunlock();
996          free_dcr(dcr);
997       } else {
998          dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
999       }
1000    } else {
1001       /* NB dir->msg gets clobbered in bnet_fsend, so save command */
1002       pm_strcpy(jcr->errmsg, dir->msg);
1003       dir->fsend(_("3927 Error scanning release command: %s\n"), jcr->errmsg);
1004    }
1005    dir->signal(BNET_EOD);
1006    return true;
1007 }
1008
1009 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1010 static uint32_t bsr_uniq = 0;
1011
1012 static bool get_bootstrap_file(JCR *jcr, BSOCK *sock)
1013 {
1014    POOLMEM *fname = get_pool_memory(PM_FNAME);
1015    FILE *bs;
1016    bool ok = false;
1017
1018    if (jcr->RestoreBootstrap) {
1019       unlink(jcr->RestoreBootstrap);
1020       free_pool_memory(jcr->RestoreBootstrap);
1021    }
1022    P(bsr_mutex);
1023    bsr_uniq++;
1024    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1025       jcr->Job, bsr_uniq);
1026    V(bsr_mutex);
1027    Dmsg1(400, "bootstrap=%s\n", fname);
1028    jcr->RestoreBootstrap = fname;
1029    bs = fopen(fname, "a+b");           /* create file */
1030    if (!bs) {
1031       berrno be;
1032       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1033          jcr->RestoreBootstrap, be.bstrerror());
1034       goto bail_out;
1035    }
1036    Dmsg0(10, "=== Bootstrap file ===\n");
1037    while (sock->recv() >= 0) {
1038        Dmsg1(10, "%s", sock->msg);
1039        fputs(sock->msg, bs);
1040    }
1041    fclose(bs);
1042    Dmsg0(10, "=== end bootstrap file ===\n");
1043    jcr->bsr = parse_bsr(jcr, jcr->RestoreBootstrap);
1044    if (!jcr->bsr) {
1045       Jmsg(jcr, M_FATAL, 0, _("Error parsing bootstrap file.\n"));
1046       goto bail_out;
1047    }
1048    if (debug_level >= 10) {
1049       dump_bsr(jcr->bsr, true);
1050    }
1051    /* If we got a bootstrap, we are reading, so create read volume list */
1052    create_restore_volume_list(jcr);
1053    ok = true;
1054
1055 bail_out:
1056    unlink(jcr->RestoreBootstrap);
1057    free_pool_memory(jcr->RestoreBootstrap);
1058    jcr->RestoreBootstrap = NULL;
1059    if (!ok) {
1060       sock->fsend(ERROR_bootstrap);
1061       return false;
1062    }
1063    return sock->fsend(OK_bootstrap);
1064 }
1065
1066 static bool bootstrap_cmd(JCR *jcr)
1067 {
1068    return get_bootstrap_file(jcr, jcr->dir_bsock);
1069 }
1070
1071 /*
1072  * Autochanger command from Director
1073  */
1074 static bool changer_cmd(JCR *jcr)
1075 {
1076    POOL_MEM devname;
1077    BSOCK *dir = jcr->dir_bsock;
1078    DEVICE *dev;
1079    DCR *dcr;
1080    const char *cmd = NULL;
1081    bool ok = false;
1082    /*
1083     * A safe_cmd may call autochanger script but does not load/unload
1084     *    slots so it can be done at the same time that the drive is open.
1085     */
1086    bool safe_cmd = false;
1087
1088    if (sscanf(dir->msg, "autochanger listall %127s", devname.c_str()) == 1) {
1089       cmd = "listall";
1090       safe_cmd = ok = true;
1091    } else if (sscanf(dir->msg, "autochanger list %127s", devname.c_str()) == 1) {
1092       cmd = "list";
1093       safe_cmd = ok = true;
1094    } else if (sscanf(dir->msg, "autochanger slots %127s", devname.c_str()) == 1) {
1095       cmd = "slots";
1096       safe_cmd = ok = true;
1097    } else if (sscanf(dir->msg, "autochanger drives %127s", devname.c_str()) == 1) {
1098       cmd = "drives";
1099       safe_cmd = ok = true;
1100    }
1101    if (ok) {
1102       dcr = find_device(jcr, devname, -1);
1103       if (dcr) {
1104          dev = dcr->dev;
1105          dev->dlock();                 /* Use P to avoid indefinite block */
1106          if (!dev->device->changer_res) {
1107             dir->fsend(_("3995 Device \"%s\" is not an autochanger.\n"), 
1108                dev->print_name());
1109          /* Under certain "safe" conditions, we can steal the lock */
1110          } else if (safe_cmd || !dev->is_open() || dev->can_steal_lock()) {
1111             autochanger_cmd(dcr, dir, cmd);
1112          } else if (dev->is_busy() || dev->is_blocked()) {
1113             send_dir_busy_message(dir, dev);
1114          } else {                     /* device not being used */
1115             autochanger_cmd(dcr, dir, cmd);
1116          }
1117          dev->dunlock();
1118          free_dcr(dcr);
1119       } else {
1120          dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
1121       }
1122    } else {  /* error on scanf */
1123       pm_strcpy(jcr->errmsg, dir->msg);
1124       dir->fsend(_("3908 Error scanning autochanger drives/list/slots command: %s\n"),
1125          jcr->errmsg);
1126    }
1127    dir->signal(BNET_EOD);
1128    return true;
1129 }
1130
1131 /*
1132  * Read and return the Volume label
1133  */
1134 static bool readlabel_cmd(JCR *jcr)
1135 {
1136    POOL_MEM devname;
1137    BSOCK *dir = jcr->dir_bsock;
1138    DEVICE *dev;
1139    DCR *dcr;
1140    int32_t Slot, drive;
1141
1142    if (sscanf(dir->msg, "readlabel %127s Slot=%d drive=%d", devname.c_str(), 
1143        &Slot, &drive) == 3) {
1144       dcr = find_device(jcr, devname, drive);
1145       if (dcr) {
1146          dev = dcr->dev;
1147          dev->dlock();                 /* Use P to avoid indefinite block */
1148          if (!dev->is_open()) {
1149             read_volume_label(jcr, dcr, dev, Slot);
1150             dev->close();
1151          /* Under certain "safe" conditions, we can steal the lock */
1152          } else if (dev->can_steal_lock()) {
1153             read_volume_label(jcr, dcr, dev, Slot);
1154          } else if (dev->is_busy() || dev->is_blocked()) {
1155             send_dir_busy_message(dir, dev);
1156          } else {                     /* device not being used */
1157             read_volume_label(jcr, dcr, dev, Slot);
1158          }
1159          dev->dunlock();
1160          free_dcr(dcr);
1161       } else {
1162          dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
1163       }
1164    } else {
1165       pm_strcpy(jcr->errmsg, dir->msg);
1166       dir->fsend(_("3909 Error scanning readlabel command: %s\n"), jcr->errmsg);
1167    }
1168    dir->signal(BNET_EOD);
1169    return true;
1170 }
1171
1172
1173 /*
1174  * Read the tape label
1175  *
1176  *  Enter with the mutex set
1177  */
1178 static void read_volume_label(JCR *jcr, DCR *dcr, DEVICE *dev, int Slot)
1179 {
1180    BSOCK *dir = jcr->dir_bsock;
1181    bsteal_lock_t hold;
1182
1183    dcr->dev = dev;
1184    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
1185
1186    if (!try_autoload_device(jcr, dcr, Slot, "")) {
1187       goto bail_out;                  /* error */
1188    }
1189
1190    dev->clear_labeled();              /* force read of label */
1191    switch (read_dev_volume_label(dcr)) {
1192    case VOL_OK:
1193       /* DO NOT add quotes around the Volume name. It is scanned in the DIR */
1194       dir->fsend(_("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolumeName, Slot);
1195       Dmsg1(100, "Volume: %s\n", dev->VolHdr.VolumeName);
1196       break;
1197    default:
1198       dir->fsend(_("3902 Cannot mount Volume on Storage Device \"%s\" because:\n%s"),
1199                  dev->print_name(), jcr->errmsg);
1200       break;
1201    }
1202
1203 bail_out:
1204    give_back_device_lock(dev, &hold);
1205    return;
1206 }
1207
1208 static bool try_autoload_device(JCR *jcr, DCR *dcr, int slot, const char *VolName)
1209 {
1210    BSOCK *dir = jcr->dir_bsock;
1211
1212    bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
1213    dcr->VolCatInfo.Slot = slot;
1214    dcr->VolCatInfo.InChanger = slot > 0;
1215    if (autoload_device(dcr, 0, dir) < 0) {    /* autoload if possible */
1216       return false;
1217    }
1218    return true;
1219 }
1220
1221 static void send_dir_busy_message(BSOCK *dir, DEVICE *dev)
1222 {
1223    if (dev->is_blocked()) {
1224       switch (dev->blocked()) {
1225       case BST_UNMOUNTED:
1226          dir->fsend(_("3931 Device \"%s\" is BLOCKED. user unmounted.\n"),
1227             dev->print_name());
1228          break;
1229       case BST_UNMOUNTED_WAITING_FOR_SYSOP:
1230          dir->fsend(_("3932 Device \"%s\" is BLOCKED. user unmounted during wait for media/mount.\n"),
1231              dev->print_name());
1232          break;
1233       case BST_WAITING_FOR_SYSOP:
1234          dir->fsend(_("3933 Device \"%s\" is BLOCKED waiting for media.\n"),
1235             dev->print_name());
1236          break;
1237       case BST_DOING_ACQUIRE:
1238          dir->fsend(_("3934 Device \"%s\" is being initialized.\n"),
1239             dev->print_name());
1240          break;
1241       case BST_WRITING_LABEL:
1242          dir->fsend(_("3935 Device \"%s\" is blocked labeling a Volume.\n"),
1243             dev->print_name());
1244          break;
1245       default:
1246          dir->fsend(_("3935 Device \"%s\" is blocked for unknown reason.\n"),
1247             dev->print_name());
1248          break;
1249       }
1250    } else if (dev->can_read()) {
1251        dir->fsend(_("3936 Device \"%s\" is busy reading.\n"),
1252                    dev->print_name());;
1253    } else {
1254        dir->fsend(_("3937 Device \"%s\" is busy with writers=%d reserved=%d.\n"),
1255           dev->print_name(), dev->num_writers, dev->num_reserved());
1256    }
1257 }