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 /* Doesn't work with internationalisation (This is not a problem) */
139 if (fnmatch("*is already mounted on", results, 0) == 0) {
143 /* Sometimes the device cannot be mounted because it is already mounted.
144 * Try to unmount it, then remount it */
146 Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
147 do_mount_dev(dev, 0, 0);
152 Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results);
153 Mmsg(dev->errmsg, _("Device %s cannot be mounted. ERR=%s\n"),
154 dev->print_name(), results);
156 * Now, just to be sure it is not mounted, try to read the
160 struct dirent *entry, *result;
164 name_max = pathconf(".", _PC_NAME_MAX);
165 if (name_max < 1024) {
169 if (!(dp = opendir(dev->device->mount_point))) {
171 dev->dev_errno = errno;
172 Dmsg3(29, "open_mounted_dev: failed to open dir %s (dev=%s), ERR=%s\n",
173 dev->device->mount_point, dev->print_name(), be.strerror());
177 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
179 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
180 dev->dev_errno = EIO;
181 Dmsg2(129, "open_mounted_dev: failed to find suitable file in dir %s (dev=%s)\n",
182 dev->device->mount_point, dev->print_name());
185 if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
186 count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
189 Dmsg2(129, "open_mounted_dev: ignoring %s in %s\n",
190 result->d_name, dev->device->mount_point);
196 Dmsg1(29, "open_mounted_dev: got %d files in the mount point (not counting ., .. and .keep)\n", count);
199 mount = 1; /* If we got more than ., .. and .keep */
200 break; /* there must be something mounted */
203 dev->set_mounted(false);
204 sm_check(__FILE__, __LINE__, false);
205 free_pool_memory(results);
206 Dmsg0(200, "============ DVD mount=0\n");
210 dev->set_mounted(mount); /* set/clear mounted flag */
211 free_pool_memory(results);
212 /* Do not check free space when unmounting */
214 update_free_space_dev(dev);
216 Dmsg1(200, "============ DVD mount=%d\n", mount);
220 /* Update the free space on the device */
221 void update_free_space_dev(DEVICE* dev)
223 POOL_MEM ocmd(PM_FNAME);
230 /* The device must be mounted in order to dvd-freespace to work */
233 sm_check(__FILE__, __LINE__, false);
234 icmd = dev->device->free_space_command;
238 dev->free_space_errno = 0;
239 dev->clear_freespace_ok(); /* No valid freespace */
241 Dmsg2(29, "update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n",
242 edit_uint64(dev->free_space, ed1), dev->free_space_errno);
246 edit_device_codes_dev(dev, ocmd, icmd);
248 Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
250 results = get_pool_memory(PM_MESSAGE);
252 /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
256 if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
257 Dmsg1(100, "Free space program run : %s\n", results);
258 free = str_to_int64(results);
260 dev->free_space = free;
261 dev->free_space_errno = 0;
262 dev->set_freespace_ok(); /* have valid freespace */
264 Mmsg0(dev->errmsg, "");
269 dev->free_space_errno = EPIPE;
270 dev->clear_freespace_ok(); /* no valid freespace */
271 Mmsg1(dev->errmsg, _("Cannot run free space command (%s)\n"), results);
274 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
275 "free_space_errno=%d ERR=%s\n", dev->print_name(),
276 edit_uint64(dev->free_space, ed1), dev->free_space_errno,
282 dev->dev_errno = dev->free_space_errno;
283 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
284 "free_space_errno=%d ERR=%s\n",
285 dev->print_name(), edit_uint64(dev->free_space, ed1),
286 dev->free_space_errno, dev->errmsg);
290 free_pool_memory(results);
291 Dmsg4(29, "update_free_space_dev: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n",
292 edit_uint64(dev->free_space, ed1), !!dev->is_freespace_ok(), dev->free_space_errno, !!dev->have_media());
293 sm_check(__FILE__, __LINE__, false);
298 * Write a part (Vol, Vol.1, ...) from the spool to the DVD
299 * This routine does not update the part number, so normally, you
300 * should call open_next_part()
301 * It is also called from truncate_dvd_dev to "blank" the medium, as
302 * well as from block.c when the DVD is full to write the last part.
304 bool dvd_write_part(DCR *dcr)
306 DEVICE *dev = dcr->dev;
307 POOL_MEM archive_name(PM_FNAME);
309 /* Don't write empty part files.
310 * This is only useful when growisofs does not support write beyond
313 * - 3.9 GB on the volume, dvd-freespace reports 0.4 GB free
314 * - Write 0.2 GB on the volume, Bacula thinks it could still
315 * append data, it creates a new empty part.
316 * - dvd-freespace reports 0 GB free, as the 4GB boundary has
318 * - Bacula thinks he must finish to write to the device, so it
319 * tries to write the last part (0-byte), but dvd-writepart fails...
321 * There is one exception: when recycling a volume, we write a blank part
322 * file, so, then, we need to accept to write it.
324 if ((dev->part_size == 0) && (dev->part > 0)) {
325 Dmsg2(29, "dvd_write_part: device is %s, won't write blank part %d\n", dev->print_name(), dev->part);
326 /* Delete spool file */
327 make_spooled_dvd_filename(dev, archive_name);
328 unlink(archive_name.c_str());
329 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
330 sm_check(__FILE__, __LINE__, false);
334 POOL_MEM ocmd(PM_FNAME);
335 POOL_MEM results(PM_MESSAGE);
341 sm_check(__FILE__, __LINE__, false);
342 Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
343 icmd = dev->device->write_part_command;
345 edit_device_codes_dev(dev, ocmd, icmd);
348 * original line follows
349 * timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
350 * I modified this for a longer timeout; pre-formatting, blanking and
351 * writing can take quite a while
354 /* Explanation of the timeout value, when writing the first part,
356 * 9 GB, write speed 1x: 6990 seconds (almost 2 hours...)
357 * Overhead: 900 seconds (starting, initializing, finalizing,probably
358 * reloading 15 minutes)
360 * A reasonable last-exit timeout would be 16000 seconds. Quite long -
361 * almost 4.5 hours, but hopefully, that timeout will only ever be needed
362 * in case of a serious emergency.
368 timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4));
370 Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
372 status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
374 Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"),
376 Dmsg1(000, "%s", dev->errmsg);
377 dev->dev_errno = EIO;
378 mark_volume_in_error(dcr);
379 sm_check(__FILE__, __LINE__, false);
382 dev->num_parts++; /* there is now one more part on DVD */
385 /* Delete spool file */
386 make_spooled_dvd_filename(dev, archive_name);
387 unlink(archive_name.c_str());
388 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
389 sm_check(__FILE__, __LINE__, false);
391 /* growisofs umounted the device, so remount it (it will update the free space) */
392 dev->clear_mounted();
394 Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"),
395 edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
396 sm_check(__FILE__, __LINE__, false);
400 /* Open the next part file.
402 * - Increment part number
403 * - Reopen the device
405 int dvd_open_next_part(DCR *dcr)
407 DEVICE *dev = dcr->dev;
409 Dmsg6(29, "Enter: ==== open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n",
410 dev->part, dev->num_parts, dev->print_name(),
411 dev->VolCatInfo.VolCatName, dev->openmode, dev->file_addr);
412 if (!dev->is_dvd()) {
413 Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name());
417 /* When appending, do not open a new part if the current is empty */
418 if (dev->can_append() && (dev->part >= dev->num_parts) &&
419 (dev->part_size == 0)) {
420 Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
432 * If we have a part open for write, then write it to
433 * DVD before opening the next part.
435 if (dev->is_dvd() && (dev->part >= dev->num_parts) && dev->can_append()) {
436 if (!dvd_write_part(dcr)) {
437 Dmsg0(29, "Error in dvd_write part.\n");
442 if (dev->part > dev->num_parts) {
443 Dmsg2(000, "In open_next_part: part=%d nump=%d\n", dev->part, dev->num_parts);
444 ASSERT(dev->part <= dev->num_parts);
446 dev->part_start += dev->part_size;
449 Dmsg2(29, "part=%d num_parts=%d\n", dev->part, dev->num_parts);
450 /* I think this dev->can_append() should not be there */
451 if ((dev->num_parts < dev->part) && dev->can_append()) {
452 POOL_MEM archive_name(PM_FNAME);
455 * First check what is on DVD. If our part is there, we
456 * are in trouble, so bail out.
457 * NB: This is however not a problem if we are writing the first part.
458 * It simply means that we are overriding an existing volume...
460 if (dev->num_parts > 0) {
461 make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
462 if (stat(archive_name.c_str(), &buf) == 0) {
463 /* bad news bail out */
464 Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
465 archive_name.c_str());
470 Dmsg2(100, "num_parts=%d part=%d\n", dev->num_parts, dev->part);
471 dev->VolCatInfo.VolCatParts = dev->part;
472 make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
474 /* Check if the next part exists in spool directory . */
475 if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
476 Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
477 /* Then try to unlink it */
478 if (unlink(archive_name.c_str()) < 0) {
480 dev->dev_errno = errno;
481 Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
482 archive_name.c_str(), be.strerror());
487 /* KES. It seems to me that this if should not be
488 * needed. If num_parts represents what is on the DVD
489 * we should only need to change it when writing a part
491 * NB. As dvd_write_part increments dev->num_parts, I also
492 * think it is not needed.
494 if (dev->num_parts < dev->part) {
495 Dmsg2(100, "Set npart=%d to part=%d\n", dev->num_parts, dev->part);
496 dev->num_parts = dev->part;
497 dev->VolCatInfo.VolCatParts = dev->part;
499 Dmsg2(50, "Call dev->open(vol=%s, mode=%d\n", dev->VolCatInfo.VolCatName,
503 int append = dev->can_append();
504 if (dev->open(dcr, dev->openmode) < 0) {
507 dev->set_labeled(); /* all next parts are "labeled" */
508 if (append && (dev->part == dev->num_parts)) { /* If needed, set the append flag back */
515 /* Open the first part file.
517 * - Reopen the device
519 int dvd_open_first_part(DCR *dcr, int mode)
521 DEVICE *dev = dcr->dev;
523 Dmsg5(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d num_parts=%d append=%d\n", dev->print_name(),
524 dev->VolCatInfo.VolCatName, dev->openmode, dev->num_parts, dev->can_append());
535 Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
537 int append = dev->can_append();
538 if (dev->open(dcr, mode) < 0) {
539 Dmsg0(50, "open dev() failed\n");
542 if (append && (dev->part == dev->num_parts)) { /* If needed, set the append flag back */
545 Dmsg2(50, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
551 /* Protected version of lseek, which opens the right part if necessary */
552 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
556 char ed1[50], ed2[50];
558 Dmsg3(100, "Enter lseek_dev fd=%d part=%d nparts=%d\n", dev->fd,
559 dev->part, dev->num_parts);
560 if (!dev->is_dvd()) {
561 Dmsg0(100, "Using sys lseek\n");
562 return lseek(dev->fd, offset, whence);
565 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
568 Dmsg2(100, "lseek_dev SEEK_SET to %s (part_start=%s)\n",
569 edit_uint64(offset, ed1), edit_uint64(dev->part_start, ed2));
570 if ((uint64_t)offset >= dev->part_start) {
571 if (((uint64_t)offset == dev->part_start) || ((uint64_t)offset < (dev->part_start+dev->part_size))) {
572 /* We are staying in the current part, just seek */
573 if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
576 return pos + dev->part_start;
579 /* Load next part, and start again */
580 if (dvd_open_next_part(dcr) < 0) {
581 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
584 return lseek_dev(dev, offset, SEEK_SET);
588 * pos < dev->part_start :
589 * We need to access a previous part,
590 * so just load the first one, and seek again
591 * until the right one is loaded
593 if (dvd_open_first_part(dcr, dev->openmode) < 0) {
594 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
597 return lseek_dev(dev, offset, SEEK_SET);
601 Dmsg1(100, "lseek_dev SEEK_CUR to %s\n", edit_uint64(offset, ed1));
602 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
605 pos += dev->part_start;
607 Dmsg1(100, "lseek_dev SEEK_CUR returns %s\n", edit_uint64(pos, ed1));
609 } else { /* Not used in Bacula, but should work */
610 return lseek_dev(dev, pos, SEEK_SET);
614 Dmsg1(100, "lseek_dev SEEK_END to %s\n", edit_uint64(offset, ed1));
616 * Bacula does not use offsets for SEEK_END
617 * Also, Bacula uses seek_end only when it wants to
618 * append to the volume, so for a dvd that means
619 * that the volume must be spooled since the DVD
620 * itself is read-only (as currently implemented).
622 if (offset > 0) { /* Not used by bacula */
623 Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %s\n",
624 edit_uint64(offset, ed1));
628 /* If we are already on a spooled part and have the
629 * right part number, simply seek
631 if (dev->is_part_spooled() && dev->part == dev->num_parts) {
632 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
635 Dmsg1(100, "lseek_dev SEEK_END returns %s\n",
636 edit_uint64(pos + dev->part_start, ed1));
637 return pos + dev->part_start;
641 * Load the first part, then load the next until we reach the last one.
642 * This is the only way to be sure we compute the right file address.
644 * Save previous openmode, and open all but last part read-only
647 int modesave = dev->openmode;
648 /* Works because num_parts > 0. */
649 if (dvd_open_first_part(dcr, OPEN_READ_ONLY) < 0) {
650 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
653 if (dev->num_parts > 0) {
654 while (dev->part < (dev->num_parts-1)) {
655 if (dvd_open_next_part(dcr) < 0) {
656 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
660 dev->openmode = modesave;
661 if (dvd_open_next_part(dcr) < 0) {
662 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
666 return lseek_dev(dev, 0, SEEK_END);
675 bool dvd_close_job(DCR *dcr)
677 DEVICE *dev = dcr->dev;
681 /* If the device is a dvd and WritePartAfterJob
682 * is set to yes, open the next part, so, in case of a device
683 * that requires mount, it will be written to the device.
685 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
686 Dmsg1(100, "Writing last part=%d write_partafter_job is set.\n",
688 if (dev->part < dev->num_parts) {
689 Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
690 dev->part, dev->num_parts, dev->print_name());
691 dev->dev_errno = EIO;
695 /* This should be !dvd_write_part(dcr)
696 NB: No! If you call dvd_write_part, the part number is not updated.
697 You must open the next part, it will automatically write the part and
698 update the part number. */
699 if (ok && (dvd_open_next_part(dcr) < 0)) {
700 Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"),
701 dev->print_name(), strerror_dev(dev));
702 dev->dev_errno = EIO;
706 Dmsg1(200, "Set VolCatParts=%d\n", dev->num_parts);
707 dev->VolCatInfo.VolCatParts = dev->num_parts;
711 bool truncate_dvd_dev(DCR *dcr) {
712 DEVICE* dev = dcr->dev;
714 /* Set num_parts to zero (on disk) */
716 dcr->VolCatInfo.VolCatParts = 0;
717 dev->VolCatInfo.VolCatParts = 0;
719 Dmsg0(100, "truncate_dvd_dev: Opening first part (1)...\n");
721 dev->truncating = true;
722 if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
723 Dmsg0(100, "truncate_dvd_dev: Error while opening first part (1).\n");
724 dev->truncating = false;
727 dev->truncating = false;
729 Dmsg0(100, "truncate_dvd_dev: Truncating...\n");
731 /* If necessary, truncate it. */
732 if (ftruncate(dev->fd, 0) != 0) {
734 Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"),
735 dev->print_name(), be.strerror());
743 Dmsg0(100, "truncate_dvd_dev: Opening first part (2)...\n");
745 if (!dvd_write_part(dcr)) {
746 Dmsg0(100, "truncate_dvd_dev: Error while writing to DVD.\n");
750 /* Set num_parts to zero (on disk) */
752 dcr->VolCatInfo.VolCatParts = 0;
753 dev->VolCatInfo.VolCatParts = 0;
755 if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
756 Dmsg0(100, "truncate_dvd_dev: Error while opening first part (2).\n");
763 /* Checks if we can write on a non-blank DVD: meaning that it just have been
764 * truncated (there is only one zero-sized file on the DVD, with the right
766 bool check_can_write_on_non_blank_dvd(DCR *dcr) {
767 DEVICE* dev = dcr->dev;
769 struct dirent *entry, *result;
772 int matched = 0; /* We found an empty file with the right name. */
773 struct stat filestat;
775 name_max = pathconf(".", _PC_NAME_MAX);
776 if (name_max < 1024) {
780 if (!(dp = opendir(dev->device->mount_point))) {
782 dev->dev_errno = errno;
783 Dmsg3(29, "check_can_write_on_non_blank_dvd: failed to open dir %s (dev=%s), ERR=%s\n",
784 dev->device->mount_point, dev->print_name(), be.strerror());
788 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
790 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
791 dev->dev_errno = EIO;
792 Dmsg2(129, "check_can_write_on_non_blank_dvd: failed to find suitable file in dir %s (dev=%s)\n",
793 dev->device->mount_point, dev->print_name());
797 Dmsg2(99, "check_can_write_on_non_blank_dvd: found %s (versus %s)\n",
798 result->d_name, dev->VolCatInfo.VolCatName);
799 if (strcmp(result->d_name, dev->VolCatInfo.VolCatName) == 0) {
800 /* Found the file, checking it is empty */
801 POOL_MEM filename(PM_FNAME);
802 pm_strcpy(filename, dev->device->mount_point);
803 if (filename.c_str()[strlen(filename.c_str())-1] != '/') {
804 pm_strcat(filename, "/");
806 pm_strcat(filename, dev->VolCatInfo.VolCatName);
807 if (stat(filename.c_str(), &filestat) < 0) {
809 dev->dev_errno = errno;
810 Dmsg2(29, "check_can_write_on_non_blank_dvd: cannot stat file (file=%s), ERR=%s\n",
811 filename.c_str(), be.strerror());
814 Dmsg2(99, "check_can_write_on_non_blank_dvd: size of %s is %d\n",
815 filename.c_str(), filestat.st_size);
816 matched = (filestat.st_size == 0);
824 Dmsg2(29, "check_can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched);
827 /* There is more than 3 files (., .., and the volume file) */
835 * Edit codes into (Un)MountCommand, Write(First)PartCommand
837 * %a = archive device name
838 * %e = erase (set if cannot mount and first part)
841 * %v = last part name
843 * omsg = edited output message
844 * imsg = input string containing edit codes (%x)
847 static void edit_device_codes_dev(DEVICE* dev, POOL_MEM &omsg, const char *imsg)
853 POOL_MEM archive_name(PM_FNAME);
856 Dmsg1(800, "edit_device_codes: %s\n", imsg);
857 for (p=imsg; *p; p++) {
867 if (dev->num_parts == 0) {
874 bsnprintf(add, sizeof(add), "%d", dev->part);
878 str = dev->device->mount_point;
881 make_spooled_dvd_filename(dev, archive_name);
882 str = archive_name.c_str();
896 Dmsg1(1900, "add_str %s\n", str);
897 pm_strcat(omsg, (char *)str);
898 Dmsg1(1800, "omsg=%s\n", omsg.c_str());