3 * dvd.c -- Routines specific to DVD devices (and
4 * possibly other removable hard media).
11 Copyright (C) 2005-2006 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 bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout);
30 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name);
33 * Write the current volume/part filename to archive_name.
35 void make_mounted_dvd_filename(DEVICE *dev, POOL_MEM &archive_name)
37 pm_strcpy(archive_name, dev->device->mount_point);
38 add_file_and_part_name(dev, archive_name);
39 dev->set_part_spooled(false);
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);
51 dev->set_part_spooled(true);
54 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
57 if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
58 pm_strcat(archive_name, "/");
61 pm_strcat(archive_name, dev->VolCatInfo.VolCatName);
62 /* if part > 1, append .# to the filename (where # is the part number) */
64 pm_strcat(archive_name, ".");
65 bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part);
66 pm_strcat(archive_name, partnumber);
68 Dmsg1(400, "Exit add_file_part_name: arch=%s\n", archive_name.c_str());
72 * If timeout, wait until the mount command returns 0.
73 * If !timeout, try to mount the device only once.
75 bool mount_dvd(DEVICE* dev, int timeout)
77 Dmsg0(90, "Enter mount_dvd\n");
78 if (dev->is_mounted()) {
80 } else if (dev->requires_mount()) {
81 return do_mount_dvd(dev, 1, timeout);
87 * If timeout, wait until the unmount command returns 0.
88 * If !timeout, try to unmount the device only once.
90 bool unmount_dvd(DEVICE *dev, int timeout)
95 Dmsg0(90, "Enter unmount_dvd\n");
96 if (dev->is_mounted()) {
97 return do_mount_dvd(dev, 0, timeout);
102 /* (Un)mount the device */
103 static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout)
105 POOL_MEM ocmd(PM_FNAME);
110 sm_check(__FILE__, __LINE__, false);
112 if (dev->is_mounted()) {
113 Dmsg0(200, "======= DVD mount=1\n");
116 icmd = dev->device->mount_command;
118 if (!dev->is_mounted()) {
119 Dmsg0(200, "======= DVD mount=0\n");
122 icmd = dev->device->unmount_command;
125 dev->edit_mount_codes(ocmd, icmd);
127 Dmsg2(200, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
130 /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
135 results = get_memory(2000);
137 /* If busy retry each second */
138 Dmsg1(20, "Run mount prog=%s\n", ocmd.c_str());
139 while ((status = run_program_full_output(ocmd.c_str(),
140 dev->max_open_wait/2, results)) != 0) {
141 Dmsg2(99, "Mount status=%d result=%s\n", status, results);
142 /* Doesn't work with internationalization (This is not a problem) */
143 if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
146 if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
150 /* Sometimes the device cannot be mounted because it is already mounted.
151 * Try to unmount it, then remount it */
153 Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
154 do_mount_dvd(dev, 0, 0);
161 Dmsg5(40, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", dev->print_name(),
162 (mount ? "" : "un"), status, results, be.strerror(status));
163 Mmsg(dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
164 dev->print_name(), (mount ? "" : "un"), be.strerror(status));
166 Dmsg4(40, "Device %s cannot be %smounted. stat=%d ERR=%s\n", dev->print_name(),
167 (mount ? "" : "un"), status, results);
168 Mmsg(dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
169 dev->print_name(), (mount ? "" : "un"), results);
172 * Now, just to be sure it is not mounted, try to read the
176 struct dirent *entry, *result;
180 name_max = pathconf(".", _PC_NAME_MAX);
181 if (name_max < 1024) {
185 if (!(dp = opendir(dev->device->mount_point))) {
187 dev->dev_errno = errno;
188 Dmsg3(29, "do_mount_dvd: failed to open dir %s (dev=%s), ERR=%s\n",
189 dev->device->mount_point, dev->print_name(), be.strerror());
193 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
196 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
197 dev->dev_errno = EIO;
198 Dmsg2(129, "do_mount_dvd: failed to find suitable file in dir %s (dev=%s)\n",
199 dev->device->mount_point, dev->print_name());
202 if (strcmp(result->d_name, ".") && strcmp(result->d_name, "..") &&
203 strcmp(result->d_name, ".keep")) {
204 count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
205 Dmsg1(100, "Inc count=%d\n", count);
208 Dmsg2(129, "do_mount_dvd: ignoring %s in %s\n",
209 result->d_name, dev->device->mount_point);
215 Dmsg1(29, "do_mount_dvd: got %d files in the mount point (not counting ., .. and .keep)\n", count);
218 /* If we got more than ., .. and .keep */
219 /* there must be something mounted */
221 Dmsg1(100, "Did Mount by count=%d\n", count);
224 /* An unmount request. We failed to unmount - report an error */
225 dev->set_mounted(true);
226 free_pool_memory(results);
227 Dmsg0(200, "== DVD mount=1\n");
232 dev->set_mounted(false);
233 sm_check(__FILE__, __LINE__, false);
234 free_pool_memory(results);
235 Dmsg0(200, "== DVD mount=0\n");
238 Dmsg0(100, "Out of mount/umount loop\n");
240 dev->set_mounted(mount); /* set/clear mounted flag */
241 free_pool_memory(results);
242 /* Do not check free space when unmounting */
244 Dmsg0(100, "Calling update_free_space\n");
245 if (!update_free_space_dev(dev)) {
249 Dmsg1(200, "== DVD mount=%d\n", mount);
253 /* Update the free space on the device */
254 bool update_free_space_dev(DEVICE* dev)
256 POOL_MEM ocmd(PM_FNAME);
265 /* The device must be mounted in order to dvd-freespace to work */
268 sm_check(__FILE__, __LINE__, false);
269 icmd = dev->device->free_space_command;
273 dev->free_space_errno = 0;
274 dev->clear_freespace_ok(); /* No valid freespace */
276 Dmsg2(29, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n",
277 edit_uint64(dev->free_space, ed1), dev->free_space_errno);
278 Mmsg(dev->errmsg, _("No FreeSpace command defined.\n"));
282 dev->edit_mount_codes(ocmd, icmd);
284 Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
286 results = get_pool_memory(PM_MESSAGE);
288 /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
293 Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str());
294 status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results);
296 free = str_to_int64(results);
297 Dmsg1(400, "Free space program run: Freespace=%s\n", results);
299 dev->free_space = free;
300 dev->free_space_errno = 0;
301 dev->set_freespace_ok(); /* have valid freespace */
303 Mmsg(dev->errmsg, "");
309 dev->free_space_errno = EPIPE;
310 dev->clear_freespace_ok(); /* no valid freespace */
311 Mmsg2(dev->errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"),
312 results, be.strerror(status));
315 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
316 "free_space_errno=%d ERR=%s\n", dev->print_name(),
317 edit_uint64(dev->free_space, ed1), dev->free_space_errno,
323 dev->dev_errno = dev->free_space_errno;
324 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
325 "free_space_errno=%d ERR=%s\n",
326 dev->print_name(), edit_uint64(dev->free_space, ed1),
327 dev->free_space_errno, dev->errmsg);
331 free_pool_memory(results);
332 Dmsg4(29, "leave update_free_space_dev: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n",
333 edit_uint64(dev->free_space, ed1), !!dev->is_freespace_ok(), dev->free_space_errno, !!dev->have_media());
334 sm_check(__FILE__, __LINE__, false);
339 * Note!!!! Part numbers now begin at 1. The part number is
340 * suppressed from the first part, which is just the Volume
341 * name. Each subsequent part is the Volumename.partnumber.
343 * Write a part (Vol, Vol.2, ...) from the spool to the DVD
344 * This routine does not update the part number, so normally, you
345 * should call open_next_part()
347 * It is also called from truncate_dvd to "blank" the medium, as
348 * well as from block.c when the DVD is full to write the last part.
350 bool dvd_write_part(DCR *dcr)
352 DEVICE *dev = dcr->dev;
353 POOL_MEM archive_name(PM_FNAME);
355 /* Don't write empty part files.
356 * This is only useful when growisofs does not support write beyond
359 * - 3.9 GB on the volume, dvd-freespace reports 0.4 GB free
360 * - Write 0.2 GB on the volume, Bacula thinks it could still
361 * append data, it creates a new empty part.
362 * - dvd-freespace reports 0 GB free, as the 4GB boundary has
364 * - Bacula thinks he must finish to write to the device, so it
365 * tries to write the last part (0-byte), but dvd-writepart fails...
367 * ***FIXME**** we cannot write a blank part!!!!!!!
368 * There is one exception: when recycling a volume, we write a blank part
369 * file, so, then, we need to accept to write it.
371 if (dev->part_size == 0) {
372 Dmsg2(29, "dvd_write_part: device is %s, won't write blank part %d\n", dev->print_name(), dev->part);
373 /* Delete spool file */
374 make_spooled_dvd_filename(dev, archive_name);
375 unlink(archive_name.c_str());
376 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
377 sm_check(__FILE__, __LINE__, false);
381 POOL_MEM ocmd(PM_FNAME);
382 POOL_MEM results(PM_MESSAGE);
388 sm_check(__FILE__, __LINE__, false);
389 Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
390 icmd = dev->device->write_part_command;
392 dev->edit_mount_codes(ocmd, icmd);
395 * original line follows
396 * timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
397 * I modified this for a longer timeout; pre-formatting, blanking and
398 * writing can take quite a while
401 /* Explanation of the timeout value, when writing the first part,
403 * 9 GB, write speed 1x: 6990 seconds (almost 2 hours...)
404 * Overhead: 900 seconds (starting, initializing, finalizing,probably
405 * reloading 15 minutes)
407 * A reasonable last-exit timeout would be 16000 seconds. Quite long -
408 * almost 4.5 hours, but hopefully, that timeout will only ever be needed
409 * in case of a serious emergency.
415 timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4));
417 Dmsg2(20, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
418 status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
421 Jmsg2(dcr->jcr, M_FATAL, 0, _("Error writing part %d to the DVD: ERR=%s\n"),
422 dev->part, results.c_str());
423 Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"),
425 Dmsg1(000, "%s\n", dev->errmsg);
426 dev->dev_errno = EIO;
427 mark_volume_in_error(dcr);
428 sm_check(__FILE__, __LINE__, false);
429 dev->truncated_dvd = false;
432 Jmsg(dcr->jcr, M_INFO, 0, _("Part %d written to DVD.\n"), dev->part);
433 Dmsg2(400, "dvd_write_part: Part %d written to DVD\nResults: %s\n",
434 dev->part, results.c_str());
436 if (dev->truncated_dvd) {
437 dev->truncated_dvd = false; /* turn off flag */
438 } else { /* DVD part written */
439 dev->num_dvd_parts++; /* there is now one more part on DVD */
440 dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
443 /* Delete spool file */
444 make_spooled_dvd_filename(dev, archive_name);
445 unlink(archive_name.c_str());
446 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
447 sm_check(__FILE__, __LINE__, false);
449 /* growisofs umounted the device, so remount it (it will update the free space) */
450 dev->clear_mounted();
452 Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"),
453 edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
454 sm_check(__FILE__, __LINE__, false);
459 * Open the next part file.
461 * - Increment part number
462 * - Reopen the device
464 int dvd_open_next_part(DCR *dcr)
466 DEVICE *dev = dcr->dev;
469 Dmsg6(29, "Enter: == open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n",
470 dev->part, dev->num_dvd_parts, dev->print_name(),
471 dev->VolCatInfo.VolCatName, dev->openmode, dev->file_addr);
472 if (!dev->is_dvd()) {
473 Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name());
477 /* When appending, do not open a new part if the current is empty */
478 if (dev->can_append() && (dev->part > dev->num_dvd_parts) &&
479 (dev->part_size == 0)) {
480 Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
485 * Note, when we close, the Volume header is zeroed. Since
486 * we reopen, but are in fact opening the same volume without
487 * re-reading the Volume header, we simply save and restore it.
489 memcpy(&VolHdr, &dev->VolHdr, sizeof(VolHdr));
490 dev->close(); /* close current part */
491 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
494 * If we have a spooled part open, write it to the
495 * DVD before opening the next part.
497 if (dev->is_part_spooled()) {
498 Dmsg2(100, "Before open next write previous. part=%d num_parts=%d\n",
499 dev->part, dev->num_dvd_parts);
500 if (!dvd_write_part(dcr)) {
501 Dmsg0(29, "Error in dvd_write part.\n");
506 dev->part_start += dev->part_size;
508 Dmsg2(29, "Inc part=%d num_dvd_parts=%d\n", dev->part, dev->num_dvd_parts);
510 if (dev->num_dvd_parts < dev->part) {
511 POOL_MEM archive_name(PM_FNAME);
514 * First check what is on DVD. If our part is there, we
515 * are in trouble, so bail out.
516 * NB: This is however not a problem if we are writing the first part.
517 * It simply means that we are overriding an existing volume...
519 if (dev->num_dvd_parts > 0) {
520 make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
521 Dmsg1(100, "Check if part on DVD: %s\n", archive_name.c_str());
522 if (stat(archive_name.c_str(), &buf) == 0) {
523 /* bad news bail out */
524 Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
525 archive_name.c_str());
530 Dmsg2(400, "num_dvd_parts=%d part=%d\n", dev->num_dvd_parts, dev->part);
531 make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
533 /* Check if the next part exists in spool directory . */
534 Dmsg1(100, "Check if part on spool: $s\n", archive_name.c_str());
535 if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
536 Dmsg1(29, "open_next_part %s is in the way, deleting it...\n", archive_name.c_str());
537 /* Then try to unlink it */
538 if (unlink(archive_name.c_str()) < 0) {
540 dev->dev_errno = errno;
541 Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
542 archive_name.c_str(), be.strerror());
548 Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
551 /* Open next part. Note, this sets part_size for part opened. */
552 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
555 /* Restore Volume header record */
556 memcpy(&dev->VolHdr, &VolHdr, sizeof(dev->VolHdr));
557 dev->set_labeled(); /* all next parts are "labeled" */
563 * Open the first part file.
565 * - Reopen the device
567 int dvd_open_first_part(DCR *dcr, int mode)
569 DEVICE *dev = dcr->dev;
572 Dmsg5(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d num_dvd_parts=%d append=%d\n", dev->print_name(),
573 dev->VolCatInfo.VolCatName, dev->openmode, dev->num_dvd_parts, dev->can_append());
577 * Note, when we close, the Volume header is zeroed. Since
578 * we reopen, but are in fact opening the same volume without
579 * re-reading the Volume header, we simply save and restore it.
581 memcpy(&VolHdr, &dev->VolHdr, sizeof(VolHdr));
583 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
585 Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
587 Dmsg0(100, "Set part=1\n");
592 /* Restore Volume header record */
593 memcpy(&dev->VolHdr, &VolHdr, sizeof(dev->VolHdr));
594 if (dev->open(dcr, mode) < 0) {
595 Dmsg0(400, "open dev() failed\n");
598 Dmsg2(400, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
604 /* Protected version of lseek, which opens the right part if necessary */
605 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
609 char ed1[50], ed2[50];
611 Dmsg5(400, "Enter lseek_dev fd=%d off=%s w=%d part=%d nparts=%d\n", dev->fd,
612 edit_int64(offset, ed1), whence, dev->part, dev->num_dvd_parts);
613 if (!dev->is_dvd()) {
614 Dmsg0(400, "Using sys lseek\n");
615 return lseek(dev->fd, offset, whence);
618 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
621 Dmsg2(400, "lseek_dev SEEK_SET to %s (part_start=%s)\n",
622 edit_int64(offset, ed1), edit_uint64(dev->part_start, ed2));
623 if ((uint64_t)offset >= dev->part_start) {
624 if ((uint64_t)offset == dev->part_start ||
625 (uint64_t)offset < dev->part_start+dev->part_size) {
626 /* We are staying in the current part, just seek */
627 if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
630 return pos + dev->part_start;
633 /* Load next part, and start again */
634 Dmsg0(100, "lseek open next part\n");
635 if (dvd_open_next_part(dcr) < 0) {
636 Dmsg0(400, "lseek_dev failed while trying to open the next part\n");
639 Dmsg2(100, "Recurse lseek after open next part=%d num_part=%d\n",
640 dev->part, dev->num_dvd_parts);
641 return lseek_dev(dev, offset, SEEK_SET);
645 * pos < dev->part_start :
646 * We need to access a previous part,
647 * so just load the first one, and seek again
648 * until the right one is loaded
650 Dmsg0(100, "lseek open first part\n");
651 if (dvd_open_first_part(dcr, dev->openmode) < 0) {
652 Dmsg0(400, "lseek_dev failed while trying to open the first part\n");
655 Dmsg2(100, "Recurse lseek after open first part=%d num_part=%d\n",
656 dev->part, dev->num_dvd_parts);
657 return lseek_dev(dev, offset, SEEK_SET);
661 Dmsg1(400, "lseek_dev SEEK_CUR to %s\n", edit_int64(offset, ed1));
662 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
663 Dmsg0(400, "Seek error.\n");
666 pos += dev->part_start;
668 Dmsg1(400, "lseek_dev SEEK_CUR returns %s\n", edit_uint64(pos, ed1));
671 Dmsg1(400, "do lseek_dev SEEK_SET %s\n", edit_uint64(pos, ed1));
672 return lseek_dev(dev, pos, SEEK_SET);
676 Dmsg1(400, "lseek_dev SEEK_END to %s\n", edit_int64(offset, ed1));
678 * Bacula does not use offsets for SEEK_END
679 * Also, Bacula uses seek_end only when it wants to
680 * append to the volume, so for a dvd that means
681 * that the volume must be spooled since the DVD
682 * itself is read-only (as currently implemented).
684 if (offset > 0) { /* Not used by bacula */
685 Dmsg1(400, "lseek_dev SEEK_END called with an invalid offset %s\n",
686 edit_uint64(offset, ed1));
690 /* If we are already on a spooled part and have the
691 * right part number, simply seek
693 if (dev->is_part_spooled() && dev->part > dev->num_dvd_parts) {
694 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
697 Dmsg1(400, "lseek_dev SEEK_END returns %s\n",
698 edit_uint64(pos + dev->part_start, ed1));
699 return pos + dev->part_start;
703 * Load the first part, then load the next until we reach the last one.
704 * This is the only way to be sure we compute the right file address.
706 * Save previous openmode, and open all but last part read-only
709 int modesave = dev->openmode;
710 if (dvd_open_first_part(dcr, OPEN_READ_ONLY) < 0) {
711 Dmsg0(400, "lseek_dev failed while trying to open the first part\n");
714 if (dev->num_dvd_parts > 0) {
715 while (dev->part < dev->num_dvd_parts) {
716 if (dvd_open_next_part(dcr) < 0) {
717 Dmsg0(400, "lseek_dev failed while trying to open the next part\n");
721 dev->openmode = modesave;
722 if (dvd_open_next_part(dcr) < 0) {
723 Dmsg0(400, "lseek_dev failed while trying to open the next part\n");
727 return lseek_dev(dev, 0, SEEK_END);
731 Dmsg0(400, "Seek call error.\n");
737 bool dvd_close_job(DCR *dcr)
739 DEVICE *dev = dcr->dev;
743 /* If the device is a dvd and WritePartAfterJob
744 * is set to yes, open the next part, so, in case of a device
745 * that requires mount, it will be written to the device.
747 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
748 Dmsg1(400, "Writing last part=%d write_partafter_job is set.\n",
750 if (dev->part < dev->num_dvd_parts+1) {
751 Jmsg3(jcr, M_FATAL, 0, _("Error writing. Current part less than total number of parts (%d/%d, device=%s)\n"),
752 dev->part, dev->num_dvd_parts, dev->print_name());
753 dev->dev_errno = EIO;
757 if (ok && !dvd_write_part(dcr)) {
758 Jmsg2(jcr, M_FATAL, 0, _("Unable to write last on %s: ERR=%s\n"),
759 dev->print_name(), dev->bstrerror());
760 dev->dev_errno = EIO;
767 bool truncate_dvd(DCR *dcr)
769 DEVICE* dev = dcr->dev;
772 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
774 if (!unmount_dvd(dev, 1)) {
775 Dmsg0(400, "truncate_dvd: Failed to unmount DVD\n");
779 /* Set num_dvd_parts to zero (on disk) */
780 dev->num_dvd_parts = 0;
781 dcr->VolCatInfo.VolCatParts = 0;
782 dev->VolCatInfo.VolCatParts = 0;
784 Dmsg0(400, "truncate_dvd: Opening first part (1)...\n");
786 dev->truncating = true;
787 if (dvd_open_first_part(dcr, CREATE_READ_WRITE) < 0) {
788 Dmsg0(400, "truncate_dvd: Error while opening first part (1).\n");
789 dev->truncating = false;
793 Dmsg0(400, "truncate_dvd: Truncating...\n");
795 /* If necessary, truncate it spool file. */
796 if (ftruncate(dev->fd, 0) != 0) {
798 Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"),
799 dev->print_name(), be.strerror());
800 dev->truncating = false;
805 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
807 Dmsg0(400, "truncate_dvd: Opening first part (2)...\n");
810 * Now actually truncate the DVD
811 * This is really kludgy, why not an argument or a separate
814 if (!dvd_write_part(dcr)) {
815 Dmsg0(400, "truncate_dvd: Error while writing to DVD.\n");
816 dev->truncating = false;
819 dev->truncating = false;
821 /* Set num_dvd_parts to zero (on disk) */
822 dev->num_dvd_parts = 0;
823 dcr->VolCatInfo.VolCatParts = 0;
824 dev->VolCatInfo.VolCatParts = 0;
827 if (!dir_update_volume_info(dcr, false)) {
831 if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
832 Dmsg0(400, "truncate_dvd: Error while opening first part (2).\n");
839 /* Checks if we can write on a non-blank DVD: meaning that it just have been
840 * truncated (there is only one zero-sized file on the DVD, with the right
843 * Note! Normally if we can mount the device, which should be the case
844 * when we get here, it is not a blank DVD. Hence we check if
845 * there is a zero length file with the right name, in which case
847 * This seems terribly kludgie to me. KES
849 bool check_can_write_on_non_blank_dvd(DCR *dcr)
851 DEVICE* dev = dcr->dev;
853 struct dirent *entry, *result;
856 bool matched = false;
857 struct stat filestat;
859 name_max = pathconf(".", _PC_NAME_MAX);
860 if (name_max < 1024) {
864 if (!(dp = opendir(dev->device->mount_point))) {
866 dev->dev_errno = errno;
867 Dmsg3(29, "check_can_write_on_non_blank_dvd: failed to open dir %s (dev=%s), ERR=%s\n",
868 dev->device->mount_point, dev->print_name(), be.strerror());
872 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
874 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
875 dev->dev_errno = EIO;
876 Dmsg2(129, "check_can_write_on_non_blank_dvd: no more files in dir %s (dev=%s)\n",
877 dev->device->mount_point, dev->print_name());
880 Dmsg2(99, "check_can_write_on_non_blank_dvd: found %s (versus %s)\n",
881 result->d_name, dev->VolCatInfo.VolCatName);
882 if (strcmp(result->d_name, dev->VolCatInfo.VolCatName) == 0) {
883 /* Found the file, checking it is empty */
884 POOL_MEM filename(PM_FNAME);
885 pm_strcpy(filename, dev->device->mount_point);
886 if (filename.c_str()[strlen(filename.c_str())-1] != '/') {
887 pm_strcat(filename, "/");
889 pm_strcat(filename, dev->VolCatInfo.VolCatName);
890 if (stat(filename.c_str(), &filestat) < 0) {
892 dev->dev_errno = errno;
893 Dmsg2(29, "check_can_write_on_non_blank_dvd: cannot stat file (file=%s), ERR=%s\n",
894 filename.c_str(), be.strerror());
897 Dmsg2(99, "check_can_write_on_non_blank_dvd: size of %s is %d\n",
898 filename.c_str(), filestat.st_size);
899 matched = filestat.st_size == 0;
908 /* There are more than 3 files (., .., and the volume file) */
909 Dmsg1(29, "Cannot write on blank DVD too many files %d greater than 3\n", count);
913 Dmsg2(29, "OK can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched);