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 void edit_device_codes_dev(DEVICE *dev, POOL_MEM &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);
40 dev->set_part_spooled(false);
43 void make_spooled_dvd_filename(DEVICE *dev, POOL_MEM &archive_name)
45 /* Use the working directory if spool directory is not defined */
46 if (dev->device->spool_directory) {
47 pm_strcpy(archive_name, dev->device->spool_directory);
49 pm_strcpy(archive_name, working_directory);
51 add_file_and_part_name(dev, archive_name);
52 dev->set_part_spooled(true);
55 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
58 if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
59 pm_strcat(archive_name, "/");
62 pm_strcat(archive_name, dev->VolCatInfo.VolCatName);
63 /* if part > 1, append .# to the filename (where # is the part number) */
65 pm_strcat(archive_name, ".");
66 bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part);
67 pm_strcat(archive_name, partnumber);
69 Dmsg1(100, "Exit make_dvd_filename: arch=%s\n", archive_name.c_str());
73 * If timeout, wait until the mount command returns 0.
74 * If !timeout, try to mount the device only once.
76 bool mount_dev(DEVICE* dev, int timeout)
78 Dmsg0(90, "Enter mount_dev\n");
79 if (dev->is_mounted()) {
81 } else if (dev->requires_mount()) {
82 return do_mount_dev(dev, 1, timeout);
88 * If timeout, wait until the unmount command returns 0.
89 * If !timeout, try to unmount the device only once.
91 bool unmount_dev(DEVICE *dev, int timeout)
93 Dmsg0(90, "Enter unmount_dev\n");
94 if (dev->is_mounted()) {
95 return do_mount_dev(dev, 0, timeout);
100 /* (Un)mount the device */
101 static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
103 POOL_MEM ocmd(PM_FNAME);
108 sm_check(__FILE__, __LINE__, false);
110 if (dev->is_mounted()) {
111 Dmsg0(200, "======= DVD mount=1\n");
114 icmd = dev->device->mount_command;
116 if (!dev->is_mounted()) {
117 Dmsg0(200, "======= DVD mount=0\n");
120 icmd = dev->device->unmount_command;
123 edit_device_codes_dev(dev, ocmd, icmd);
125 Dmsg2(200, "do_mount_dev: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
128 /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
133 results = get_memory(2000);
135 /* If busy retry each second */
136 while ((status = run_program_full_output(ocmd.c_str(),
137 dev->max_open_wait/2, results)) != 0) {
138 if (fnmatch("*is already mounted on", results, 0) == 0) {
142 /* Sometimes the device cannot be mounted because it is already mounted.
143 * Try to unmount it, then remount it */
145 Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
146 do_mount_dev(dev, 0, 0);
151 Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results);
152 Mmsg(dev->errmsg, "Device %s cannot be mounted. ERR=%s\n",
153 dev->print_name(), results);
155 * Now, just to be sure it is not mounted, try to read the
159 struct dirent *entry, *result;
163 name_max = pathconf(".", _PC_NAME_MAX);
164 if (name_max < 1024) {
168 if (!(dp = opendir(dev->device->mount_point))) {
170 dev->dev_errno = errno;
171 Dmsg3(29, "open_mounted_dev: failed to open dir %s (dev=%s), ERR=%s\n",
172 dev->device->mount_point, dev->print_name(), be.strerror());
176 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
178 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
179 dev->dev_errno = ENOENT;
180 Dmsg2(29, "open_mounted_dev: failed to find suitable file in dir %s (dev=%s)\n",
181 dev->device->mount_point, dev->print_name());
189 mount = 1; /* If we got more than . and .. */
190 break; /* there must be something mounted */
193 dev->set_mounted(false);
194 sm_check(__FILE__, __LINE__, false);
195 free_pool_memory(results);
196 Dmsg0(200, "============ DVD mount=0\n");
200 dev->set_mounted(mount); /* set/clear mounted flag */
201 free_pool_memory(results);
202 /* Do not check free space when unmounting (otherwise it will mount it again) */
204 update_free_space_dev(dev);
206 Dmsg1(200, "============ DVD mount=%d\n", mount);
210 /* Update the free space on the device */
211 void update_free_space_dev(DEVICE* dev)
213 POOL_MEM ocmd(PM_FNAME);
220 /* The device must be mounted in order to dvd-freespace to work */
223 sm_check(__FILE__, __LINE__, false);
224 icmd = dev->device->free_space_command;
228 dev->free_space_errno = 0;
230 Dmsg2(29, "update_free_space_dev: free_space=%d, free_space_errno=%d (!icmd)\n", dev->free_space, dev->free_space_errno);
234 edit_device_codes_dev(dev, ocmd, icmd);
236 Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
238 results = get_pool_memory(PM_MESSAGE);
240 /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
244 if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
245 Dmsg1(100, "Free space program run : %s\n", results);
246 free = str_to_int64(results);
248 dev->free_space = free;
249 dev->free_space_errno = 1;
251 Mmsg0(dev->errmsg, "");
256 dev->free_space_errno = -EPIPE;
257 Mmsg1(dev->errmsg, "Cannot run free space command (%s)\n", results);
260 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
261 "free_space_errno=%d ERR=%s\n", dev->print_name(),
262 edit_uint64(dev->free_space, ed1), dev->free_space_errno,
268 dev->dev_errno = -dev->free_space_errno;
269 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
270 "free_space_errno=%d ERR=%s\n",
271 dev->print_name(), edit_uint64(dev->free_space, ed1),
272 dev->free_space_errno, dev->errmsg);
276 free_pool_memory(results);
277 Dmsg3(29, "update_free_space_dev: free_space=%s, free_space_errno=%d have_media=%d\n",
278 edit_uint64(dev->free_space, ed1), dev->free_space_errno, dev->have_media());
279 sm_check(__FILE__, __LINE__, false);
284 * Write a part (Vol, Vol.1, ...) from the spool to the DVD
285 * This MUST only be called from open_next_part. Otherwise the part number
288 static bool dvd_write_part(DCR *dcr)
290 DEVICE *dev = dcr->dev;
291 POOL_MEM ocmd(PM_FNAME);
297 sm_check(__FILE__, __LINE__, false);
298 Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
299 icmd = dev->device->write_part_command;
301 edit_device_codes_dev(dev, ocmd, icmd);
304 * Wait at most the time a maximum size part is written in DVD 0.5x speed
305 * FIXME: Minimum speed should be in device configuration
307 timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
309 Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
312 POOL_MEM results(PM_MESSAGE);
313 sm_check(__FILE__, __LINE__, false);
314 status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
315 sm_check(__FILE__, __LINE__, false);
317 Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s",
319 Dmsg1(000, "%s", dev->errmsg);
320 dev->dev_errno = EIO;
323 sm_check(__FILE__, __LINE__, false);
327 POOL_MEM archive_name(PM_FNAME);
328 /* Delete spool file */
329 make_spooled_dvd_filename(dev, archive_name);
330 unlink(archive_name.c_str());
331 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
332 sm_check(__FILE__, __LINE__, false);
335 /* growisofs umount the device, so remount it (it will update the free space) */
336 dev->clear_mounted();
338 Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"),
339 edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
340 sm_check(__FILE__, __LINE__, false);
344 /* Open the next part file.
346 * - Increment part number
347 * - Reopen the device
349 int open_next_part(DCR *dcr)
351 DEVICE *dev = dcr->dev;
353 Dmsg6(29, "Enter: ==== open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n",
354 dev->part, dev->num_parts, dev->print_name(),
355 dev->VolCatInfo.VolCatName, dev->openmode, dev->file_addr);
356 if (!dev->is_dvd()) {
357 Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name());
361 /* When appending, do not open a new part if the current is empty */
362 if (dev->can_append() && (dev->part >= dev->num_parts) &&
363 (dev->part_size == 0)) {
364 Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
376 * If we have a part open for write, then write it to
377 * DVD before opening the next part.
379 if (dev->is_dvd() && (dev->part >= dev->num_parts) && dev->can_append()) {
380 if (!dvd_write_part(dcr)) {
385 if (dev->part > dev->num_parts) {
386 Dmsg2(000, "In open_next_part: part=%d nump=%d\n", dev->part, dev->num_parts);
387 ASSERT(dev->part <= dev->num_parts);
389 dev->part_start += dev->part_size;
392 Dmsg2(29, "part=%d num_parts=%d\n", dev->part, dev->num_parts);
393 /* I think this dev->can_append() should not be there */
394 if ((dev->num_parts < dev->part) && dev->can_append()) {
395 POOL_MEM archive_name(PM_FNAME);
398 * First check what is on DVD. If our part is there, we
399 * are in trouble, so bail out.
400 * NB: This is however not a problem if we are writing the first part.
401 * It simply means that we are overriding an existing volume...
403 if (dev->num_parts > 0) {
404 make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
405 if (stat(archive_name.c_str(), &buf) == 0) {
406 /* bad news bail out */
407 Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
408 archive_name.c_str());
413 Dmsg2(100, "Set npart=%d to part=%d\n", dev->num_parts, dev->part);
414 dev->num_parts = dev->part;
415 dev->VolCatInfo.VolCatParts = dev->part;
416 make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
418 /* Check if the next part exists in spool directory . */
419 if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
420 Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
421 /* Then try to unlink it */
422 if (unlink(archive_name.c_str()) < 0) {
424 dev->dev_errno = errno;
425 Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
426 archive_name.c_str(), be.strerror());
431 if (dev->num_parts < dev->part) {
432 Dmsg2(100, "Set npart=%d to part=%d\n", dev->num_parts, dev->part);
433 dev->num_parts = dev->part;
434 dev->VolCatInfo.VolCatParts = dev->part;
436 Dmsg2(50, "Call dev->open(vol=%s, mode=%d\n", dev->VolCatInfo.VolCatName,
440 int append = dev->can_append();
441 if (dev->open(dcr, dev->openmode) < 0) {
444 dev->set_labeled(); /* all next parts are "labeled" */
445 if (append && (dev->part == dev->num_parts)) { /* If needed, set the append flag back */
452 /* Open the first part file.
454 * - Reopen the device
456 int open_first_part(DCR *dcr, int mode)
458 DEVICE *dev = dcr->dev;
460 Dmsg3(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d\n", dev->print_name(),
461 dev->VolCatInfo.VolCatName, dev->openmode);
472 Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
474 if (dev->open(dcr, mode) < 0) {
475 Dmsg0(50, "open dev() failed\n");
478 Dmsg1(50, "Leave open_first_part state=%s\n", dev->is_open()?"open":"not open");
483 /* Protected version of lseek, which opens the right part if necessary */
484 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
489 Dmsg3(100, "Enter lseek_dev fd=%d part=%d nparts=%d\n", dev->fd,
490 dev->part, dev->num_parts);
491 if (!dev->is_dvd()) {
492 Dmsg0(100, "Using sys lseek\n");
493 return lseek(dev->fd, offset, whence);
496 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
499 Dmsg2(100, "lseek_dev SEEK_SET to %d (part_start=%d)\n", (int)offset, (int)dev->part_start);
500 if ((uint64_t)offset >= dev->part_start) {
501 if (((uint64_t)offset == dev->part_start) || ((uint64_t)offset < (dev->part_start+dev->part_size))) {
502 /* We are staying in the current part, just seek */
503 if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
506 return pos + dev->part_start;
509 /* Load next part, and start again */
510 if (open_next_part(dcr) < 0) {
511 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
514 return lseek_dev(dev, offset, SEEK_SET);
518 * pos < dev->part_start :
519 * We need to access a previous part,
520 * so just load the first one, and seek again
521 * until the right one is loaded
523 if (open_first_part(dcr, dev->openmode) < 0) {
524 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
527 return lseek_dev(dev, offset, SEEK_SET);
531 Dmsg1(100, "lseek_dev SEEK_CUR to %d\n", (int)offset);
532 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
535 pos += dev->part_start;
537 Dmsg1(100, "lseek_dev SEEK_CUR returns %d\n", pos);
539 } else { /* Not used in Bacula, but should work */
540 return lseek_dev(dev, pos, SEEK_SET);
544 Dmsg1(100, "lseek_dev SEEK_END to %d\n", (int)offset);
546 * Bacula does not use offsets for SEEK_END
547 * Also, Bacula uses seek_end only when it wants to
548 * append to the volume, so for a dvd that means
549 * that the volume must be spooled since the DVD
550 * itself is read-only (as currently implemented).
552 if (offset > 0) { /* Not used by bacula */
553 Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", (int)offset);
557 /* If we are already on a spooled part and have the
558 * right part number, simply seek
560 if (dev->is_part_spooled() && dev->part == dev->num_parts) {
561 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
564 Dmsg1(100, "lseek_dev SEEK_END returns %d\n", pos + dev->part_start);
565 return pos + dev->part_start;
569 * Load the first part, then load the next until we reach the last one.
570 * This is the only way to be sure we compute the right file address.
572 * Save previous openmode, and open all but last part read-only
575 int modesave = dev->openmode;
576 /* Works because num_parts > 0. */
577 if (open_first_part(dcr, OPEN_READ_ONLY) < 0) {
578 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
581 if (dev->num_parts > 0) {
582 while (dev->part < (dev->num_parts-1)) {
583 if (open_next_part(dcr) < 0) {
584 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
588 dev->openmode = modesave;
589 if (open_next_part(dcr) < 0) {
590 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
594 return lseek_dev(dev, 0, SEEK_END);
603 bool dvd_close_job(DCR *dcr)
605 DEVICE *dev = dcr->dev;
609 /* If the device is a dvd and WritePartAfterJob
610 * is set to yes, open the next part, so, in case of a device
611 * that requires mount, it will be written to the device.
613 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
614 Dmsg1(100, "Writing last part=%d write_partafter_job is set.\n",
616 if (dev->part < dev->num_parts) {
617 Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
618 dev->part, dev->num_parts, dev->print_name());
619 dev->dev_errno = EIO;
623 /* This should be !dvd_write_part(dcr)
624 NB: No! If you call dvd_write_part, the part number is not updated.
625 You must open the next part, it will automatically write the part and
626 update the part number. */
627 if (ok && (open_next_part(dcr) < 0)) {
628 // if (ok && !dvd_write_part(dcr)) {
629 Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"),
630 dev->print_name(), strerror_dev(dev));
631 dev->dev_errno = EIO;
635 Dmsg1(200, "Set VolCatParts=%d\n", dev->num_parts);
636 dev->VolCatInfo.VolCatParts = dev->num_parts;
642 * Edit codes into (Un)MountCommand, Write(First)PartCommand
644 * %a = archive device name
645 * %e = erase (set if cannot mount and first part)
647 * %v = last part name
649 * omsg = edited output message
650 * imsg = input string containing edit codes (%x)
653 static void edit_device_codes_dev(DEVICE* dev, POOL_MEM &omsg, const char *imsg)
659 POOL_MEM archive_name(PM_FNAME);
662 Dmsg1(800, "edit_device_codes: %s\n", imsg);
663 for (p=imsg; *p; p++) {
673 if (dev->part == 0 && !dev->is_mounted()) {
680 bsnprintf(add, sizeof(add), "%d", dev->part);
684 str = dev->device->mount_point;
687 make_spooled_dvd_filename(dev, archive_name);
688 str = archive_name.c_str();
702 Dmsg1(1900, "add_str %s\n", str);
703 pm_strcat(omsg, (char *)str);
704 Dmsg1(1800, "omsg=%s\n", omsg.c_str());