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