3 * dvd.c -- Routines specific to DVD devices (and
4 * possibly other removable hard media).
11 Copyright (C) 2005 Kern Sibbald
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 version 2 as amended with additional clauses defined in the
16 file LICENSE in the main source directory.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 the file LICENSE for additional details.
28 /* Forward referenced functions */
29 static char *edit_device_codes_dev(DEVICE *dev, char *omsg, const char *imsg);
30 static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout);
31 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name);
34 * Write the current volume/part filename to archive_name.
36 void make_mounted_dvd_filename(DEVICE *dev, POOL_MEM &archive_name)
38 pm_strcpy(archive_name, dev->device->mount_point);
39 add_file_and_part_name(dev, archive_name);
42 void make_spooled_dvd_filename(DEVICE *dev, POOL_MEM &archive_name)
44 /* Use the working directory if spool directory is not defined */
45 if (dev->device->spool_directory) {
46 pm_strcpy(archive_name, dev->device->spool_directory);
48 pm_strcpy(archive_name, working_directory);
50 add_file_and_part_name(dev, archive_name);
53 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
56 if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
57 pm_strcat(archive_name, "/");
60 pm_strcat(archive_name, dev->VolCatInfo.VolCatName);
61 /* if part > 1, append .# to the filename (where # is the part number) */
63 pm_strcat(archive_name, ".");
64 bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part);
65 pm_strcat(archive_name, partnumber);
67 Dmsg1(100, "Exit make_dvd_filename: arch=%s\n", archive_name.c_str());
71 * If timeout, wait until the mount command returns 0.
72 * If !timeout, try to mount the device only once.
74 bool mount_dev(DEVICE* dev, int timeout)
76 Dmsg0(900, "Enter mount_dev\n");
77 if (dev->is_mounted()) {
79 } else if (dev->requires_mount()) {
80 return do_mount_dev(dev, 1, timeout);
86 * If timeout, wait until the unmount command returns 0.
87 * If !timeout, try to unmount the device only once.
89 bool unmount_dev(DEVICE *dev, int timeout)
91 Dmsg0(900, "Enter unmount_dev\n");
92 if (dev->is_mounted()) {
93 return do_mount_dev(dev, 0, timeout);
98 /* (Un)mount the device */
99 static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
101 POOL_MEM ocmd(PM_FNAME);
107 if (dev->is_mounted()) {
110 icmd = dev->device->mount_command;
112 if (!dev->is_mounted()) {
115 icmd = dev->device->unmount_command;
118 edit_device_codes_dev(dev, ocmd.c_str(), icmd);
120 Dmsg2(200, "do_mount_dev: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
123 /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
128 results = get_pool_memory(PM_MESSAGE);
130 /* If busy retry each second */
131 while ((status = run_program_full_output(ocmd.c_str(),
132 dev->max_open_wait/2, results)) != 0) {
133 Dmsg1(100, "results len=%d\n", strlen(results));
134 if (fnmatch("*is already mounted on", results, 0) == 0) {
138 /* Sometimes the device cannot be mounted because it is already mounted.
139 * Try to unmount it, then remount it */
141 Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
142 do_mount_dev(dev, 0, 0);
147 Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results);
148 Mmsg(dev->errmsg, "Device %s cannot be mounted. ERR=%s\n",
149 dev->print_name(), results);
152 * Now, just to be sure it is not mounted, try to read the
156 struct dirent *entry, *result;
160 name_max = pathconf(".", _PC_NAME_MAX);
161 if (name_max < 1024) {
165 if (!(dp = opendir(dev->device->mount_point))) {
167 dev->dev_errno = errno;
168 Dmsg3(29, "open_mounted_dev: failed to open dir %s (dev=%s), ERR=%s\n", dev->device->mount_point, dev->dev_name, be.strerror());
172 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
174 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
175 dev->dev_errno = ENOENT;
176 Dmsg2(29, "open_mounted_dev: failed to find suitable file in dir %s (dev=%s)\n", dev->device->mount_point, dev->dev_name);
184 mount = 1; /* If we got more than . and .. */
185 break; /* there must be something mounted */
189 free_pool_memory(results);
193 dev->set_mounted(mount); /* set/clear mounted flag */
194 free_pool_memory(results);
198 /* Update the free space on the device */
199 void update_free_space_dev(DEVICE* dev)
201 POOL_MEM ocmd(PM_FNAME);
208 icmd = dev->device->free_space_command;
212 dev->free_space_errno = 0;
214 Dmsg2(29, "update_free_space_dev: free_space=%d, free_space_errno=%d (!icmd)\n", dev->free_space, dev->free_space_errno);
218 edit_device_codes_dev(dev, ocmd.c_str(), icmd);
220 Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
222 results = get_pool_memory(PM_MESSAGE);
225 /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
229 if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
230 Dmsg1(100, "results len=%d\n", strlen(results));
231 Dmsg1(100, "Free space program run : %s\n", results);
232 free = str_to_int64(results);
234 dev->free_space = free;
235 dev->free_space_errno = 1;
237 Mmsg0(dev->errmsg, "");
242 dev->free_space_errno = -EPIPE;
243 Mmsg1(dev->errmsg, "Cannot run free space command (%s)\n", results);
246 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
247 "free_space_errno=%d ERR=%s\n", dev->dev_name,
248 edit_uint64(dev->free_space, ed1), dev->free_space_errno,
254 dev->dev_errno = -dev->free_space_errno;
255 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
256 "free_space_errno=%d ERR=%s\n",
257 dev->dev_name, edit_uint64(dev->free_space, ed1),
258 dev->free_space_errno, dev->errmsg);
262 free_pool_memory(results);
263 Dmsg3(29, "update_free_space_dev: free_space=%s, free_space_errno=%d have_media=%d\n",
264 edit_uint64(dev->free_space, ed1), dev->free_space_errno, dev->have_media());
269 * Write a part (Vol, Vol.1, ...) from the spool to the DVD
271 static bool dvd_write_part(DCR *dcr)
273 DEVICE *dev = dcr->dev;
274 Dmsg1(29, "dvd_write_part: device is %s\n", dev->print_name());
276 if (!unmount_dev(dev, 1)) {
277 Dmsg0(29, "dvd_write_part: unable to unmount the device\n");
280 POOL_MEM ocmd(PM_FNAME);
281 POOL_MEM results(PM_MESSAGE);
288 results.c_str()[0] = 0;
289 icmd = dev->device->write_part_command;
292 * Note! part is used to control whether or not we create a
293 * new filesystem. If the device could be mounted, it is because
294 * it already has a filesystem, so we artificially set part=1
295 * to avoid zapping an existing filesystem.
298 if (dev->is_mounted() && dev->part < 2) {
299 dev->part = 2; /* do not wipe out existing filesystem */
301 edit_device_codes_dev(dev, ocmd.c_str(), icmd);
305 * Wait at most the time a maximum size part is written in DVD 0.5x speed
306 * FIXME: Minimum speed should be in device configuration
308 timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
310 Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
312 status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
313 Dmsg1(100, "results len=%d\n", strlen(results.c_str()));
315 Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s",
317 Dmsg1(000, "%s", dev->errmsg);
318 dev->dev_errno = EIO;
322 POOL_MEM archive_name(PM_FNAME);
323 /* Delete spool file */
324 make_spooled_dvd_filename(dev, archive_name);
325 unlink(archive_name.c_str());
326 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
327 update_free_space_dev(dev);
328 Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"),
329 edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
330 Dmsg1(100, "results=%s\n", results.c_str());
334 /* Open the next part file.
336 * - Increment part number
337 * - Reopen the device
339 int open_next_part(DCR *dcr)
341 DEVICE *dev = dcr->dev;
343 Dmsg5(29, "Enter: ==== open_next_part part=%d npart=%d dev=%s vol=%s mode=%d\n",
344 dev->part, dev->num_parts, dev->print_name(),
345 dev->VolCatInfo.VolCatName, dev->openmode);
346 if (!dev->is_dvd()) {
347 Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name());
351 /* When appending, do not open a new part if the current is empty */
352 if (dev->can_append() && (dev->part >= dev->num_parts) &&
353 (dev->part_size == 0)) {
354 Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
366 * If we have a part open for write, then write it to
367 * DVD before opening the next part.
369 if (dev->is_dvd() && (dev->part >= dev->num_parts) && dev->can_append()) {
370 if (!dvd_write_part(dcr)) {
375 if (dev->part > dev->num_parts) {
376 Dmsg2(000, "In open_next_part: part=%d nump=%d\n", dev->part, dev->num_parts);
377 ASSERT(dev->part <= dev->num_parts);
379 dev->part_start += dev->part_size;
382 Dmsg2(29, "part=%d num_parts=%d\n", dev->part, dev->num_parts);
383 /* I think this dev->can_append() should not be there */
384 if ((dev->num_parts < dev->part) && dev->can_append()) {
385 POOL_MEM archive_name(PM_FNAME);
388 * First check what is on DVD. If out part is there, we
389 * are in trouble, so bail out.
391 make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
392 if (stat(archive_name.c_str(), &buf) == 0) {
393 /* bad news bail out */
394 Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
395 archive_name.c_str());
399 dev->num_parts = dev->part;
400 dev->VolCatInfo.VolCatParts = dev->part;
401 make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
403 /* Check if the next part exists in spool directory . */
404 if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
405 Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
406 /* Then try to unlink it */
407 if (unlink(archive_name.c_str()) < 0) {
409 dev->dev_errno = errno;
410 Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
411 archive_name.c_str(), be.strerror());
416 if (dev->num_parts < dev->part) {
417 dev->num_parts = dev->part;
418 dev->VolCatInfo.VolCatParts = dev->part;
420 Dmsg2(50, "Call dev->open(vol=%s, mode=%d", dev->VolCatInfo.VolCatName,
423 if (dev->open(dcr, dev->openmode) < 0) {
426 dev->set_labeled(); /* all next parts are "labeled" */
430 /* Open the first part file.
432 * - Reopen the device
434 * I don't see why this is necessary unless the current
437 int open_first_part(DCR *dcr, int mode)
439 DEVICE *dev = dcr->dev;
441 Dmsg3(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d\n", dev->dev_name,
442 dev->VolCatInfo.VolCatName, dev->openmode);
453 Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
455 if (dev->open(dcr, mode) < 0) {
456 Dmsg0(50, "open dev() failed\n");
459 Dmsg1(50, "Leave open_first_part state=%s\n", dev->is_open()?"open":"not open");
464 /* Protected version of lseek, which opens the right part if necessary */
465 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
471 Dmsg0(100, "Enter lseek_dev\n");
472 if (!dev->is_dvd() || dev->num_parts <= 1) { /* If there is only one part, simply call lseek. */
473 return lseek(dev->fd, offset, whence);
476 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
479 Dmsg1(100, "lseek_dev SEEK_SET to %d\n", (int)offset);
480 if ((uint64_t)offset >= dev->part_start) {
481 if ((uint64_t)(offset - dev->part_start) < dev->part_size) {
482 /* We are staying in the current part, just seek */
483 offset -= dev->part_start; /* adjust for start of this part */
484 if ((pos = lseek(dev->fd, offset, SEEK_SET)) < 0) {
487 return pos + dev->part_start;
490 /* Load next part, and start again */
491 if (open_next_part(dcr) < 0) {
492 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
495 return lseek_dev(dev, offset, SEEK_SET);
499 * pos < dev->part_start :
500 * We need to access a previous part,
501 * so just load the first one, and seek again
502 * until the right one is loaded
504 if (open_first_part(dcr, dev->openmode) < 0) {
505 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
508 return lseek_dev(dev, offset, SEEK_SET);
512 Dmsg1(100, "lseek_dev SEEK_CUR to %d\n", (int)offset);
513 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
516 pos += dev->part_start;
519 } else { /* Not used in Bacula, but should work */
520 return lseek_dev(dev, pos, SEEK_SET);
524 Dmsg1(100, "lseek_dev SEEK_END to %d\n", (int)offset);
525 if (offset > 0) { /* Not used by bacula */
526 Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", (int)offset);
531 if (dev->part == dev->num_parts) { /* The right part is already loaded */
532 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
535 return pos + dev->part_start;
538 /* Load the first part, then load the next until we reach the last one.
539 * This is the only way to be sure we compute the right file address. */
540 /* Save previous openmode, and open all but last part read-only (useful for DVDs) */
541 openmode = dev->openmode;
543 /* Works because num_parts > 0. */
544 if (open_first_part(dcr, OPEN_READ_ONLY) < 0) {
545 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
548 while (dev->part < (dev->num_parts-1)) {
549 if (open_next_part(dcr) < 0) {
550 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
554 dev->openmode = openmode;
555 if (open_next_part(dcr) < 0) {
556 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
559 return lseek_dev(dev, 0, SEEK_END);
568 bool dvd_close_job(DCR *dcr)
570 DEVICE *dev = dcr->dev;
574 /* If the device is a dvd and WritePartAfterJob
575 * is set to yes, open the next part, so, in case of a device
576 * that requires mount, it will be written to the device.
578 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
579 Dmsg1(100, "Writing last part=%d write_partafter_job is set.\n",
581 if (dev->part < dev->num_parts) {
582 Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
583 dev->part, dev->num_parts, dev->print_name());
584 dev->dev_errno = EIO;
588 /* This should be !dvd_write_part(dcr) */
589 // if (ok && open_next_part(dcr) < 0) {
590 if (ok && !dvd_write_part(dcr)) {
591 Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"),
592 dev->print_name(), strerror_dev(dev));
593 dev->dev_errno = EIO;
597 Dmsg1(200, "Set VolCatParts=%d\n", dev->num_parts);
598 dev->VolCatInfo.VolCatParts = dev->num_parts;
604 * Edit codes into (Un)MountCommand, Write(First)PartCommand
606 * %a = archive device name
608 * %v = last part name
610 * omsg = edited output message
611 * imsg = input string containing edit codes (%x)
614 static char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg)
620 POOL_MEM archive_name(PM_FNAME);
623 Dmsg1(800, "edit_device_codes: %s\n", imsg);
624 for (p=imsg; *p; p++) {
631 bsnprintf(add, sizeof(add), "%d", dev->part);
638 str = dev->device->mount_point;
641 make_spooled_dvd_filename(dev, archive_name);
642 str = archive_name.c_str();
656 Dmsg1(1900, "add_str %s\n", str);
657 pm_strcat(&omsg, (char *)str);
658 Dmsg1(1800, "omsg=%s\n", omsg);