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,
439 if (dev->open(dcr, dev->openmode) < 0) {
442 dev->set_labeled(); /* all next parts are "labeled" */
446 /* Open the first part file.
448 * - Reopen the device
450 int open_first_part(DCR *dcr, int mode)
452 DEVICE *dev = dcr->dev;
454 Dmsg3(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d\n", dev->print_name(),
455 dev->VolCatInfo.VolCatName, dev->openmode);
466 Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
468 if (dev->open(dcr, mode) < 0) {
469 Dmsg0(50, "open dev() failed\n");
472 Dmsg1(50, "Leave open_first_part state=%s\n", dev->is_open()?"open":"not open");
477 /* Protected version of lseek, which opens the right part if necessary */
478 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
483 Dmsg3(100, "Enter lseek_dev fd=%d part=%d nparts=%d\n", dev->fd,
484 dev->part, dev->num_parts);
485 if (!dev->is_dvd()) {
486 Dmsg0(100, "Using sys lseek\n");
487 return lseek(dev->fd, offset, whence);
490 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
493 Dmsg2(100, "lseek_dev SEEK_SET to %d (part_start=%d)\n", (int)offset, (int)dev->part_start);
494 if ((uint64_t)offset >= dev->part_start) {
495 if (((uint64_t)offset == dev->part_start) || ((uint64_t)offset < (dev->part_start+dev->part_size))) {
496 /* We are staying in the current part, just seek */
497 if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
500 return pos + dev->part_start;
503 /* Load next part, and start again */
504 if (open_next_part(dcr) < 0) {
505 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
508 return lseek_dev(dev, offset, SEEK_SET);
512 * pos < dev->part_start :
513 * We need to access a previous part,
514 * so just load the first one, and seek again
515 * until the right one is loaded
517 if (open_first_part(dcr, dev->openmode) < 0) {
518 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
521 return lseek_dev(dev, offset, SEEK_SET);
525 Dmsg1(100, "lseek_dev SEEK_CUR to %d\n", (int)offset);
526 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
529 pos += dev->part_start;
531 Dmsg1(100, "lseek_dev SEEK_CUR returns %d\n", pos);
533 } else { /* Not used in Bacula, but should work */
534 return lseek_dev(dev, pos, SEEK_SET);
538 Dmsg1(100, "lseek_dev SEEK_END to %d\n", (int)offset);
540 * Bacula does not use offsets for SEEK_END
541 * Also, Bacula uses seek_end only when it wants to
542 * append to the volume, so for a dvd that means
543 * that the volume must be spooled since the DVD
544 * itself is read-only (as currently implemented).
546 if (offset > 0) { /* Not used by bacula */
547 Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", (int)offset);
551 /* If we are already on a spooled part and have the
552 * right part number, simply seek
554 if (dev->is_part_spooled() && dev->part == dev->num_parts) {
555 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
558 Dmsg1(100, "lseek_dev SEEK_END returns %d\n", pos + dev->part_start);
559 return pos + dev->part_start;
563 * Load the first part, then load the next until we reach the last one.
564 * This is the only way to be sure we compute the right file address.
566 * Save previous openmode, and open all but last part read-only
569 int modesave = dev->openmode;
570 /* Works because num_parts > 0. */
571 if (open_first_part(dcr, OPEN_READ_ONLY) < 0) {
572 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
575 if (dev->num_parts > 0) {
576 while (dev->part < (dev->num_parts-1)) {
577 if (open_next_part(dcr) < 0) {
578 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
582 dev->openmode = modesave;
583 if (open_next_part(dcr) < 0) {
584 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
588 return lseek_dev(dev, 0, SEEK_END);
597 bool dvd_close_job(DCR *dcr)
599 DEVICE *dev = dcr->dev;
603 /* If the device is a dvd and WritePartAfterJob
604 * is set to yes, open the next part, so, in case of a device
605 * that requires mount, it will be written to the device.
607 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
608 Dmsg1(100, "Writing last part=%d write_partafter_job is set.\n",
610 if (dev->part < dev->num_parts) {
611 Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
612 dev->part, dev->num_parts, dev->print_name());
613 dev->dev_errno = EIO;
617 /* This should be !dvd_write_part(dcr)
618 NB: No! If you call dvd_write_part, the part number is not updated.
619 You must open the next part, it will automatically write the part and
620 update the part number. */
621 if (ok && (open_next_part(dcr) < 0)) {
622 // if (ok && !dvd_write_part(dcr)) {
623 Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"),
624 dev->print_name(), strerror_dev(dev));
625 dev->dev_errno = EIO;
629 Dmsg1(200, "Set VolCatParts=%d\n", dev->num_parts);
630 dev->VolCatInfo.VolCatParts = dev->num_parts;
636 * Edit codes into (Un)MountCommand, Write(First)PartCommand
638 * %a = archive device name
639 * %e = erase (set if cannot mount and first part)
641 * %v = last part name
643 * omsg = edited output message
644 * imsg = input string containing edit codes (%x)
647 static void edit_device_codes_dev(DEVICE* dev, POOL_MEM &omsg, const char *imsg)
653 POOL_MEM archive_name(PM_FNAME);
656 Dmsg1(800, "edit_device_codes: %s\n", imsg);
657 for (p=imsg; *p; p++) {
667 if (dev->part == 0 && !dev->is_mounted()) {
674 bsnprintf(add, sizeof(add), "%d", dev->part);
678 str = dev->device->mount_point;
681 make_spooled_dvd_filename(dev, archive_name);
682 str = archive_name.c_str();
696 Dmsg1(1900, "add_str %s\n", str);
697 pm_strcat(omsg, (char *)str);
698 Dmsg1(1800, "omsg=%s\n", omsg.c_str());