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