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