]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/dvd.c
bfa47a4a0bf3a1fd42d8a0358aaaab52dcfed646
[bacula/bacula] / bacula / src / stored / dvd.c
1 /*
2  *
3  *   dvd.c  -- Routines specific to DVD devices (and
4  *             possibly other removable hard media). 
5  *
6  *    Nicolas Boichat, MMV
7  *
8  *   Version $Id$
9  */
10 /*
11    Copyright (C) 2005-2006 Kern Sibbald
12
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.
17
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.
22
23  */
24
25 #include "bacula.h"
26 #include "stored.h"
27
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);
31
32 /* 
33  * Write the current volume/part filename to archive_name.
34  */
35 void make_mounted_dvd_filename(DEVICE *dev, POOL_MEM &archive_name) 
36 {
37    pm_strcpy(archive_name, dev->device->mount_point);
38    add_file_and_part_name(dev, archive_name);
39    dev->set_part_spooled(false);
40 }
41
42 void make_spooled_dvd_filename(DEVICE *dev, POOL_MEM &archive_name)
43 {
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);
47    } else {
48       pm_strcpy(archive_name, working_directory);
49    }
50    add_file_and_part_name(dev, archive_name);
51    dev->set_part_spooled(true);
52 }      
53
54 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
55 {
56    char partnumber[20];
57    if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
58       pm_strcat(archive_name, "/");
59    }
60
61    pm_strcat(archive_name, dev->VolCatInfo.VolCatName);
62    /* if part > 1, append .# to the filename (where # is the part number) */
63    if (dev->part > 1) {
64       pm_strcat(archive_name, ".");
65       bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part);
66       pm_strcat(archive_name, partnumber);
67    }
68    Dmsg1(400, "Exit add_file_part_name: arch=%s\n", archive_name.c_str());
69 }  
70
71 /* Mount the device.
72  * If timeout, wait until the mount command returns 0.
73  * If !timeout, try to mount the device only once.
74  */
75 bool mount_dvd(DEVICE* dev, int timeout) 
76 {
77    Dmsg0(90, "Enter mount_dvd\n");
78    if (dev->is_mounted()) {
79       return true;
80    } else if (dev->requires_mount()) {
81       return do_mount_dvd(dev, 1, timeout);
82    }       
83    return true;
84 }
85
86 /* Unmount the device
87  * If timeout, wait until the unmount command returns 0.
88  * If !timeout, try to unmount the device only once.
89  */
90 bool unmount_dvd(DEVICE *dev, int timeout) 
91 {
92    if (!dev->is_dvd()) {
93       return true;
94    }
95    Dmsg0(90, "Enter unmount_dvd\n");
96    if (dev->is_mounted()) {
97       return do_mount_dvd(dev, 0, timeout);
98    }
99    return true;
100 }
101
102 /* (Un)mount the device */
103 static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) 
104 {
105    POOL_MEM ocmd(PM_FNAME);
106    POOLMEM *results;
107    char *icmd;
108    int status, timeout;
109    
110    sm_check(__FILE__, __LINE__, false);
111    if (mount) {
112       if (dev->is_mounted()) {
113          Dmsg0(200, "======= DVD mount=1\n");
114          return true;
115       }
116       icmd = dev->device->mount_command;
117    } else {
118       if (!dev->is_mounted()) {
119          Dmsg0(200, "======= DVD mount=0\n");
120          return true;
121       }
122       icmd = dev->device->unmount_command;
123    }
124    
125    dev->edit_mount_codes(ocmd, icmd);
126    
127    Dmsg2(200, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
128
129    if (dotimeout) {
130       /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
131       timeout = 1;
132    } else {
133       timeout = 0;
134    }
135    results = get_memory(2000);
136    results[0] = 0;
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(20, "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) {
144          break;
145       }
146       if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
147          break;
148       }
149       if (timeout-- > 0) {
150          /* Sometimes the device cannot be mounted because it is already mounted.
151           * Try to unmount it, then remount it */
152          if (mount) {
153             Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
154             do_mount_dvd(dev, 0, 0);
155          }
156          bmicrosleep(1, 0);
157          continue;
158       }
159       if (status != 0) {
160          berrno be;
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));
165       } else {
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);
170       }
171       /*
172        * Now, just to be sure it is not mounted, try to read the
173        *  filesystem.
174        */
175       DIR* dp;
176       struct dirent *entry, *result;
177       int name_max;
178       int count;
179       
180       name_max = pathconf(".", _PC_NAME_MAX);
181       if (name_max < 1024) {
182          name_max = 1024;
183       }
184          
185       if (!(dp = opendir(dev->device->mount_point))) {
186          berrno be;
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());
190          goto get_out;
191       }
192       
193       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
194       count = 0;
195       while (1) {
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());
200             break;
201          }
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);
206             break;
207          } else {
208             Dmsg2(129, "do_mount_dvd: ignoring %s in %s\n", 
209                   result->d_name, dev->device->mount_point);
210          }
211       }
212       free(entry);
213       closedir(dp);
214       
215       Dmsg1(29, "do_mount_dvd: got %d files in the mount point (not counting ., .. and .keep)\n", count);
216       
217       if (count > 0) {
218          /* If we got more than ., .. and .keep */
219          /*   there must be something mounted */
220          if (mount) {
221             Dmsg1(100, "Did Mount by count=%d\n", count);
222             break;
223          } else {
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");
228             return false;
229          }
230       }
231 get_out:
232       dev->set_mounted(false);
233       sm_check(__FILE__, __LINE__, false);
234       free_pool_memory(results);
235       Dmsg0(200, "== DVD mount=0\n");
236       return false;
237    }
238    Dmsg0(100, "Out of mount/umount loop\n");
239    
240    dev->set_mounted(mount);              /* set/clear mounted flag */
241    free_pool_memory(results);
242    /* Do not check free space when unmounting */
243    if (mount) {
244       Dmsg0(100, "Calling update_free_space\n");
245       if (!update_free_space_dev(dev)) {
246          return false;
247       }
248    }
249    Dmsg1(200, "== DVD mount=%d\n", mount);
250    return true;
251 }
252
253 /* Update the free space on the device */
254 bool update_free_space_dev(DEVICE* dev) 
255 {
256    POOL_MEM ocmd(PM_FNAME);
257    POOLMEM* results;
258    char* icmd;
259    int timeout;
260    uint64_t free;
261    char ed1[50];
262    bool ok = false;
263    int status;
264
265    if (!dev->is_dvd() || dev->is_freespace_ok()) {
266       return true;
267    }
268    
269    /* The device must be mounted in order to dvd-freespace to work */
270    mount_dvd(dev, 1);
271    
272    sm_check(__FILE__, __LINE__, false);
273    icmd = dev->device->free_space_command;
274    
275    if (!icmd) {
276       dev->free_space = 0;
277       dev->free_space_errno = 0;
278       dev->clear_freespace_ok();              /* No valid freespace */
279       dev->clear_media();
280       Dmsg2(29, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n", 
281             edit_uint64(dev->free_space, ed1), dev->free_space_errno);
282       Mmsg(dev->errmsg, _("No FreeSpace command defined.\n"));
283       return false;
284    }
285    
286    dev->edit_mount_codes(ocmd, icmd);
287    
288    Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
289
290    results = get_pool_memory(PM_MESSAGE);
291    
292    /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
293    timeout = 3;
294    
295    while (1) {
296       berrno be;
297       Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str());
298       status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results);
299       Dmsg2(20, "Freespace status=%d result=%s\n", status, results);
300       if (status == 0) {
301          free = str_to_int64(results);
302          Dmsg1(400, "Free space program run: Freespace=%s\n", results);
303          if (free >= 0) {
304             dev->free_space = free;
305             dev->free_space_errno = 0;
306             dev->set_freespace_ok();     /* have valid freespace */
307             dev->set_media();
308             Mmsg(dev->errmsg, "");
309             ok = true;
310             break;
311          }
312       }
313       dev->free_space = 0;
314       dev->free_space_errno = EPIPE;
315       dev->clear_freespace_ok();         /* no valid freespace */
316       Mmsg2(dev->errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"), 
317             results, be.strerror(status));
318       
319       if (--timeout > 0) {
320          Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
321             "free_space_errno=%d ERR=%s\n", dev->print_name(), 
322                edit_uint64(dev->free_space, ed1), dev->free_space_errno, 
323                dev->errmsg);
324          bmicrosleep(1, 0);
325          continue;
326       }
327
328       dev->dev_errno = dev->free_space_errno;
329       Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
330          "free_space_errno=%d ERR=%s\n",
331             dev->print_name(), edit_uint64(dev->free_space, ed1),
332             dev->free_space_errno, dev->errmsg);
333       break;
334    }
335    
336    free_pool_memory(results);
337    Dmsg4(29, "leave update_free_space_dev: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n", 
338       edit_uint64(dev->free_space, ed1), !!dev->is_freespace_ok(), dev->free_space_errno, !!dev->have_media());
339    sm_check(__FILE__, __LINE__, false);
340    return ok;
341 }
342
343 /*
344  * Note!!!! Part numbers now begin at 1. The part number is
345  *  suppressed from the first part, which is just the Volume
346  *  name. Each subsequent part is the Volumename.partnumber.
347  *
348  * Write a part (Vol, Vol.2, ...) from the spool to the DVD   
349  * This routine does not update the part number, so normally, you
350  *  should call open_next_part()
351  *
352  * It is also called from truncate_dvd to "blank" the medium, as
353  *  well as from block.c when the DVD is full to write the last part.
354  */
355 bool dvd_write_part(DCR *dcr)
356 {
357    DEVICE *dev = dcr->dev;
358    POOL_MEM archive_name(PM_FNAME);
359    
360    dev->clear_freespace_ok();             /* need to update freespace */
361
362    /* Don't write empty part files.
363     * This is only useful when growisofs does not support write beyond
364     * the 4GB boundary.
365     * Example :
366     *   - 3.9 GB on the volume, dvd-freespace reports 0.4 GB free
367     *   - Write 0.2 GB on the volume, Bacula thinks it could still
368     *     append data, it creates a new empty part.
369     *   - dvd-freespace reports 0 GB free, as the 4GB boundary has
370     *     been crossed
371     *   - Bacula thinks he must finish to write to the device, so it
372     *     tries to write the last part (0-byte), but dvd-writepart fails...
373     *
374     *  ***FIXME****  we cannot write a blank part!!!!!!!
375     * There is one exception: when recycling a volume, we write a blank part
376     * file, so, then, we need to accept to write it.
377     */
378    if (dev->part_size == 0) {
379       Dmsg2(29, "dvd_write_part: device is %s, won't write blank part %d\n", dev->print_name(), dev->part);
380       /* Delete spool file */
381       make_spooled_dvd_filename(dev, archive_name);
382       unlink(archive_name.c_str());
383       Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
384       sm_check(__FILE__, __LINE__, false);
385       return true;
386    }
387    
388    POOL_MEM ocmd(PM_FNAME);
389    POOL_MEM results(PM_MESSAGE);
390    char* icmd;
391    int status;
392    int timeout;
393    char ed1[50];
394    
395    sm_check(__FILE__, __LINE__, false);
396    Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
397    icmd = dev->device->write_part_command;
398    
399    dev->edit_mount_codes(ocmd, icmd);
400       
401    /*
402     * original line follows
403     * timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
404     * I modified this for a longer timeout; pre-formatting, blanking and
405     * writing can take quite a while
406     */
407
408    /* Explanation of the timeout value, when writing the first part,
409     *  by Arno Lehmann :
410     * 9 GB, write speed 1x: 6990 seconds (almost 2 hours...)
411     * Overhead: 900 seconds (starting, initializing, finalizing,probably 
412     *   reloading 15 minutes)
413     * Sum: 15780.
414     * A reasonable last-exit timeout would be 16000 seconds. Quite long - 
415     * almost 4.5 hours, but hopefully, that timeout will only ever be needed 
416     * in case of a serious emergency.
417     */
418
419    if (dev->part == 1) {
420       timeout = 16000;
421    } else {
422       timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4));
423    }
424
425    Dmsg2(20, "Write part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
426    status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
427    Dmsg2(20, "Write part status=%d result=%s\n", status, results.c_str());
428
429    dev->truncated_dvd = false;
430    if (status != 0) {
431       Jmsg2(dcr->jcr, M_FATAL, 0, _("Error writing part %d to the DVD: ERR=%s\n"),
432          dev->part, results.c_str());
433       Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"), 
434             results.c_str());
435       Dmsg1(000, "%s\n", dev->errmsg);
436       dev->dev_errno = EIO;
437       mark_volume_in_error(dcr);
438       sm_check(__FILE__, __LINE__, false);
439       return false;
440    }
441    Jmsg(dcr->jcr, M_INFO, 0, _("Part %d written to DVD.\n"), dev->part);
442    Dmsg2(400, "dvd_write_part: Part %d written to DVD\nResults: %s\n",
443             dev->part, results.c_str());
444     
445    dev->num_dvd_parts++;            /* there is now one more part on DVD */
446    dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
447    Dmsg1(000, "Update num_parts=%d\n", dev->num_dvd_parts);
448
449    /* Delete spool file */
450    make_spooled_dvd_filename(dev, archive_name);
451    unlink(archive_name.c_str());
452    Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
453    sm_check(__FILE__, __LINE__, false);
454    
455    /* growisofs umounted the device, so remount it (it will update the free space) */
456    dev->clear_mounted();
457    mount_dvd(dev, 1);
458    Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"), 
459       edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
460    sm_check(__FILE__, __LINE__, false);
461    return true;
462 }
463
464 /*
465  * Open the next part file.
466  *  - Close the fd
467  *  - Increment part number 
468  *  - Reopen the device
469  */
470 int dvd_open_next_part(DCR *dcr)
471 {
472    DEVICE *dev = dcr->dev;
473    VOLUME_LABEL VolHdr;
474
475    Dmsg6(29, "Enter: == open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n", 
476       dev->part, dev->num_dvd_parts, dev->print_name(),
477          dev->VolCatInfo.VolCatName, dev->openmode, dev->file_addr);
478    if (!dev->is_dvd()) {
479       Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name()); 
480       return -1;
481    }
482    
483    /* When appending, do not open a new part if the current is empty */
484    if (dev->can_append() && (dev->part > dev->num_dvd_parts) && 
485        (dev->part_size == 0)) {
486       Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
487       return dev->fd;
488    }
489
490    /*              
491     * Note, when we close, the Volume header is zeroed. Since
492     *  we reopen, but are in fact opening the same volume without
493     *  re-reading the Volume header, we simply save and restore it.
494     */
495    memcpy(&VolHdr, &dev->VolHdr, sizeof(VolHdr));
496    dev->close();                      /* close current part */
497    memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
498    
499    /*
500     * If we have a spooled part open, write it to the
501     *  DVD before opening the next part.
502     */
503    if (dev->is_part_spooled()) {
504       Dmsg2(100, "Before open next write previous. part=%d num_parts=%d\n",
505          dev->part, dev->num_dvd_parts);
506       if (!dvd_write_part(dcr)) {
507          Dmsg0(29, "Error in dvd_write part.\n");
508          return -1;
509       }
510    }
511      
512    dev->part_start += dev->part_size;
513    dev->part++;
514    Dmsg2(29, "Inc part=%d num_dvd_parts=%d\n", dev->part, dev->num_dvd_parts);
515
516    /* Are we working on a part past what is written in the DVD? */
517    if (dev->num_dvd_parts < dev->part) {
518       POOL_MEM archive_name(PM_FNAME);
519       struct stat buf;
520       /* 
521        * First check what is on DVD.  If our part is there, we
522        *   are in trouble, so bail out.
523        * NB: This is however not a problem if we are writing the first part.
524        * It simply means that we are over writing an existing volume...
525        */
526       if (dev->num_dvd_parts > 0) {
527          make_mounted_dvd_filename(dev, archive_name);   /* makes dvd name */
528          Dmsg1(100, "Check if part on DVD: %s\n", archive_name.c_str());
529          if (stat(archive_name.c_str(), &buf) == 0) {
530             /* bad news bail out */
531             Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
532                archive_name.c_str());
533             return -1;
534          }
535       }
536
537 #ifdef neeeded
538       Dmsg2(400, "num_dvd_parts=%d part=%d\n", dev->num_dvd_parts, dev->part);
539       make_spooled_dvd_filename(dev, archive_name);   /* makes spool name */
540       
541       /* Check if the next part exists in spool directory . */
542       Dmsg1(100, "Check if part on spool: %s\n", archive_name.c_str());
543       if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
544          Dmsg1(29, "======= Part %s is in the way, deleting it...\n", archive_name.c_str());
545          /* Then try to unlink it */
546          if (unlink(archive_name.c_str()) < 0) {
547             berrno be;
548             dev->dev_errno = errno;
549             Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), 
550                    archive_name.c_str(), be.strerror());
551             return -1;
552          }
553       }
554 #endif
555    }
556
557    Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName, 
558          dev->openmode);
559
560    /* Open next part.  Note, this sets part_size for part opened. */
561    if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
562       return -1;
563    } 
564    /* Restore Volume header record */
565    memcpy(&dev->VolHdr, &VolHdr, sizeof(dev->VolHdr));
566    dev->set_labeled();                   /* all next parts are "labeled" */
567    
568    return dev->fd;
569 }
570
571 /*
572  * Open the first part file.
573  *  - Close the fd
574  *  - Reopen the device
575  */
576 int dvd_open_first_part(DCR *dcr, int mode)
577 {
578    DEVICE *dev = dcr->dev;
579    VOLUME_LABEL VolHdr;
580
581    Dmsg5(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d num_dvd_parts=%d append=%d\n", dev->print_name(), 
582          dev->VolCatInfo.VolCatName, dev->openmode, dev->num_dvd_parts, dev->can_append());
583
584
585    /*              
586     * Note, when we close, the Volume header is zeroed. Since
587     *  we reopen, but are in fact opening the same volume without
588     *  re-reading the Volume header, we simply save and restore it.
589     */
590    memcpy(&VolHdr, &dev->VolHdr, sizeof(VolHdr));
591    dev->close();
592    memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
593
594    Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName, 
595          mode);
596    Dmsg0(100, "Set part=1\n");
597    dev->part = 1;
598    dev->part_start = 0;
599
600
601    /* Restore Volume header record */
602    memcpy(&dev->VolHdr, &VolHdr, sizeof(dev->VolHdr));
603    if (dev->open(dcr, mode) < 0) {
604       Dmsg0(400, "open dev() failed\n");
605       return -1;
606    }
607    Dmsg2(400, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
608    
609    return dev->fd;
610 }
611
612
613 /* Protected version of lseek, which opens the right part if necessary */
614 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
615 {
616    DCR *dcr;
617    off_t pos;
618    char ed1[50], ed2[50];
619    
620    Dmsg5(400, "Enter lseek_dev fd=%d off=%s w=%d part=%d nparts=%d\n", dev->fd,
621       edit_int64(offset, ed1), whence, dev->part, dev->num_dvd_parts);
622    if (!dev->is_dvd()) { 
623       Dmsg0(400, "Using sys lseek\n");
624       return lseek(dev->fd, offset, whence);
625    }
626
627    dcr = (DCR *)dev->attached_dcrs->first();  /* any dcr will do */
628    switch(whence) {
629    case SEEK_SET:
630       Dmsg2(400, "lseek_dev SEEK_SET to %s (part_start=%s)\n",
631          edit_int64(offset, ed1), edit_uint64(dev->part_start, ed2));
632       if ((uint64_t)offset >= dev->part_start) {
633          if ((uint64_t)offset == dev->part_start || 
634              (uint64_t)offset < dev->part_start+dev->part_size) {
635             /* We are staying in the current part, just seek */
636             if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
637                return pos;
638             } else {
639                return pos + dev->part_start;
640             }
641          } else {
642             /* Load next part, and start again */
643             Dmsg0(100, "lseek open next part\n");
644             if (dvd_open_next_part(dcr) < 0) {
645                Dmsg0(400, "lseek_dev failed while trying to open the next part\n");
646                return -1;
647             }
648             Dmsg2(100, "Recurse lseek after open next part=%d num_part=%d\n",
649                dev->part, dev->num_dvd_parts);
650             return lseek_dev(dev, offset, SEEK_SET);
651          }
652       } else {
653          /*
654           * pos < dev->part_start :
655           * We need to access a previous part, 
656           * so just load the first one, and seek again
657           * until the right one is loaded
658           */
659          Dmsg0(100, "lseek open first part\n");
660          if (dvd_open_first_part(dcr, dev->openmode) < 0) {
661             Dmsg0(400, "lseek_dev failed while trying to open the first part\n");
662             return -1;
663          }
664          Dmsg2(100, "Recurse lseek after open first part=%d num_part=%d\n",
665                dev->part, dev->num_dvd_parts);
666          return lseek_dev(dev, offset, SEEK_SET);
667       }
668       break;
669    case SEEK_CUR:
670       Dmsg1(400, "lseek_dev SEEK_CUR to %s\n", edit_int64(offset, ed1));
671       if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
672          Dmsg0(400, "Seek error.\n");
673          return pos;                  
674       }
675       pos += dev->part_start;
676       if (offset == 0) {
677          Dmsg1(400, "lseek_dev SEEK_CUR returns %s\n", edit_uint64(pos, ed1));
678          return pos;
679       } else { 
680          Dmsg1(400, "do lseek_dev SEEK_SET %s\n", edit_uint64(pos, ed1));
681          return lseek_dev(dev, pos, SEEK_SET);
682       }
683       break;
684    case SEEK_END:
685       Dmsg1(400, "lseek_dev SEEK_END to %s\n", edit_int64(offset, ed1));
686       /*
687        * Bacula does not use offsets for SEEK_END
688        *  Also, Bacula uses seek_end only when it wants to
689        *  append to the volume, so for a dvd that means
690        *  that the volume must be spooled since the DVD
691        *  itself is read-only (as currently implemented).
692        */
693       if (offset > 0) { /* Not used by bacula */
694          Dmsg1(400, "lseek_dev SEEK_END called with an invalid offset %s\n", 
695             edit_uint64(offset, ed1));
696          errno = EINVAL;
697          return -1;
698       }
699       /* If we are already on a spooled part and have the
700        *  right part number, simply seek
701        */
702       if (dev->is_part_spooled() && dev->part > dev->num_dvd_parts) {
703          if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
704             return pos;   
705          } else {
706             Dmsg1(400, "lseek_dev SEEK_END returns %s\n", 
707                   edit_uint64(pos + dev->part_start, ed1));
708             return pos + dev->part_start;
709          }
710       } else {
711          /*
712           * Load the first part, then load the next until we reach the last one.
713           * This is the only way to be sure we compute the right file address.
714           *
715           * Save previous openmode, and open all but last part read-only 
716           * (useful for DVDs) 
717           */
718          int modesave = dev->openmode;
719          if (dvd_open_first_part(dcr, OPEN_READ_ONLY) < 0) {
720             Dmsg0(400, "lseek_dev failed while trying to open the first part\n");
721             return -1;
722          }
723          if (dev->num_dvd_parts > 0) {
724             while (dev->part < dev->num_dvd_parts) {
725                if (dvd_open_next_part(dcr) < 0) {
726                   Dmsg0(400, "lseek_dev failed while trying to open the next part\n");
727                   return -1;
728                }
729             }
730             dev->openmode = modesave;
731             if (dvd_open_next_part(dcr) < 0) {
732                Dmsg0(400, "lseek_dev failed while trying to open the next part\n");
733                return -1;
734             }
735          }
736          return lseek_dev(dev, 0, SEEK_END);
737       }
738       break;
739    default:
740       Dmsg0(400, "Seek call error.\n");
741       errno = EINVAL;
742       return -1;
743    }
744 }
745
746 bool dvd_close_job(DCR *dcr)
747 {
748    DEVICE *dev = dcr->dev;
749    JCR *jcr = dcr->jcr;
750    bool ok = true;
751
752    /*
753     * If the device is a dvd and WritePartAfterJob
754     * is set to yes, open the next part, so, in case of a device
755     * that requires mount, it will be written to the device.
756     */
757    if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
758       Dmsg1(400, "Writing last part=%d write_partafter_job is set.\n",
759          dev->part);
760       if (dev->part < dev->num_dvd_parts+1) {
761          Jmsg3(jcr, M_FATAL, 0, _("Error writing. Current part less than total number of parts (%d/%d, device=%s)\n"),
762                dev->part, dev->num_dvd_parts, dev->print_name());
763          dev->dev_errno = EIO;
764          ok = false;
765       }
766       
767       if (ok && !dvd_write_part(dcr)) {
768          Jmsg2(jcr, M_FATAL, 0, _("Unable to write last on %s: ERR=%s\n"),
769                dev->print_name(), dev->bstrerror());
770          dev->dev_errno = EIO;
771          ok = false;
772       }
773    }
774    return ok;
775 }
776
777 bool truncate_dvd(DCR *dcr) 
778 {
779    DEVICE* dev = dcr->dev;
780
781    dev->close();
782    memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
783
784    if (!unmount_dvd(dev, 1)) {
785       Dmsg0(400, "truncate_dvd: Failed to unmount DVD\n");
786       return false;
787    }
788
789    /* Set num_dvd_parts to zero (on disk) */
790    dev->num_dvd_parts = 0;
791    dcr->VolCatInfo.VolCatParts = 0;
792    dev->VolCatInfo.VolCatParts = 0;
793    
794    Dmsg0(400, "truncate_dvd: Opening first part (1)...\n");
795    
796    dev->truncating = true;
797    if (dvd_open_first_part(dcr, CREATE_READ_WRITE) < 0) {
798       Dmsg0(400, "truncate_dvd: Error while opening first part (1).\n");
799       dev->truncating = false;
800       return false;
801    }
802
803    Dmsg0(400, "truncate_dvd: Truncating...\n");
804
805    /* If necessary, truncate it spool file. */
806    if (ftruncate(dev->fd, 0) != 0) {
807       berrno be;
808       Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"), 
809          dev->print_name(), be.strerror());
810       dev->truncating = false;
811       return false;
812    }
813    
814    dev->close();
815    memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
816    
817    Dmsg0(400, "truncate_dvd: Opening first part (2)...\n");
818    
819    /* 
820     * Now actually truncate the DVD
821     *  This is really kludgy, why not an argument or a separate
822     *  subroutine?  KES
823     */
824    if (!dvd_write_part(dcr)) {
825       Dmsg0(400, "truncate_dvd: Error while writing to DVD.\n");
826       dev->truncating = false;
827       return false;
828    }
829    dev->truncating = false;
830    
831    /* Set num_dvd_parts to zero (on disk) */
832    dev->num_dvd_parts = 0;
833    dcr->VolCatInfo.VolCatParts = 0;
834    dev->VolCatInfo.VolCatParts = 0;
835
836    /* Update catalog */
837    if (!dir_update_volume_info(dcr, false)) {
838       return false;
839    }
840    
841    if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
842       Dmsg0(400, "truncate_dvd: Error while opening first part (2).\n");
843       return false;
844    }
845
846    return true;
847 }
848
849 /* Checks if we can write on a non-blank DVD: meaning that it just have been
850  * truncated (there is only one zero-sized file on the DVD, with the right
851  * volume name).   
852  *  
853  * Note!  Normally if we can mount the device, which should be the case
854  *   when we get here, it is not a blank DVD.  Hence we check if
855  *   there is a zero length file with the right name, in which case
856  *   we allow it.
857  * This seems terribly kludgie to me.  KES
858  */
859 bool check_can_write_on_non_blank_dvd(DCR *dcr) 
860 {
861    DEVICE* dev = dcr->dev;
862    DIR* dp;
863    struct dirent *entry, *result;
864    int name_max;
865    int count = 0;
866    bool matched = true;
867    struct stat filestat;
868       
869    name_max = pathconf(".", _PC_NAME_MAX);
870    if (name_max < 1024) {
871       name_max = 1024;
872    }
873    
874    if (!(dp = opendir(dev->device->mount_point))) {
875       berrno be;
876       dev->dev_errno = errno;
877       Dmsg3(29, "check_can_write_on_non_blank_dvd: failed to open dir %s (dev=%s), ERR=%s\n", 
878             dev->device->mount_point, dev->print_name(), be.strerror());
879       return false;
880    }
881    
882    entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
883    while (1) {
884       if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
885          dev->dev_errno = EIO;
886          Dmsg2(129, "check_can_write_on_non_blank_dvd: no more files in dir %s (dev=%s)\n", 
887                dev->device->mount_point, dev->print_name());
888          break;
889       } else {
890          Dmsg2(99, "check_can_write_on_non_blank_dvd: found %s (versus %s)\n", 
891                result->d_name, dev->VolCatInfo.VolCatName);
892          if (strcmp(result->d_name, dev->VolCatInfo.VolCatName) == 0) {
893             /* Found the file, checking it is empty */
894             POOL_MEM filename(PM_FNAME);
895             pm_strcpy(filename, dev->device->mount_point);
896             if (filename.c_str()[strlen(filename.c_str())-1] != '/') {
897                pm_strcat(filename, "/");
898             }
899             pm_strcat(filename, dev->VolCatInfo.VolCatName);
900             if (stat(filename.c_str(), &filestat) < 0) {
901                berrno be;
902                dev->dev_errno = errno;
903                Dmsg2(29, "check_can_write_on_non_blank_dvd: cannot stat file (file=%s), ERR=%s\n", 
904                   filename.c_str(), be.strerror());
905                return false;
906             }
907             Dmsg2(99, "check_can_write_on_non_blank_dvd: size of %s is %d\n", 
908                filename.c_str(), filestat.st_size);
909             matched = filestat.st_size == 0;
910          }
911       }
912       count++;
913    }
914    free(entry);
915    closedir(dp);
916    
917    if (count > 3) {
918       /* There are more than 3 files (., .., and the volume file) */
919       Dmsg1(29, "Cannot write on blank DVD too many files %d greater than 3\n", count);
920       return false;
921    }
922    
923    Dmsg2(29, "OK  can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched);
924    return matched;
925 }