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(100, "Exit make_dvd_filename: 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 while ((status = run_program_full_output(ocmd.c_str(),
139 dev->max_open_wait/2, results)) != 0) {
140 /* Doesn't work with internationalisation (This is not a problem) */
141 if (fnmatch("*is already mounted on", results, 0) == 0) {
145 /* Sometimes the device cannot be mounted because it is already mounted.
146 * Try to unmount it, then remount it */
148 Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
149 do_mount_dvd(dev, 0, 0);
154 Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results);
155 Mmsg(dev->errmsg, _("Device %s cannot be mounted. ERR=%s\n"),
156 dev->print_name(), results);
158 * Now, just to be sure it is not mounted, try to read the
162 struct dirent *entry, *result;
166 name_max = pathconf(".", _PC_NAME_MAX);
167 if (name_max < 1024) {
171 if (!(dp = opendir(dev->device->mount_point))) {
173 dev->dev_errno = errno;
174 Dmsg3(29, "do_mount_dvd: failed to open dir %s (dev=%s), ERR=%s\n",
175 dev->device->mount_point, dev->print_name(), be.strerror());
179 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
182 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
183 dev->dev_errno = EIO;
184 Dmsg2(129, "do_mount_dvd: failed to find suitable file in dir %s (dev=%s)\n",
185 dev->device->mount_point, dev->print_name());
188 if (strcmp(result->d_name, ".") && strcmp(result->d_name, "..") &&
189 strcmp(result->d_name, ".keep")) {
190 count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
194 Dmsg2(129, "do_mount_dvd: ignoring %s in %s\n",
195 result->d_name, dev->device->mount_point);
201 Dmsg1(29, "do_mount_dvd: got %d files in the mount point (not counting ., .. and .keep)\n", count);
204 mount = 1; /* If we got more than ., .. and .keep */
205 break; /* there must be something mounted */
208 dev->set_mounted(false);
209 sm_check(__FILE__, __LINE__, false);
210 free_pool_memory(results);
211 Dmsg0(200, "============ DVD mount=0\n");
215 dev->set_mounted(mount); /* set/clear mounted flag */
216 free_pool_memory(results);
217 /* Do not check free space when unmounting */
219 update_free_space_dev(dev);
221 Dmsg1(200, "============ DVD mount=%d\n", mount);
225 /* Update the free space on the device */
226 void update_free_space_dev(DEVICE* dev)
228 POOL_MEM ocmd(PM_FNAME);
235 /* The device must be mounted in order to dvd-freespace to work */
238 sm_check(__FILE__, __LINE__, false);
239 icmd = dev->device->free_space_command;
243 dev->free_space_errno = 0;
244 dev->clear_freespace_ok(); /* No valid freespace */
246 Dmsg2(29, "update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n",
247 edit_uint64(dev->free_space, ed1), dev->free_space_errno);
251 dev->edit_mount_codes(ocmd, icmd);
253 Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
255 results = get_pool_memory(PM_MESSAGE);
257 /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
261 if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
262 Dmsg1(100, "Free space program run : %s\n", results);
263 free = str_to_int64(results);
265 dev->free_space = free;
266 dev->free_space_errno = 0;
267 dev->set_freespace_ok(); /* have valid freespace */
269 Mmsg0(dev->errmsg, "");
274 dev->free_space_errno = EPIPE;
275 dev->clear_freespace_ok(); /* no valid freespace */
276 Mmsg1(dev->errmsg, _("Cannot run free space command (%s)\n"), results);
279 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
280 "free_space_errno=%d ERR=%s\n", dev->print_name(),
281 edit_uint64(dev->free_space, ed1), dev->free_space_errno,
287 dev->dev_errno = dev->free_space_errno;
288 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
289 "free_space_errno=%d ERR=%s\n",
290 dev->print_name(), edit_uint64(dev->free_space, ed1),
291 dev->free_space_errno, dev->errmsg);
295 free_pool_memory(results);
296 Dmsg4(29, "update_free_space_dev: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n",
297 edit_uint64(dev->free_space, ed1), !!dev->is_freespace_ok(), dev->free_space_errno, !!dev->have_media());
298 sm_check(__FILE__, __LINE__, false);
303 * Write a part (Vol, Vol.1, ...) from the spool to the DVD
304 * This routine does not update the part number, so normally, you
305 * should call open_next_part()
306 * It is also called from truncate_dvd to "blank" the medium, as
307 * well as from block.c when the DVD is full to write the last part.
309 bool dvd_write_part(DCR *dcr)
311 DEVICE *dev = dcr->dev;
312 POOL_MEM archive_name(PM_FNAME);
314 /* Don't write empty part files.
315 * This is only useful when growisofs does not support write beyond
318 * - 3.9 GB on the volume, dvd-freespace reports 0.4 GB free
319 * - Write 0.2 GB on the volume, Bacula thinks it could still
320 * append data, it creates a new empty part.
321 * - dvd-freespace reports 0 GB free, as the 4GB boundary has
323 * - Bacula thinks he must finish to write to the device, so it
324 * tries to write the last part (0-byte), but dvd-writepart fails...
326 * There is one exception: when recycling a volume, we write a blank part
327 * file, so, then, we need to accept to write it.
329 if ((dev->part_size == 0) && (dev->part > 0)) {
330 Dmsg2(29, "dvd_write_part: device is %s, won't write blank part %d\n", dev->print_name(), dev->part);
331 /* Delete spool file */
332 make_spooled_dvd_filename(dev, archive_name);
333 unlink(archive_name.c_str());
334 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
335 sm_check(__FILE__, __LINE__, false);
339 POOL_MEM ocmd(PM_FNAME);
340 POOL_MEM results(PM_MESSAGE);
346 sm_check(__FILE__, __LINE__, false);
347 Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
348 icmd = dev->device->write_part_command;
350 dev->edit_mount_codes(ocmd, icmd);
353 * original line follows
354 * timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
355 * I modified this for a longer timeout; pre-formatting, blanking and
356 * writing can take quite a while
359 /* Explanation of the timeout value, when writing the first part,
361 * 9 GB, write speed 1x: 6990 seconds (almost 2 hours...)
362 * Overhead: 900 seconds (starting, initializing, finalizing,probably
363 * reloading 15 minutes)
365 * A reasonable last-exit timeout would be 16000 seconds. Quite long -
366 * almost 4.5 hours, but hopefully, that timeout will only ever be needed
367 * in case of a serious emergency.
373 timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4));
375 Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
377 status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
379 Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"),
381 Dmsg1(000, "%s", dev->errmsg);
382 dev->dev_errno = EIO;
383 mark_volume_in_error(dcr);
384 sm_check(__FILE__, __LINE__, false);
387 dev->num_parts++; /* there is now one more part on DVD */
390 /* Delete spool file */
391 make_spooled_dvd_filename(dev, archive_name);
392 unlink(archive_name.c_str());
393 Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
394 sm_check(__FILE__, __LINE__, false);
396 /* growisofs umounted the device, so remount it (it will update the free space) */
397 dev->clear_mounted();
399 Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"),
400 edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
401 sm_check(__FILE__, __LINE__, false);
405 /* Open the next part file.
407 * - Increment part number
408 * - Reopen the device
410 int dvd_open_next_part(DCR *dcr)
412 DEVICE *dev = dcr->dev;
414 Dmsg6(29, "Enter: ==== open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n",
415 dev->part, dev->num_parts, dev->print_name(),
416 dev->VolCatInfo.VolCatName, dev->openmode, dev->file_addr);
417 if (!dev->is_dvd()) {
418 Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name());
422 /* When appending, do not open a new part if the current is empty */
423 if (dev->can_append() && (dev->part >= dev->num_parts) &&
424 (dev->part_size == 0)) {
425 Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
437 * If we have a part open for write, then write it to
438 * DVD before opening the next part.
440 if (dev->is_dvd() && (dev->part >= dev->num_parts) && dev->can_append()) {
441 if (!dvd_write_part(dcr)) {
442 Dmsg0(29, "Error in dvd_write part.\n");
447 if (dev->part > dev->num_parts) {
448 Dmsg2(000, "In open_next_part: part=%d nump=%d\n", dev->part, dev->num_parts);
449 ASSERT(dev->part <= dev->num_parts);
451 dev->part_start += dev->part_size;
454 Dmsg2(29, "part=%d num_parts=%d\n", dev->part, dev->num_parts);
455 /* I think this dev->can_append() should not be there */
456 if ((dev->num_parts < dev->part) && dev->can_append()) {
457 POOL_MEM archive_name(PM_FNAME);
460 * First check what is on DVD. If our part is there, we
461 * are in trouble, so bail out.
462 * NB: This is however not a problem if we are writing the first part.
463 * It simply means that we are overriding an existing volume...
465 if (dev->num_parts > 0) {
466 make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
467 if (stat(archive_name.c_str(), &buf) == 0) {
468 /* bad news bail out */
469 Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
470 archive_name.c_str());
475 Dmsg2(100, "num_parts=%d part=%d\n", dev->num_parts, dev->part);
476 dev->VolCatInfo.VolCatParts = dev->part;
477 make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
479 /* Check if the next part exists in spool directory . */
480 if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
481 Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
482 /* Then try to unlink it */
483 if (unlink(archive_name.c_str()) < 0) {
485 dev->dev_errno = errno;
486 Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
487 archive_name.c_str(), be.strerror());
492 /* KES. It seems to me that this if should not be
493 * needed. If num_parts represents what is on the DVD
494 * we should only need to change it when writing a part
496 * NB. As dvd_write_part increments dev->num_parts, I also
497 * think it is not needed.
499 if (dev->num_parts < dev->part) {
500 Dmsg2(100, "Set npart=%d to part=%d\n", dev->num_parts, dev->part);
501 dev->num_parts = dev->part;
502 dev->VolCatInfo.VolCatParts = dev->part;
504 Dmsg2(50, "Call dev->open(vol=%s, mode=%d\n", dev->VolCatInfo.VolCatName,
508 int append = dev->can_append();
509 if (dev->open(dcr, dev->openmode) < 0) {
512 dev->set_labeled(); /* all next parts are "labeled" */
513 if (append && (dev->part == dev->num_parts)) { /* If needed, set the append flag back */
520 /* Open the first part file.
522 * - Reopen the device
524 int dvd_open_first_part(DCR *dcr, int mode)
526 DEVICE *dev = dcr->dev;
528 Dmsg5(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d num_parts=%d append=%d\n", dev->print_name(),
529 dev->VolCatInfo.VolCatName, dev->openmode, dev->num_parts, dev->can_append());
540 Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
542 int append = dev->can_append();
543 if (dev->open(dcr, mode) < 0) {
544 Dmsg0(50, "open dev() failed\n");
547 if (append && (dev->part == dev->num_parts)) { /* If needed, set the append flag back */
550 Dmsg2(50, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
556 /* Protected version of lseek, which opens the right part if necessary */
557 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
561 char ed1[50], ed2[50];
563 Dmsg3(100, "Enter lseek_dev fd=%d part=%d nparts=%d\n", dev->fd,
564 dev->part, dev->num_parts);
565 if (!dev->is_dvd()) {
566 Dmsg0(100, "Using sys lseek\n");
567 return lseek(dev->fd, offset, whence);
570 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
573 Dmsg2(100, "lseek_dev SEEK_SET to %s (part_start=%s)\n",
574 edit_uint64(offset, ed1), edit_uint64(dev->part_start, ed2));
575 if ((uint64_t)offset >= dev->part_start) {
576 if (((uint64_t)offset == dev->part_start) || ((uint64_t)offset < (dev->part_start+dev->part_size))) {
577 /* We are staying in the current part, just seek */
578 if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
581 return pos + dev->part_start;
584 /* Load next part, and start again */
585 if (dvd_open_next_part(dcr) < 0) {
586 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
589 return lseek_dev(dev, offset, SEEK_SET);
593 * pos < dev->part_start :
594 * We need to access a previous part,
595 * so just load the first one, and seek again
596 * until the right one is loaded
598 if (dvd_open_first_part(dcr, dev->openmode) < 0) {
599 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
602 return lseek_dev(dev, offset, SEEK_SET);
606 Dmsg1(100, "lseek_dev SEEK_CUR to %s\n", edit_uint64(offset, ed1));
607 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
610 pos += dev->part_start;
612 Dmsg1(100, "lseek_dev SEEK_CUR returns %s\n", edit_uint64(pos, ed1));
614 } else { /* Not used in Bacula, but should work */
615 return lseek_dev(dev, pos, SEEK_SET);
619 Dmsg1(100, "lseek_dev SEEK_END to %s\n", edit_uint64(offset, ed1));
621 * Bacula does not use offsets for SEEK_END
622 * Also, Bacula uses seek_end only when it wants to
623 * append to the volume, so for a dvd that means
624 * that the volume must be spooled since the DVD
625 * itself is read-only (as currently implemented).
627 if (offset > 0) { /* Not used by bacula */
628 Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %s\n",
629 edit_uint64(offset, ed1));
633 /* If we are already on a spooled part and have the
634 * right part number, simply seek
636 if (dev->is_part_spooled() && dev->part == dev->num_parts) {
637 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
640 Dmsg1(100, "lseek_dev SEEK_END returns %s\n",
641 edit_uint64(pos + dev->part_start, ed1));
642 return pos + dev->part_start;
646 * Load the first part, then load the next until we reach the last one.
647 * This is the only way to be sure we compute the right file address.
649 * Save previous openmode, and open all but last part read-only
652 int modesave = dev->openmode;
653 /* Works because num_parts > 0. */
654 if (dvd_open_first_part(dcr, OPEN_READ_ONLY) < 0) {
655 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
658 if (dev->num_parts > 0) {
659 while (dev->part < (dev->num_parts-1)) {
660 if (dvd_open_next_part(dcr) < 0) {
661 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
665 dev->openmode = modesave;
666 if (dvd_open_next_part(dcr) < 0) {
667 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
671 return lseek_dev(dev, 0, SEEK_END);
680 bool dvd_close_job(DCR *dcr)
682 DEVICE *dev = dcr->dev;
686 /* If the device is a dvd and WritePartAfterJob
687 * is set to yes, open the next part, so, in case of a device
688 * that requires mount, it will be written to the device.
690 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
691 Dmsg1(100, "Writing last part=%d write_partafter_job is set.\n",
693 if (dev->part < dev->num_parts) {
694 Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
695 dev->part, dev->num_parts, dev->print_name());
696 dev->dev_errno = EIO;
700 /* This should be !dvd_write_part(dcr)
701 NB: No! If you call dvd_write_part, the part number is not updated.
702 You must open the next part, it will automatically write the part and
703 update the part number. */
704 if (ok && (dvd_open_next_part(dcr) < 0)) {
705 Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"),
706 dev->print_name(), strerror_dev(dev));
707 dev->dev_errno = EIO;
711 Dmsg1(200, "Set VolCatParts=%d\n", dev->num_parts);
712 dev->VolCatInfo.VolCatParts = dev->num_parts;
716 bool truncate_dvd(DCR *dcr) {
717 DEVICE* dev = dcr->dev;
719 /* Set num_parts to zero (on disk) */
721 dcr->VolCatInfo.VolCatParts = 0;
722 dev->VolCatInfo.VolCatParts = 0;
724 Dmsg0(100, "truncate_dvd: Opening first part (1)...\n");
726 dev->truncating = true;
727 if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
728 Dmsg0(100, "truncate_dvd: Error while opening first part (1).\n");
729 dev->truncating = false;
732 dev->truncating = false;
734 Dmsg0(100, "truncate_dvd: Truncating...\n");
736 /* If necessary, truncate it. */
737 if (ftruncate(dev->fd, 0) != 0) {
739 Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"),
740 dev->print_name(), be.strerror());
748 Dmsg0(100, "truncate_dvd: Opening first part (2)...\n");
750 if (!dvd_write_part(dcr)) {
751 Dmsg0(100, "truncate_dvd: Error while writing to DVD.\n");
755 /* Set num_parts to zero (on disk) */
757 dcr->VolCatInfo.VolCatParts = 0;
758 dev->VolCatInfo.VolCatParts = 0;
760 if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
761 Dmsg0(100, "truncate_dvd: Error while opening first part (2).\n");
768 /* Checks if we can write on a non-blank DVD: meaning that it just have been
769 * truncated (there is only one zero-sized file on the DVD, with the right
771 bool check_can_write_on_non_blank_dvd(DCR *dcr) {
772 DEVICE* dev = dcr->dev;
774 struct dirent *entry, *result;
777 int matched = 0; /* We found an empty file with the right name. */
778 struct stat filestat;
780 name_max = pathconf(".", _PC_NAME_MAX);
781 if (name_max < 1024) {
785 if (!(dp = opendir(dev->device->mount_point))) {
787 dev->dev_errno = errno;
788 Dmsg3(29, "check_can_write_on_non_blank_dvd: failed to open dir %s (dev=%s), ERR=%s\n",
789 dev->device->mount_point, dev->print_name(), be.strerror());
793 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
795 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
796 dev->dev_errno = EIO;
797 Dmsg2(129, "check_can_write_on_non_blank_dvd: failed to find suitable file in dir %s (dev=%s)\n",
798 dev->device->mount_point, dev->print_name());
801 Dmsg2(99, "check_can_write_on_non_blank_dvd: found %s (versus %s)\n",
802 result->d_name, dev->VolCatInfo.VolCatName);
803 if (strcmp(result->d_name, dev->VolCatInfo.VolCatName) == 0) {
804 /* Found the file, checking it is empty */
805 POOL_MEM filename(PM_FNAME);
806 pm_strcpy(filename, dev->device->mount_point);
807 if (filename.c_str()[strlen(filename.c_str())-1] != '/') {
808 pm_strcat(filename, "/");
810 pm_strcat(filename, dev->VolCatInfo.VolCatName);
811 if (stat(filename.c_str(), &filestat) < 0) {
813 dev->dev_errno = errno;
814 Dmsg2(29, "check_can_write_on_non_blank_dvd: cannot stat file (file=%s), ERR=%s\n",
815 filename.c_str(), be.strerror());
818 Dmsg2(99, "check_can_write_on_non_blank_dvd: size of %s is %d\n",
819 filename.c_str(), filestat.st_size);
820 matched = filestat.st_size == 0;
828 Dmsg2(29, "check_can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched);
831 /* There are more than 3 files (., .., and the volume file) */