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 ammended 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 char *edit_device_codes_dev(DEVICE *dev, char *omsg, const char *imsg);
30 static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout);
31 static bool dvd_write_part(DEVICE *dev);
32 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name);
35 * Write the current volume/part filename to archive_name.
37 void make_mounted_dvd_filename(DEVICE *dev, POOL_MEM &archive_name)
39 pm_strcpy(archive_name, dev->device->mount_point);
40 add_file_and_part_name(dev, archive_name);
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);
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 != 0, 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_dev(DEVICE* dev, int timeout)
77 Dmsg0(900, "Enter mount_dev\n");
78 if (dev->is_mounted()) {
80 } else if (dev->requires_mount()) {
81 return do_mount_dev(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_dev(DEVICE *dev, int timeout)
92 Dmsg0(900, "Enter unmount_dev\n");
93 if (dev->is_mounted()) {
94 return do_mount_dev(dev, 0, timeout);
99 /* (Un)mount the device */
100 static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
102 POOL_MEM ocmd(PM_FNAME);
108 if (dev->is_mounted()) {
111 icmd = dev->device->mount_command;
113 if (!dev->is_mounted()) {
116 icmd = dev->device->unmount_command;
119 edit_device_codes_dev(dev, ocmd.c_str(), icmd);
121 Dmsg2(200, "do_mount_dev: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
124 /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
129 results = get_pool_memory(PM_MESSAGE);
131 /* If busy retry each second */
132 while ((status = run_program_full_output(ocmd.c_str(),
133 dev->max_open_wait/2, results)) != 0) {
134 if (fnmatch("*is already mounted on", results, 0) == 0) {
138 /* Sometimes the device cannot be mounted because it is already mounted.
139 * Try to unmount it, then remount it */
141 Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
142 do_mount_dev(dev, 0, 0);
147 Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results);
148 Mmsg(dev->errmsg, "Device %s cannot be mounted. ERR=%s\n",
149 dev->print_name(), results);
150 free_pool_memory(results);
154 dev->set_mounted(mount); /* set/clear mounted flag */
155 free_pool_memory(results);
159 /* Update the free space on the device */
160 void update_free_space_dev(DEVICE* dev)
162 POOL_MEM ocmd(PM_FNAME);
169 icmd = dev->device->free_space_command;
173 dev->free_space_errno = 0;
175 Dmsg2(29, "update_free_space_dev: free_space=%d, free_space_errno=%d (!icmd)\n", dev->free_space, dev->free_space_errno);
179 edit_device_codes_dev(dev, ocmd.c_str(), icmd);
181 Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
183 results = get_pool_memory(PM_MESSAGE);
186 /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
190 if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
191 Dmsg1(100, "Free space program run : %s\n", results);
192 free = str_to_int64(results);
194 dev->free_space = free;
195 dev->free_space_errno = 1;
197 Mmsg0(dev->errmsg, "");
202 dev->free_space_errno = -EPIPE;
203 Mmsg1(dev->errmsg, "Cannot run free space command (%s)\n", results);
206 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
207 "free_space_errno=%d ERR=%s\n", dev->dev_name,
208 edit_uint64(dev->free_space, ed1), dev->free_space_errno,
214 dev->dev_errno = -dev->free_space_errno;
215 Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
216 "free_space_errno=%d ERR=%s\n",
217 dev->dev_name, edit_uint64(dev->free_space, ed1),
218 dev->free_space_errno, dev->errmsg);
222 free_pool_memory(results);
223 Dmsg3(29, "update_free_space_dev: free_space=%s, free_space_errno=%d have_media=%d\n",
224 edit_uint64(dev->free_space, ed1), dev->free_space_errno, dev->have_media());
228 static bool dvd_write_part(DEVICE *dev)
230 Dmsg1(29, "dvd_write_part: device is %s\n", dev->dev_name);
232 if (unmount_dev(dev, 1) < 0) {
233 Dmsg0(29, "dvd_write_part: unable to unmount the device\n");
236 POOL_MEM ocmd(PM_FNAME);
242 results = get_pool_memory(PM_MESSAGE);
244 icmd = dev->device->write_part_command;
246 edit_device_codes_dev(dev, ocmd.c_str(), icmd);
248 /* Wait at most the time a maximum size part is written in DVD 0.5x speed
249 * FIXME: Minimum speed should be in device configuration
251 timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
253 Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
255 status = run_program_full_output(ocmd.c_str(), timeout, results);
257 Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s",
259 Dmsg1(000, "%s", dev->errmsg);
260 dev->dev_errno = EIO;
261 free_pool_memory(results);
265 POOL_MEM archive_name(PM_FNAME);
266 /* Delete spool file */
267 make_spooled_dvd_filename(dev, archive_name);
268 unlink(archive_name.c_str());
269 free_pool_memory(results);
273 /* Open the next part file.
275 * - Increment part number
276 * - Reopen the device
278 int open_next_part(DCR *dcr)
280 DEVICE *dev = dcr->dev;
282 Dmsg5(29, "Enter: open_next_part part=%d npart=%d dev=%s vol=%s mode=%d\n",
283 dev->part, dev->num_parts, dev->print_name(),
284 dev->VolCatInfo.VolCatName, dev->openmode);
285 /* When appending, do not open a new part if the current is empty */
286 if (dev->can_append() && (dev->part == dev->num_parts) &&
287 (dev->part_size == 0)) {
288 Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
300 * If we have a part open for write, then write it to
301 * DVD before opening the next part.
303 if (dev->is_dvd() && (dev->part == dev->num_parts) && dev->can_append()) {
304 if (!dvd_write_part(dev)) {
309 dev->part_start += dev->part_size;
312 Dmsg2(29, "part=%d num_parts=%d\n", dev->part, dev->num_parts);
313 if ((dev->num_parts < dev->part) && dev->can_append()) {
314 POOL_MEM archive_name(PM_FNAME);
318 * First check what is on DVD. If out part is there, we
319 * are in trouble, so bail out.
321 make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
322 if (stat(archive_name.c_str(), &buf) == 0) {
323 /* bad news bail out */
324 Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
325 archive_name.c_str());
329 dev->num_parts = dev->part;
330 make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
332 /* Check if the next part exists in spool directory . */
333 if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
334 Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
335 /* Then try to unlink it */
336 if (unlink(archive_name.c_str()) < 0) {
338 dev->dev_errno = errno;
339 Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
340 archive_name.c_str(), be.strerror());
346 Dmsg2(50, "Call dev->open(vol=%s, mode=%d", dev->VolCatInfo.VolCatName,
349 if (dev->open(dcr, dev->openmode) < 0) {
352 dev->set_labeled(); /* all next parts are "labeled" */
356 /* Open the first part file.
358 * - Reopen the device
360 int open_first_part(DCR *dcr, int mode)
362 DEVICE *dev = dcr->dev;
363 Dmsg3(29, "Enter: open_first_part dev=%s Vol=%s mode=%d\n", dev->dev_name,
364 dev->VolCatInfo.VolCatName, dev->openmode);
374 Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
376 if (dev->open(dcr, mode) < 0) {
377 Dmsg0(50, "open dev() failed\n");
380 Dmsg1(50, "Leave open_first_part state=%s\n", dev->is_open()?"open":"not open");
385 /* Protected version of lseek, which opens the right part if necessary */
386 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
391 if (dev->num_parts == 0) { /* If there is only one part, simply call lseek. */
392 return lseek(dev->fd, offset, whence);
395 dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */
398 Dmsg1(100, "lseek_dev SEEK_SET to %d\n", (int)offset);
399 if ((uint64_t)offset >= dev->part_start) {
400 if ((uint64_t)(offset - dev->part_start) < dev->part_size) {
401 /* We are staying in the current part, just seek */
402 if ((pos = lseek(dev->fd, (off_t)(offset-dev->part_start), SEEK_SET)) < 0) {
405 return pos + dev->part_start;
408 /* Load next part, and start again */
409 if (open_next_part(dcr) < 0) {
410 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
413 return lseek_dev(dev, offset, SEEK_SET);
416 /* pos < dev->part_start :
417 * We need to access a previous part,
418 * so just load the first one, and seek again
419 * until the right one is loaded */
420 if (open_first_part(dcr, dev->openmode) < 0) {
421 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
424 return lseek_dev(dev, offset, SEEK_SET);
428 Dmsg1(100, "lseek_dev SEEK_CUR to %d\n", (int)offset);
429 if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
432 pos += dev->part_start;
435 } else { /* Not used in Bacula, but should work */
436 return lseek_dev(dev, pos, SEEK_SET);
440 Dmsg1(100, "lseek_dev SEEK_END to %d\n", (int)offset);
441 if (offset > 0) { /* Not used by bacula */
442 Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", (int)offset);
447 if (dev->part == dev->num_parts) { /* The right part is already loaded */
448 if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
451 return pos + dev->part_start;
454 /* Load the first part, then load the next until we reach the last one.
455 * This is the only way to be sure we compute the right file address. */
456 /* Save previous openmode, and open all but last part read-only (useful for DVDs) */
457 openmode = dev->openmode;
459 /* Works because num_parts > 0. */
460 if (open_first_part(dcr, OPEN_READ_ONLY) < 0) {
461 Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
464 while (dev->part < (dev->num_parts-1)) {
465 if (open_next_part(dcr) < 0) {
466 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
470 dev->openmode = openmode;
471 if (open_next_part(dcr) < 0) {
472 Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
475 return lseek_dev(dev, 0, SEEK_END);
484 bool dvd_close_job(DCR *dcr)
486 DEVICE *dev = dcr->dev;
490 /* If the device is a dvd and WritePartAfterJob
491 * is set to yes, open the next part, so, in case of a device
492 * that requires mount, it will be written to the device.
494 if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
495 Dmsg0(100, "Writing last part because write_part_after_job is set.\n");
496 if (dev->part < dev->num_parts) {
497 Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
498 dev->part, dev->num_parts, dev->print_name());
499 dev->dev_errno = EIO;
503 if (ok && (open_next_part(dcr) < 0)) {
504 Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
505 dev->print_name(), strerror_dev(dev));
506 dev->dev_errno = EIO;
509 dev->VolCatInfo.VolCatParts = dev->num_parts;
516 * Edit codes into (Un)MountCommand, Write(First)PartCommand
518 * %a = archive device name
520 * %v = last part name
522 * omsg = edited output message
523 * imsg = input string containing edit codes (%x)
526 static char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg)
532 POOL_MEM archive_name(PM_FNAME);
535 Dmsg1(800, "edit_device_codes: %s\n", imsg);
536 for (p=imsg; *p; p++) {
543 bsnprintf(add, sizeof(add), "%d", dev->part);
550 str = dev->device->mount_point;
553 make_spooled_dvd_filename(dev, archive_name);
554 str = archive_name.c_str();
568 Dmsg1(1900, "add_str %s\n", str);
569 pm_strcat(&omsg, (char *)str);
570 Dmsg1(1800, "omsg=%s\n", omsg);