Priority:
For 1.39:
+- When reading through parts on the DVD, the DVD is mounted and
+ unmounted for each part.
- Restricted consoles start in the Default catalog even if it
is not permitted.
- Make sure that the restore options don't permit "seeing" other
- Fix ClientRunBefore/AfterJob compatibility.
- Ensure that connection to daemon failure always indicates what
daemon it was trying to connect to.
+- Freespace on DVD requested over and over even with no intervening
+ writes.
*/
if (is_cleaning_tape(ua, &mr, &pr)) {
if (media_record_exists) { /* we update it */
- mr.VolBytes = 1;
+ mr.VolBytes = 1; /* any bytes to indicate it exists */
bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
mr.MediaType[0] = 0;
mr.StorageId = store->StorageId;
char dev_name[MAX_NAME_LENGTH];
bool ok = false;
bool is_dvd = false;
+ uint64_t VolBytes = 0;
if (!(sd=open_sd_bsock(ua))) {
return false;
}
while (bnet_recv(sd) >= 0) {
+ int dvd;
bsendmsg(ua, "%s", sd->msg);
- if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
+ if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu DVD=%d ", &VolBytes,
+ &dvd) == 2) {
+ is_dvd = dvd;
ok = true;
}
- if (strncmp(sd->msg, "3000 OK label. DVD=1 ", 21) == 0) {
- is_dvd = true;
- }
}
unbash_spaces(mr->VolumeName);
unbash_spaces(mr->MediaType);
}
if (ok) {
if (media_record_exists) { /* we update it */
- mr->VolBytes = 1;
+ mr->VolBytes = VolBytes;
mr->InChanger = 1;
mr->StorageId = ua->jcr->wstore->StorageId;
if (!db_update_media_record(ua->jcr, ua->db, mr)) {
}
} else { /* create the media record */
set_pool_dbr_defaults_in_media_dbr(mr, pr);
- mr->VolBytes = 1; /* flag indicating Volume labeled */
+ mr->VolBytes = VolBytes;
mr->InChanger = 1;
mr->StorageId = ua->jcr->wstore->StorageId;
mr->Enabled = 1;
if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
return false;
}
+ if (mr.Enabled == 2) {
+ bsendmsg(ua, _("Cannot prune Volume \"%s\" because it is archived.\n"),
+ mr.VolumeName);
+ }
if (!confirm_retention(ua, &mr.VolRetention, "Volume")) {
return false;
}
*/
attr->stream = stream;
Dmsg1(400, "Attr: %s\n", rec);
- if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
+ if (sscanf(rec, "%ld %ld", &attr->file_index, &attr->type) != 2) {
Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
Dmsg1(100, "\nError scanning attributes. %s\n", rec);
return 0;
stop_child_timer(bpipe->timer_id);
}
free(bpipe);
- Dmsg2(200, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat);
+ Dmsg2(800, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat);
return stat;
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
*/
* and is 1 Jan 1970 at 0:0 UTC
*
* The major two times that should be left are:
- * btime_t (64 bit integer in microseconds base Epoch)
- * utime_t (64 bit integer in seconds base Epoch)
+ * btime_t (64 bit integer in microseconds base Epoch)
+ * utime_t (64 bit integer in seconds base Epoch)
*/
#include "bacula.h"
time_t ttime;
if (sscanf(str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
return 0;
}
if (tm.tm_mon > 0) {
*/
int tm_wom(int mday, int wday)
{
- int fs; /* first sunday */
+ int fs; /* first sunday */
fs = (mday%7) - wday;
if (fs <= 0) {
fs += 7;
}
-/* date_encode -- Encode civil date as a Julian day number. */
+/* date_encode -- Encode civil date as a Julian day number. */
/* Deprecated. Do not use. */
fdate_t date_encode(uint32_t year, uint8_t month, uint8_t day)
y = year;
if (m <= 2) {
- y--;
- m += 12;
+ y--;
+ m += 12;
}
/* Determine whether date is in Julian or Gregorian calendar based on
canonical date of calendar reform. */
if ((year < 1582) || ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) {
- b = 0;
+ b = 0;
} else {
- a = ((int) (y / 100));
- b = 2 - a + (a / 4);
+ a = ((int) (y / 100));
+ b = 2 - a + (a / 4);
}
return (((int32_t) (365.25 * (y + 4716))) + ((int) (30.6001 * (m + 1))) +
- day + b - 1524.5);
+ day + b - 1524.5);
}
/* time_encode -- Encode time from hours, minutes, and seconds
- into a fraction of a day. */
+ into a fraction of a day. */
/* Deprecated. Do not use. */
ftime_t time_encode(uint8_t hour, uint8_t minute, uint8_t second,
- float32_t second_fraction)
+ float32_t second_fraction)
{
ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0));
return (ftime_t) (((second + 60L * (minute + 60L * hour)) / 86400.0)) +
- second_fraction;
+ second_fraction;
}
/* date_time_encode -- Set day number and fraction from date
- and time. */
+ and time. */
/* Deprecated. Do not use. */
void date_time_encode(struct date_time *dt,
- uint32_t year, uint8_t month, uint8_t day,
- uint8_t hour, uint8_t minute, uint8_t second,
- float32_t second_fraction)
+ uint32_t year, uint8_t month, uint8_t day,
+ uint8_t hour, uint8_t minute, uint8_t second,
+ float32_t second_fraction)
{
dt->julian_day_number = date_encode(year, month, day);
dt->julian_day_fraction = time_encode(hour, minute, second, second_fraction);
/* Deprecated. Do not use. */
void date_decode(fdate_t date, uint32_t *year, uint8_t *month,
- uint8_t *day)
+ uint8_t *day)
{
fdate_t z, f, a, alpha, b, c, d, e;
f = date - z;
if (z < 2299161.0) {
- a = z;
+ a = z;
} else {
- alpha = floor((z - 1867216.25) / 36524.25);
- a = z + 1 + alpha - floor(alpha / 4);
+ alpha = floor((z - 1867216.25) / 36524.25);
+ a = z + 1 + alpha - floor(alpha / 4);
}
b = a + 1524;
/* Deprecated. Do not use. */
void time_decode(ftime_t time, uint8_t *hour, uint8_t *minute,
- uint8_t *second, float32_t *second_fraction)
+ uint8_t *second, float32_t *second_fraction)
{
uint32_t ij;
*minute = (uint8_t) ((ij / 60L) % 60L);
*second = (uint8_t) (ij % 60L);
if (second_fraction != NULL) {
- *second_fraction = (float32_t)(time - floor(time));
+ *second_fraction = (float32_t)(time - floor(time));
}
}
/* date_time_decode -- Decode a Julian day and day fraction
- into civil date and time. */
+ into civil date and time. */
/* Deprecated. Do not use. */
void date_time_decode(struct date_time *dt,
- uint32_t *year, uint8_t *month, uint8_t *day,
- uint8_t *hour, uint8_t *minute, uint8_t *second,
- float32_t *second_fraction)
+ uint32_t *year, uint8_t *month, uint8_t *day,
+ uint8_t *hour, uint8_t *minute, uint8_t *second,
+ float32_t *second_fraction)
{
date_decode(dt->julian_day_number, year, month, day);
time_decode(dt->julian_day_fraction, hour, minute, second, second_fraction);
}
/* tm_encode -- Encode a civil date and time from a tm structure
- * to a Julian day and day fraction.
+ * to a Julian day and day fraction.
*/
/* Deprecated. Do not use. */
void tm_encode(struct date_time *dt,
- struct tm *tm)
+ struct tm *tm)
{
uint32_t year;
uint8_t month, day, hour, minute, second;
/* tm_decode -- Decode a Julian day and day fraction
- into civil date and time in tm structure */
+ into civil date and time in tm structure */
/* Deprecated. Do not use. */
void tm_decode(struct date_time *dt,
- struct tm *tm)
+ struct tm *tm)
{
uint32_t year;
uint8_t month, day, hour, minute, second;
/* date_time_compare -- Compare two dates and times and return
- the relationship as follows:
+ the relationship as follows:
- -1 dt1 < dt2
- 0 dt1 = dt2
- 1 dt1 > dt2
+ -1 dt1 < dt2
+ 0 dt1 = dt2
+ 1 dt1 > dt2
*/
/* Deprecated. Do not use. */
int date_time_compare(struct date_time *dt1, struct date_time *dt2)
{
if (dt1->julian_day_number == dt2->julian_day_number) {
- if (dt1->julian_day_fraction == dt2->julian_day_fraction) {
- return 0;
- }
- return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
+ if (dt1->julian_day_fraction == dt2->julian_day_fraction) {
+ return 0;
+ }
+ return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
}
return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1;
}
}
vp = (void *)va_arg(ap, void *);
// Dmsg2(000, "val=%lld at 0x%lx\n", value, (long unsigned)vp);
- if (l < 2) {
+ if (l == 0) {
+ *((int *)vp) = (int)value;
+ } else if (l == 1) {
*((uint32_t *)vp) = (uint32_t)value;
// Dmsg0(000, "Store 32 bit int\n");
} else {
/* Responses received from the Director */
-static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u"
- " VolBlocks=%u VolBytes=%" lld " VolMounts=%u VolErrors=%u VolWrites=%u"
- " MaxVolBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s"
- " Slot=%d MaxVolJobs=%u MaxVolFiles=%u InChanger=%d"
- " VolReadTime=%" lld " VolWriteTime=%" lld " EndFile=%u EndBlock=%u"
- " VolParts=%u LabelType=%d";
+static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%lu"
+ " VolBlocks=%lu VolBytes=%lld VolMounts=%lu VolErrors=%lu VolWrites=%lu"
+ " MaxVolBytes=%lld VolCapacityBytes=%lld VolStatus=%20s"
+ " Slot=%ld MaxVolJobs=%lu MaxVolFiles=%lu InChanger=%ld"
+ " VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu"
+ " VolParts=%lu LabelType=%ld";
static char OK_create[] = "1000 OK CreateJobMedia\n";
BSOCK *dir = jcr->dir_bsock;
VOLUME_CAT_INFO vol;
int n;
- int InChanger;
+ int32_t InChanger;
dcr->VolumeName[0] = 0; /* No volume */
if (bnet_recv(dir) <= 0) {
/* Just labeled or relabeled the tape */
if (label) {
bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus));
- vol->VolCatBytes = 1; /* indicates tape labeled */
}
pm_strcpy(VolumeName, vol->VolCatName);
bash_spaces(VolumeName);
}
/* We successfully wrote the block, now do housekeeping */
-
- dev->VolCatInfo.VolCatBytes += block->binbuf;
+ Dmsg2(400, "VolCatBytes=%d newVolCatBytes=%d\n", (int)dev->VolCatInfo.VolCatBytes,
+ (int)(dev->VolCatInfo.VolCatBytes+wlen));
+ dev->VolCatInfo.VolCatBytes += wlen;
dev->VolCatInfo.VolCatBlocks++;
dev->EndBlock = dev->block_num;
dev->EndFile = dev->file;
return false;
}
}
+
+ if (!dev->is_freespace_ok()) {
+ update_free_space_dev(dev);
+ }
if (!dev->is_freespace_ok()) { /* Error while getting free space */
char ed1[50], ed2[50];
}
x32 = 123456789;
bsnprintf(buf, sizeof(buf), "%u", x32);
- i = bsscanf(buf, "%u", &y32);
+ i = bsscanf(buf, "%lu", &y32);
if (i != 1 || x32 != y32) {
Pmsg3(-1, _("32 bit printf/scanf problem. i=%d x32=%u y32=%u\n"), i, x32, y32);
exit(1);
int status;
part = num_dvd_parts;
- Dmsg3(100, "Remove empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n",
- part, num_dvd_parts, VolCatInfo.VolCatName);
make_spooled_dvd_filename(this, archive_name);
/* Check that the part file is empty */
status = stat(archive_name.c_str(), &statp);
if (status == 0 && statp.st_size == 0) {
+ Dmsg3(100, "Unlink empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n",
+ part, num_dvd_parts, VolCatInfo.VolCatName);
Dmsg1(100, "unlink(%s)\n", archive_name.c_str());
unlink(archive_name.c_str());
set_part_spooled(false); /* no spooled part left */
int label_status;
int mode;
const char *volname = (relabel == 0) ? newname : oldname;
+ char ed1[50];
steal_device_lock(dev, &hold, BST_WRITING_LABEL);
Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name());
Dmsg0(90, "try_autoload_device - looking for volume_info\n");
if (relabel && dev->is_dvd()) {
- dcr->VolCatInfo.VolCatParts=1;
+ dcr->VolCatInfo.VolCatParts=0;
}
if (!try_autoload_device(dcr->jcr, slot, volname)) {
}
bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
/* The following 3000 OK label. string is scanned in ua_label.c */
- bnet_fsend(dir, "3000 OK label. DVD=%d Volume=\"%s\" Device=\"%s\"\n",
- dev->is_dvd()?1:0, newname, dev->print_name());
+ bnet_fsend(dir, "3000 OK label. VolBytes=%s DVD=%d Volume=\"%s\" Device=%s\n",
+ edit_uint64(dev->VolCatInfo.VolCatBytes, ed1),
+ dev->is_dvd()?1:0, newname, dev->print_name());
break;
case VOL_NO_MEDIA:
bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
Dmsg1(20, "Run mount prog=%s\n", ocmd.c_str());
while ((status = run_program_full_output(ocmd.c_str(),
dev->max_open_wait/2, results)) != 0) {
- Dmsg2(99, "Mount status=%d result=%s\n", status, results);
+ Dmsg2(20, "Mount status=%d result=%s\n", status, results);
/* Doesn't work with internationalization (This is not a problem) */
if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
break;
char ed1[50];
bool ok = false;
int status;
+
+ if (!dev->is_dvd() || dev->is_freespace_ok()) {
+ return true;
+ }
/* The device must be mounted in order to dvd-freespace to work */
mount_dvd(dev, 1);
if (!icmd) {
dev->free_space = 0;
dev->free_space_errno = 0;
- dev->clear_freespace_ok(); /* No valid freespace */
+ dev->clear_freespace_ok(); /* No valid freespace */
dev->clear_media();
Dmsg2(29, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n",
edit_uint64(dev->free_space, ed1), dev->free_space_errno);
berrno be;
Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str());
status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results);
+ Dmsg2(20, "Freespace status=%d result=%s\n", status, results);
if (status == 0) {
free = str_to_int64(results);
Dmsg1(400, "Free space program run: Freespace=%s\n", results);
DEVICE *dev = dcr->dev;
POOL_MEM archive_name(PM_FNAME);
+ dev->clear_freespace_ok(); /* need to update freespace */
+
/* Don't write empty part files.
* This is only useful when growisofs does not support write beyond
* the 4GB boundary.
* in case of a serious emergency.
*/
- if (dev->part == 1)
+ if (dev->part == 1) {
timeout = 16000;
- else
+ } else {
timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4));
+ }
- Dmsg2(20, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
+ Dmsg2(20, "Write part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
+ Dmsg2(20, "Write part status=%d result=%s\n", status, results.c_str());
+ dev->truncated_dvd = false;
if (status != 0) {
Jmsg2(dcr->jcr, M_FATAL, 0, _("Error writing part %d to the DVD: ERR=%s\n"),
dev->part, results.c_str());
dev->dev_errno = EIO;
mark_volume_in_error(dcr);
sm_check(__FILE__, __LINE__, false);
- dev->truncated_dvd = false;
return false;
}
Jmsg(dcr->jcr, M_INFO, 0, _("Part %d written to DVD.\n"), dev->part);
Dmsg2(400, "dvd_write_part: Part %d written to DVD\nResults: %s\n",
dev->part, results.c_str());
- if (dev->truncated_dvd) {
- dev->truncated_dvd = false; /* turn off flag */
- } else { /* DVD part written */
- dev->num_dvd_parts++; /* there is now one more part on DVD */
- dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
- }
+ dev->num_dvd_parts++; /* there is now one more part on DVD */
+ dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
+ Dmsg1(000, "Update num_parts=%d\n", dev->num_dvd_parts);
/* Delete spool file */
make_spooled_dvd_filename(dev, archive_name);
dev->part++;
Dmsg2(29, "Inc part=%d num_dvd_parts=%d\n", dev->part, dev->num_dvd_parts);
+ /* Are we working on a part past what is written in the DVD? */
if (dev->num_dvd_parts < dev->part) {
POOL_MEM archive_name(PM_FNAME);
struct stat buf;
* First check what is on DVD. If our part is there, we
* are in trouble, so bail out.
* NB: This is however not a problem if we are writing the first part.
- * It simply means that we are overriding an existing volume...
+ * It simply means that we are over writing an existing volume...
*/
if (dev->num_dvd_parts > 0) {
make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */
}
}
+#ifdef neeeded
Dmsg2(400, "num_dvd_parts=%d part=%d\n", dev->num_dvd_parts, dev->part);
make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
/* Check if the next part exists in spool directory . */
- Dmsg1(100, "Check if part on spool: $s\n", archive_name.c_str());
+ Dmsg1(100, "Check if part on spool: %s\n", archive_name.c_str());
if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
- Dmsg1(29, "open_next_part %s is in the way, deleting it...\n", archive_name.c_str());
+ Dmsg1(29, "======= Part %s is in the way, deleting it...\n", archive_name.c_str());
/* Then try to unlink it */
if (unlink(archive_name.c_str()) < 0) {
berrno be;
return -1;
}
}
+#endif
}
Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
JCR *jcr = dcr->jcr;
bool ok = true;
- /* If the device is a dvd and WritePartAfterJob
+ /*
+ * If the device is a dvd and WritePartAfterJob
* is set to yes, open the next part, so, in case of a device
* that requires mount, it will be written to the device.
*/
struct dirent *entry, *result;
int name_max;
int count = 0;
- bool matched = false;
+ bool matched = true;
struct stat filestat;
name_max = pathconf(".", _PC_NAME_MAX);
Dmsg0(200, "Error from write volume label.\n");
return false;
}
+
+ dev->VolCatInfo.VolCatBytes = 0; /* reset byte count */
+
/*
* If we are not dealing with a streaming device,
* write the block now to ensure we have write permission.
/* Set or reset Volume statistics */
dev->VolCatInfo.VolCatJobs = 0;
dev->VolCatInfo.VolCatFiles = 0;
- dev->VolCatInfo.VolCatBytes = 1;
dev->VolCatInfo.VolCatErrors = 0;
dev->VolCatInfo.VolCatBlocks = 0;
dev->VolCatInfo.VolCatRBytes = 0;
bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
dev->VolHdr.VerNum = BaculaTapeVersion;
- if (dev->is_dvd()) {
+ if (dvdnow) {
/* We do not want to re-label a DVD so write VOL_LABEL now */
dev->VolHdr.LabelType = VOL_LABEL;
} else {
mark_volume_in_error(dcr);
goto mount_next_vol;
}
+ if (dev->is_dvd()) {
+ char ed1[50], ed2[50];
+ if (dev->VolCatInfo.VolCatBytes == dev->part_start + dev->part_size) {
+ Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
+ " part=%d size=%s\n"), dcr->VolumeName,
+ dev->part, edit_uint64(dev->VolCatInfo.VolCatBytes,ed1));
+ } else {
+ Jmsg(jcr, M_ERROR, 0, _("I cannot write on Volume \"%s\" because: "
+ "The sizes do not match! Volume=%s Catalog=%s\n"),
+ dcr->VolumeName,
+ edit_uint64(dev->part_start + dev->part_size, ed1),
+ edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
+ mark_volume_in_error(dcr);
+ goto mount_next_vol;
+ }
+ }
/* *****FIXME**** we should do some checking for files too */
if (dev->is_tape()) {
/*
dcr->VolumeName, dev_file(dev));
} else {
Jmsg(jcr, M_ERROR, 0, _("I cannot write on Volume \"%s\" because:\n"
-"The number of files mismatch! Volume=%u Catalog=%u\n"),
+ "The number of files mismatch! Volume=%u Catalog=%u\n"),
dcr->VolumeName, dev_file(dev), dev->VolCatInfo.VolCatFiles);
mark_volume_in_error(dcr);
goto mount_next_vol;
#undef VERSION
#define VERSION "1.39.21"
-#define BDATE "01 Septermber 2006"
-#define LSMDATE "01Sep06"
+#define BDATE "02 Septermber 2006"
+#define LSMDATE "02Sep06"
#define BYEAR "2006" /* year for copyright messages in progs */
/* Debug flags */
Technical notes on version 1.39
General:
+02Sep06
+kes When doing a label, pass the VolBytes back to the Director,
+ which puts it in the catalog.
+kes Print an error message if the user attempts to prune an
+ archived Volume.
+kes Need to start using %ld when sscanfing 32 bit values.
+kes Update the free
+kes Correct the counting of VolCatBytes for DVDs.
+kes Add code to mount.c to require that VolCatBytes corresponds to
+ what is actually found when doing an append.
+kes Update freespace only after writing on the DVD.
+kes Remove code that blows away the current part in the spool file.
01Sep06
kes Apply new dvd-handler patch from Richard Mortimer.
kes Tweak so that debug level 20 shows only DVD commands.