@(cd platforms; echo "==>Entering directory `pwd`"; ${MAKE} $@ || exit 1)
@$(RMF) *~ 1 2 3 core core.* config.guess console.log console.sum
@$(RMF) examples/1 examples/2 examples/devices/1 examples/devices/2
- @$(RMF) autom4te.cache
+ @$(RMF) -r autom4te.cache
# clean for distribution
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
dnl AC_PATH_PROG(RANLIB, ranlib, ranlib)
AC_PATH_PROG(OPENSSL, openssl, none)
AC_PATH_PROG(MTX, mtx, mtx)
+AC_PATH_PROG(MKISOFS, mkisofs, mkisofs)
+AC_PATH_PROG(PYTHON, python, python)
+AC_PATH_PROG(GROWISOFS, growisofs, growisofs)
+AC_PATH_PROG(DVDRWMEDIAINFO, dvd+rw-mediainfo, dvd+rw-mediainfo)
AC_PATH_PROG(PKGCONFIG, pkg-config, pkg-config)
AC_PATH_PROG(WXCONFIG, wx-config, wx-config)
AC_PATH_PROG(CDRECORD, cdrecord, cdrecord)
scripts/bacula.desktop.gnome2.xsu \
scripts/gnome-console.console_apps \
scripts/mtx-changer \
+ scripts/dvd-writepart \
+ scripts/dvd-freespace \
scripts/bacula-tray-monitor.desktop \
scripts/logwatch/Makefile \
scripts/logwatch/logfile.bacula.conf \
- Optimized bootstrap.
For 1.37:
-- Look at Preben's fstype error handling code.
- Look at Preben's acl.c error handling code.
- See multiple-store.txt for Multiple Storage implementation
design.
devel_bacula
gconsole
mtx-changer
+dvd-writepart
+dvd-freespace
Makefile
bacula
btraceback
$(MV) -f ${DESTDIR}${scriptdir}/mtx-changer ${DESTDIR}${scriptdir}/mtx-changer.old; \
fi
$(INSTALL_SCRIPT) mtx-changer $(DESTDIR)$(scriptdir)/mtx-changer
+ @if test -f ${DESTDIR}${scriptdir}/dvd-writepart; then \
+ echo " ==> Saving existing dvd-writepart to dvd-writepart.old"; \
+ $(MV) -f ${DESTDIR}${scriptdir}/dvd-writepart ${DESTDIR}${scriptdir}/dvd-writepart.old; \
+ fi
+ $(INSTALL_SCRIPT) dvd-writepart $(DESTDIR)$(scriptdir)/dvd-writepart
+ @if test -f ${DESTDIR}${scriptdir}/dvd-freespace; then \
+ echo " ==> Saving existing dvd-freespace to dvd-freespace.old"; \
+ $(MV) -f ${DESTDIR}${scriptdir}/dvd-freespace ${DESTDIR}${scriptdir}/dvd-freespace.old; \
+ fi
+ $(INSTALL_SCRIPT) dvd-freespace $(DESTDIR)$(scriptdir)/dvd-freespace
$(INSTALL_DATA) btraceback.gdb $(DESTDIR)$(scriptdir)/btraceback.gdb
$(INSTALL_DATA) btraceback.dbx $(DESTDIR)$(scriptdir)/btraceback.dbx
$(INSTALL_SCRIPT) btraceback $(DESTDIR)$(sbindir)/btraceback
(cd $(DESTDIR)$(scriptdir); $(RMF) bacula)
(cd $(DESTDIR)$(scriptdir); $(RMF) fd)
(cd $(DESTDIR)$(scriptdir); $(RMF) mtx-changer)
+ (cd $(DESTDIR)$(scriptdir); $(RMF) dvd-writepart)
+ (cd $(DESTDIR)$(scriptdir); $(RMF) dvd-freespace)
(cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.gdb)
(cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.dbx)
(cd $(DESTDIR)$(sbindir); $(RMF) btraceback)
cd $(topdir) \
&& CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
chmod 755 startmysql stopmysql bacula startit stopit btraceback
- chmod 755 mtx-changer bconsole gconsole
+ chmod 755 mtx-changer dvd-writepart dvd-freespace bconsole gconsole
Makefiles:
$(SHELL) config.status
chmod 755 startmysql stopmysql bacula startit stopit btraceback
- chmod 755 mtx-changer bconsole gconsole
+ chmod 755 mtx-changer dvd-writepart dvd-freespace bconsole gconsole
clean:
@$(RMF) *~ 1 2 3
distclean: clean
@$(RMF) startmysql stopmysql bacula fd startit stopit btraceback
@$(RMF) bconsole gconsole logrotate bacula.desktop
- @$(RMF) bacula.desktop.gnome1 bacula.desktop.gnome2 mtx-changer
+ @$(RMF) bacula.desktop.gnome1 bacula.desktop.gnome2 mtx-changer dvd-writepart dvd-freespace
@$(RMF) gnome-console.console_apps bacula.desktop.gnome2.xsu
@$(RMF) bacula.desktop.gnome2.consolehelper bacula.desktop.gnome1.xsu
@$(RMF) bacula.desktop.gnome1.consolehelper
/*
- Copyright (C) 2000-2005 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
uint32_t VolWrites; /* Number of writes */
uint32_t VolReads; /* Number of reads */
uint64_t VolBytes; /* Number of bytes written */
+ uint32_t VolParts; /* Number of parts written */
uint64_t MaxVolBytes; /* Max bytes to write to Volume */
uint64_t VolCapacityBytes; /* capacity estimate */
uint64_t VolReadTime; /* time spent reading volume */
VolBlocks INTEGER UNSIGNED NOT NULL DEFAULT 0,
VolMounts INTEGER UNSIGNED NOT NULL DEFAULT 0,
VolBytes BIGINT UNSIGNED NOT NULL DEFAULT 0,
+ VolParts INTEGER UNSIGNED NOT NULL DEFAULT 0,
VolErrors INTEGER UNSIGNED NOT NULL DEFAULT 0,
VolWrites INTEGER UNSIGNED NOT NULL DEFAULT 0,
VolCapacityBytes BIGINT UNSIGNED NOT NULL,
default 0,
volbytes bigint not null
default 0,
+ volparts integer not null
+ default 0,
volerrors integer not null
default 0,
volwrites integer not null
VolBlocks INTEGER UNSIGNED DEFAULT 0,
VolMounts INTEGER UNSIGNED DEFAULT 0,
VolBytes BIGINT UNSIGNED DEFAULT 0,
+ VolParts INTEGER UNSIGNED DEFAULT 0,
VolErrors INTEGER UNSIGNED DEFAULT 0,
VolWrites INTEGER UNSIGNED DEFAULT 0,
VolCapacityBytes BIGINT UNSIGNED DEFAULT 0,
Mmsg(mdb->cmd,
"INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes,"
"Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
-"VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,"
+"VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts,"
"EndFile,EndBlock) "
-"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,0,0)",
+"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0)",
mr->VolumeName,
mr->MediaType, mr->PoolId,
edit_uint64(mr->MaxVolBytes,ed1),
edit_uint64(mr->VolBytes, ed5),
mr->InChanger,
edit_uint64(mr->VolReadTime, ed6),
- edit_uint64(mr->VolWriteTime, ed7));
+ edit_uint64(mr->VolWriteTime, ed7),
+ mr->VolParts
+ );
Dmsg1(500, "Create Volume: %s\n", mdb->cmd);
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,"
- "FirstWritten,LastWritten,VolStatus,InChanger "
+ "FirstWritten,LastWritten,VolStatus,InChanger,VolParts "
"FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus IN ('Full',"
"'Recycle','Purged','Used','Append') "
"ORDER BY LastWritten LIMIT 1", mr->PoolId, mr->MediaType);
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,"
- "FirstWritten,LastWritten,VolStatus,InChanger "
+ "FirstWritten,LastWritten,VolStatus,InChanger,VolParts "
"FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' "
"%s "
"%s LIMIT %d",
mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
bstrncpy(mr->VolStatus, row[19], sizeof(mr->VolStatus));
mr->InChanger = str_to_int64(row[20]);
+ mr->VolParts = str_to_int64(row[21]);
sql_free_result(mdb);
db_unlock(mdb);
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
- "Recycle,Slot,FirstWritten,LastWritten,InChanger,EndFile,EndBlock "
+ "Recycle,Slot,FirstWritten,LastWritten,InChanger,EndFile,EndBlock,VolParts "
"FROM Media WHERE MediaId=%d", mr->MediaId);
} else { /* find by name */
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
- "Recycle,Slot,FirstWritten,LastWritten,InChanger,EndFile,EndBlock "
+ "Recycle,Slot,FirstWritten,LastWritten,InChanger,EndFile,EndBlock,VolParts "
"FROM Media WHERE VolumeName='%s'", mr->VolumeName);
}
mr->InChanger = str_to_uint64(row[22]);
mr->EndFile = str_to_uint64(row[23]);
mr->EndBlock = str_to_uint64(row[24]);
+ mr->VolParts = str_to_int64(row[25]);
stat = mr->MediaId;
}
} else {
"VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
"VolCapacityBytes,VolStatus,Recycle,VolRetention,"
"VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger,"
- "EndFile,EndBlock "
+ "EndFile,EndBlock,VolParts "
"FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName);
} else {
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
"VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
"VolCapacityBytes,VolStatus,Recycle,VolRetention,"
"VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger,"
- "EndFile,EndBlock "
+ "EndFile,EndBlock,VolParts "
"FROM Media WHERE Media.PoolId=%u ORDER BY MediaId", mdbr->PoolId);
}
} else {
time_t ttime;
struct tm tm;
int stat;
- char ed1[30], ed2[30], ed3[30], ed4[30];
+ char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30];
Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
"VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
"VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s',"
- "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s "
+ "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%s "
" WHERE VolumeName='%s'",
mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
mr->VolMounts, mr->VolErrors, mr->VolWrites,
mr->VolStatus, mr->Slot, mr->InChanger,
edit_uint64(mr->VolReadTime, ed3),
edit_uint64(mr->VolWriteTime, ed4),
+ edit_uint64(mr->VolParts, ed5),
mr->VolumeName);
} else {
Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
"VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
"VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
- "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s "
+ "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%s "
" WHERE VolumeName='%s'",
mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
mr->VolMounts, mr->VolErrors, mr->VolWrites,
mr->VolStatus, mr->Slot, mr->InChanger,
edit_uint64(mr->VolReadTime, ed3),
edit_uint64(mr->VolWriteTime, ed4),
+ edit_uint64(mr->VolParts, ed5),
mr->VolumeName);
}
if $bindir/mysql $* -f <<END-OF-DATA
USE bacula;
-ALTER TABLE Media ADD COLUMN EndFile INTEGER UNSIGNED NOT NULL DEFAULT 0;
-ALTER TABLE Media ADD COLUMN EndBlock INTEGER UNSIGNED NOT NULL DEFAULT 0;
-
-ALTER TABLE File ADD INDEX (JobId, PathId, FilenameId);
-
-UPDATE Filename SET Name='' WHERE Name=' ';
-
-CREATE TABLE CDImages (
- MediaId INTEGER UNSIGNED NOT NULL,
- LastBurn DATETIME NOT NULL,
- PRIMARY KEY (MediaId)
- );
-
-DELETE FROM Version;
-INSERT INTO Version (VersionId) VALUES (8);
+ALTER TABLE Media ADD COLUMN VolParts INTEGER UNSIGNED NOT NULL DEFAULT 0;
END-OF-DATA
then
if $bindir/psql $* -f - <<END-OF-DATA
\c bacula
-ALTER TABLE media ADD COLUMN EndFile integer;
-UPDATE media SET EndFile=0;
-ALTER TABLE media ALTER COLUMN EndFile SET NOT NULL;
-ALTER TABLE media ADD COLUMN EndBlock integer;
-UPDATE media SET EndBlock=0;
-ALTER TABLE media ALTER COLUMN EndBlock SET NOT NULL;
-
-UPDATE Filename SET Name='' WHERE Name=' ';
-
-alter table file rename column filenameid to filenameidold;
-alter table file add column filenameid integer;
-update file set filenameid = filenameidold;
-alter table file alter column filenameid set not null;
-alter table file drop column filenameidold;
-
-DELETE FROM Version;
-INSERT INTO Version (VersionId) VALUES (8);
-
-create index file_jobid_idx on file (jobid);
-create index file_pathid_idx on file(pathid);
-create index file_filenameid_idx on file(filenameid);
-create index file_jpfid_idx on file (jobid, pathid, filenameid);
-
-create table CDImages
-(
- MediaId integer not null,
- LastBurn timestamp without time zone not null,
- primary key (MediaId)
-);
+ALTER TABLE media ADD COLUMN volparts integer;
+UPDATE media SET volparts=0;
+ALTER TABLE media ALTER COLUMN volparts SET NOT NULL;
vacuum;
VolBlocks INTEGER UNSIGNED DEFAULT 0,
VolMounts INTEGER UNSIGNED DEFAULT 0,
VolBytes BIGINT UNSIGNED DEFAULT 0,
+ VolParts INTEGER UNSIGNED DEFAULT 0,
VolErrors INTEGER UNSIGNED DEFAULT 0,
VolWrites INTEGER UNSIGNED DEFAULT 0,
VolCapacityBytes BIGINT UNSIGNED DEFAULT 0,
MediaId, VolumeName, Slot, PoolId,
MediaType, FirstWritten, LastWritten,
LabelDate, VolJobs, VolFiles, VolBlocks,
- VolMounts, VolBytes, VolErrors, VolWrites,
+ VolMounts, VolBytes, 0, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
MaxVolFiles, MaxVolBytes, InChanger, MediaAddressing,
- VolReadTime, VolWriteTime, 0, 0
+ VolReadTime, VolWriteTime, EndFile, EndBlock
FROM Media;
VolBlocks INTEGER UNSIGNED DEFAULT 0,
VolMounts INTEGER UNSIGNED DEFAULT 0,
VolBytes BIGINT UNSIGNED DEFAULT 0,
+ VolParts INTEGER UNSIGNED DEFAULT 0,
VolErrors INTEGER UNSIGNED DEFAULT 0,
VolWrites INTEGER UNSIGNED DEFAULT 0,
VolCapacityBytes BIGINT UNSIGNED DEFAULT 0,
MediaId, VolumeName, Slot, PoolId,
MediaType, FirstWritten, LastWritten,
LabelDate, VolJobs, VolFiles, VolBlocks,
- VolMounts, VolBytes, VolErrors, VolWrites,
+ VolMounts, VolBytes, VolParts, VolErrors, VolWrites,
VolCapacityBytes, VolStatus, Recycle,
VolRetention, VolUseDuration, MaxVolJobs,
MaxVolFiles, MaxVolBytes,
DROP TABLE Media_backup;
-CREATE TABLE CDImages (
- MediaId INTEGER UNSIGNED NOT NULL,
- LastBurn DATETIME NOT NULL,
- PRIMARY KEY (MediaId)
- );
-
-CREATE INDEX inx9 ON File (JobId, PathId, FileNameId);
-
COMMIT;
-UPDATE Filename SET Name='' WHERE Name=' ';
-
-DELETE FROM Version;
-INSERT INTO Version (VersionId) VALUES (8);
-
END-OF-DATA
* Version $Id$
*/
/*
- Copyright (C) 2001-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s"
" VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%" lld " VolMounts=%u"
" VolErrors=%u VolWrites=%u MaxVolBytes=%" lld " EndTime=%d VolStatus=%10s"
-" Slot=%d relabel=%d InChanger=%d VolReadTime=%" lld " VolWriteTime=%" lld "\n";
+" Slot=%d relabel=%d InChanger=%d VolReadTime=%" lld " VolWriteTime=%" lld
+" VolParts=%u\n";
static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia "
" FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u "
" VolBlocks=%u VolBytes=%s VolMounts=%u VolErrors=%u VolWrites=%u"
" MaxVolBytes=%s VolCapacityBytes=%s VolStatus=%s Slot=%d"
" MaxVolJobs=%u MaxVolFiles=%u InChanger=%d VolReadTime=%s"
- " VolWriteTime=%s EndFile=%u EndBlock=%u\n";
+ " VolWriteTime=%s EndFile=%u EndBlock=%u VolParts=%u\n";
static char OK_create[] = "1000 OK CreateJobMedia\n";
mr->InChanger,
edit_uint64(mr->VolReadTime, ed4),
edit_uint64(mr->VolWriteTime, ed5),
- mr->EndFile, mr->EndBlock);
+ mr->EndFile, mr->EndBlock,
+ mr->VolParts);
unbash_spaces(mr->VolumeName);
Dmsg2(200, "Vol Info for %s: %s", jcr->Job, sd->msg);
return stat;
if (ok) {
send_volume_info_to_storage_daemon(jcr, bs, &mr);
} else {
- bnet_fsend(bs, "1901 No Media.\n");
+ bnet_fsend(bs, "1901 No Media.\n");
}
/*
* and Media Type matches and Pool allows any volume.
*/
if (mr.PoolId != jcr->PoolId) {
- reason = "not in Pool";
+ reason = "not in Pool";
} else if (strcmp(mr.MediaType, jcr->store->media_type) != 0) {
- reason = "not correct MediaType";
+ reason = "not correct MediaType";
} else {
/*
* ****FIXME***
* This test (accept_any_volume) is turned off
- * because it doesn't properly check if the volume
+ * because it doesn't properly check if the volume
* really is out of sequence!
*
* } else if (!jcr->pool->accept_any_volume) {
- * reason = "Volume not in sequence";
+ * reason = "Volume not in sequence";
*/
/*
send_volume_info_to_storage_daemon(jcr, bs, &mr);
} else {
/* Not suitable volume */
- bnet_fsend(bs, "1998 Volume \"%s\" status is %s, %s.\n", mr.VolumeName,
+ bnet_fsend(bs, "1998 Volume \"%s\" status is %s, %s.\n", mr.VolumeName,
mr.VolStatus, reason);
}
} else {
- bnet_fsend(bs, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
+ bnet_fsend(bs, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
}
&sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes, &sdmr.VolMounts, &sdmr.VolErrors,
&sdmr.VolWrites, &sdmr.MaxVolBytes, &sdmr.LastWritten, &sdmr.VolStatus,
&sdmr.Slot, &label, &sdmr.InChanger, &sdmr.VolReadTime,
- &sdmr.VolWriteTime) == 17) {
+ &sdmr.VolWriteTime, &sdmr.VolParts) == 18) {
db_lock(jcr->db);
Dmsg3(300, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName,
bstrncpy(mr.VolumeName, sdmr.VolumeName, sizeof(mr.VolumeName)); /* copy Volume name */
unbash_spaces(mr.VolumeName);
if (!db_get_media_record(jcr, jcr->db, &mr)) {
- Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"),
+ Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"),
mr.VolumeName, db_strerror(jcr->db));
- bnet_fsend(bs, "1991 Catalog Request failed: %s", db_strerror(jcr->db));
+ bnet_fsend(bs, "1991 Catalog Request failed: %s", db_strerror(jcr->db));
db_unlock(jcr->db);
return;
}
* Insanity check for VolFiles get set to a smaller value
*/
if (sdmr.VolFiles < mr.VolFiles) {
- Jmsg(jcr, M_ERROR, 0, _("ERROR!! Volume Files at %u being set to %u. This is probably wrong.\n"),
+ Jmsg(jcr, M_ERROR, 0, _("ERROR!! Volume Files at %u being set to %u. This is probably wrong.\n"),
mr.VolFiles, sdmr.VolFiles);
}
}
mr.InChanger = sdmr.InChanger;
mr.VolReadTime = sdmr.VolReadTime;
mr.VolWriteTime = sdmr.VolWriteTime;
+ mr.VolParts = sdmr.VolParts;
bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus));
Dmsg2(300, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName);
} else if (db_update_media_record(jcr, jcr->db, &mr)) {
send_volume_info_to_storage_daemon(jcr, bs, &mr);
} else {
- Jmsg(jcr, M_ERROR, 0, _("Catalog error updating Media record. %s"),
+ Jmsg(jcr, M_ERROR, 0, _("Catalog error updating Media record. %s"),
db_strerror(jcr->db));
- bnet_fsend(bs, "1992 Update Media error\n");
- Dmsg0(190, "send error\n");
+ bnet_fsend(bs, "1992 Update Media error\n");
+ Dmsg0(190, "send error\n");
}
db_unlock(jcr->db);
Dmsg6(300, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n",
jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex);
if (!db_create_jobmedia_record(jcr, jcr->db, &jm)) {
- Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"),
+ Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"),
db_strerror(jcr->db));
- bnet_fsend(bs, "1991 Update JobMedia error\n");
+ bnet_fsend(bs, "1991 Update JobMedia error\n");
} else {
- Dmsg0(300, "JobMedia record created\n");
+ Dmsg0(300, "JobMedia record created\n");
bnet_fsend(bs, OK_create);
}
Dmsg1(120, "dird<filed: attr=%s\n", attr);
if (!db_create_file_attributes_record(jcr, jcr->db, &ar)) {
- Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db));
+ Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db));
}
/* Save values for SIG update */
jcr->FileId = ar.FileId;
} else if (Stream == STREAM_MD5_SIGNATURE || Stream == STREAM_SHA1_SIGNATURE) {
fname = p;
if (jcr->FileIndex != FileIndex) {
- Jmsg(jcr, M_WARNING, 0, "Got MD5/SHA1 but not same File as attributes\n");
+ Jmsg(jcr, M_WARNING, 0, "Got MD5/SHA1 but not same File as attributes\n");
} else {
/* Update signature in catalog */
char SIGbuf[50]; /* 24 bytes should be enough */
type = SHA1_SIG;
}
bin_to_base64(SIGbuf, fname, len);
- Dmsg3(190, "SIGlen=%d SIG=%s type=%d\n", strlen(SIGbuf), SIGbuf, Stream);
+ Dmsg3(190, "SIGlen=%d SIG=%s type=%d\n", strlen(SIGbuf), SIGbuf, Stream);
if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIGbuf, type)) {
- Jmsg(jcr, M_ERROR, 0, _("Catalog error updating MD5/SHA1. %s"),
+ Jmsg(jcr, M_ERROR, 0, _("Catalog error updating MD5/SHA1. %s"),
db_strerror(jcr->db));
}
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
{"rescheduleinterval", store_time, ITEM(res_job.RescheduleInterval), 0, ITEM_DEFAULT, 60 * 30},
{"rescheduletimes", store_pint, ITEM(res_job.RescheduleTimes), 0, 0, 0},
{"priority", store_pint, ITEM(res_job.Priority), 0, ITEM_DEFAULT, 10},
+ {"writepartafterjob", store_yesno, ITEM(res_job.write_part_after_job), 1, ITEM_DEFAULT, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
edit_uint64(res->res_dir.FDConnectTimeout, ed1),
edit_uint64(res->res_dir.SDConnectTimeout, ed2));
if (res->res_dir.query_file) {
- sendit(sock, " query_file=%s\n", res->res_dir.query_file);
+ sendit(sock, " query_file=%s\n", res->res_dir.query_file);
}
if (res->res_dir.messages) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock);
}
break;
break;
case R_COUNTER:
if (res->res_counter.WrapCounter) {
- sendit(sock, "Counter: name=%s min=%d max=%d cur=%d wrapcntr=%s\n",
+ sendit(sock, "Counter: name=%s min=%d max=%d cur=%d wrapcntr=%s\n",
res->res_counter.hdr.name, res->res_counter.MinValue,
res->res_counter.MaxValue, res->res_counter.CurrentValue,
res->res_counter.WrapCounter->hdr.name);
} else {
- sendit(sock, "Counter: name=%s min=%d max=%d\n",
+ sendit(sock, "Counter: name=%s min=%d max=%d\n",
res->res_counter.hdr.name, res->res_counter.MinValue,
res->res_counter.MaxValue);
}
if (res->res_counter.Catalog) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock);
}
break;
edit_utime(res->res_client.FileRetention, ed2, sizeof(ed2)),
res->res_client.AutoPrune);
if (res->res_client.catalog) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock);
}
break;
case R_JOB:
case R_JOBDEFS:
sendit(sock, "%s: name=%s JobType=%d level=%s Priority=%d MaxJobs=%u\n",
- type == R_JOB ? "Job" : "JobDefs",
+ type == R_JOB ? "Job" : "JobDefs",
res->res_job.hdr.name, res->res_job.JobType,
level_to_str(res->res_job.JobLevel), res->res_job.Priority,
res->res_job.MaxConcurrentJobs);
- sendit(sock, " Resched=%d Times=%d Interval=%s Spool=%d\n",
+ sendit(sock, " Resched=%d Times=%d Interval=%s Spool=%d WritePartAfterJob=%d\n",
res->res_job.RescheduleOnError, res->res_job.RescheduleTimes,
edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1),
- res->res_job.spool_data);
+ res->res_job.spool_data, res->res_job.write_part_after_job);
if (res->res_job.client) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock);
}
if (res->res_job.fileset) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock);
}
if (res->res_job.schedule) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock);
}
if (res->res_job.RestoreWhere) {
- sendit(sock, " --> Where=%s\n", NPRT(res->res_job.RestoreWhere));
+ sendit(sock, " --> Where=%s\n", NPRT(res->res_job.RestoreWhere));
}
if (res->res_job.RestoreBootstrap) {
- sendit(sock, " --> Bootstrap=%s\n", NPRT(res->res_job.RestoreBootstrap));
+ sendit(sock, " --> Bootstrap=%s\n", NPRT(res->res_job.RestoreBootstrap));
}
if (res->res_job.RunBeforeJob) {
- sendit(sock, " --> RunBefore=%s\n", NPRT(res->res_job.RunBeforeJob));
+ sendit(sock, " --> RunBefore=%s\n", NPRT(res->res_job.RunBeforeJob));
}
if (res->res_job.RunAfterJob) {
- sendit(sock, " --> RunAfter=%s\n", NPRT(res->res_job.RunAfterJob));
+ sendit(sock, " --> RunAfter=%s\n", NPRT(res->res_job.RunAfterJob));
}
if (res->res_job.RunAfterFailedJob) {
- sendit(sock, " --> RunAfterFailed=%s\n", NPRT(res->res_job.RunAfterFailedJob));
+ sendit(sock, " --> RunAfterFailed=%s\n", NPRT(res->res_job.RunAfterFailedJob));
}
if (res->res_job.WriteBootstrap) {
- sendit(sock, " --> WriteBootstrap=%s\n", NPRT(res->res_job.WriteBootstrap));
+ sendit(sock, " --> WriteBootstrap=%s\n", NPRT(res->res_job.WriteBootstrap));
}
if (res->res_job.storage[0]) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
/* ***FIXME*** */
// dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock);
}
if (res->res_job.pool) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock);
}
if (res->res_job.full_pool) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_POOL, (RES *)res->res_job.full_pool, sendit, sock);
}
if (res->res_job.inc_pool) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_POOL, (RES *)res->res_job.inc_pool, sendit, sock);
}
if (res->res_job.dif_pool) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_POOL, (RES *)res->res_job.dif_pool, sendit, sock);
}
if (res->res_job.verify_job) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-type, (RES *)res->res_job.verify_job, sendit, sock);
}
break;
if (res->res_job.messages) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
}
break;
INCEXE *incexe = res->res_fs.include_items[i];
for (j=0; j<incexe->num_opts; j++) {
FOPTS *fo = incexe->opts_list[j];
- sendit(sock, " O %s\n", fo->opts);
+ sendit(sock, " O %s\n", fo->opts);
for (k=0; k<fo->regex.size(); k++) {
- sendit(sock, " R %s\n", fo->regex.get(k));
+ sendit(sock, " R %s\n", fo->regex.get(k));
}
for (k=0; k<fo->regexdir.size(); k++) {
- sendit(sock, " RD %s\n", fo->regexdir.get(k));
+ sendit(sock, " RD %s\n", fo->regexdir.get(k));
}
for (k=0; k<fo->regexfile.size(); k++) {
- sendit(sock, " RF %s\n", fo->regexfile.get(k));
+ sendit(sock, " RF %s\n", fo->regexfile.get(k));
}
for (k=0; k<fo->wild.size(); k++) {
- sendit(sock, " W %s\n", fo->wild.get(k));
+ sendit(sock, " W %s\n", fo->wild.get(k));
}
for (k=0; k<fo->wilddir.size(); k++) {
- sendit(sock, " WD %s\n", fo->wilddir.get(k));
+ sendit(sock, " WD %s\n", fo->wilddir.get(k));
}
for (k=0; k<fo->wildfile.size(); k++) {
- sendit(sock, " WF %s\n", fo->wildfile.get(k));
+ sendit(sock, " WF %s\n", fo->wildfile.get(k));
}
for (k=0; k<fo->base.size(); k++) {
- sendit(sock, " B %s\n", fo->base.get(k));
+ sendit(sock, " B %s\n", fo->base.get(k));
}
for (k=0; k<fo->fstype.size(); k++) {
- sendit(sock, " X %s\n", fo->fstype.get(k));
+ sendit(sock, " X %s\n", fo->fstype.get(k));
}
if (fo->reader) {
- sendit(sock, " D %s\n", fo->reader);
+ sendit(sock, " D %s\n", fo->reader);
}
if (fo->writer) {
- sendit(sock, " T %s\n", fo->writer);
+ sendit(sock, " T %s\n", fo->writer);
}
- sendit(sock, " N\n");
+ sendit(sock, " N\n");
}
for (j=0; j<incexe->name_list.size(); j++) {
- sendit(sock, " I %s\n", incexe->name_list.get(j));
+ sendit(sock, " I %s\n", incexe->name_list.get(j));
}
if (incexe->name_list.size()) {
- sendit(sock, " N\n");
+ sendit(sock, " N\n");
}
}
for (i=0; i<res->res_fs.num_excludes; i++) {
INCEXE *incexe = res->res_fs.exclude_items[i];
for (j=0; j<incexe->name_list.size(); j++) {
- sendit(sock, " E %s\n", incexe->name_list.get(j));
+ sendit(sock, " E %s\n", incexe->name_list.get(j));
}
if (incexe->name_list.size()) {
- sendit(sock, " N\n");
+ sendit(sock, " N\n");
}
}
break;
int i;
RUN *run = res->res_sch.run;
char buf[1000], num[30];
- sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
+ sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
if (!run) {
break;
}
next_run:
- sendit(sock, " --> Run Level=%s\n", level_to_str(run->level));
- bstrncpy(buf, " hour=", sizeof(buf));
+ sendit(sock, " --> Run Level=%s\n", level_to_str(run->level));
+ bstrncpy(buf, " hour=", sizeof(buf));
for (i=0; i<24; i++) {
if (bit_is_set(i, run->hour)) {
- bsnprintf(num, sizeof(num), "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
- bstrncat(buf, "\n", sizeof(buf));
+ bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
- bstrncpy(buf, " mday=", sizeof(buf));
+ bstrncpy(buf, " mday=", sizeof(buf));
for (i=0; i<31; i++) {
if (bit_is_set(i, run->mday)) {
- bsnprintf(num, sizeof(num), "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
- bstrncat(buf, "\n", sizeof(buf));
+ bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
- bstrncpy(buf, " month=", sizeof(buf));
+ bstrncpy(buf, " month=", sizeof(buf));
for (i=0; i<12; i++) {
if (bit_is_set(i, run->month)) {
- bsnprintf(num, sizeof(num), "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
- bstrncat(buf, "\n", sizeof(buf));
+ bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
- bstrncpy(buf, " wday=", sizeof(buf));
+ bstrncpy(buf, " wday=", sizeof(buf));
for (i=0; i<7; i++) {
if (bit_is_set(i, run->wday)) {
- bsnprintf(num, sizeof(num), "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
- bstrncat(buf, "\n", sizeof(buf));
+ bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
- bstrncpy(buf, " wom=", sizeof(buf));
+ bstrncpy(buf, " wom=", sizeof(buf));
for (i=0; i<5; i++) {
if (bit_is_set(i, run->wom)) {
- bsnprintf(num, sizeof(num), "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
- bstrncat(buf, "\n", sizeof(buf));
+ bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
- bstrncpy(buf, " woy=", sizeof(buf));
+ bstrncpy(buf, " woy=", sizeof(buf));
for (i=0; i<54; i++) {
if (bit_is_set(i, run->woy)) {
- bsnprintf(num, sizeof(num), "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
- bstrncat(buf, "\n", sizeof(buf));
+ bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
- sendit(sock, " mins=%d\n", run->minute);
+ sendit(sock, " mins=%d\n", run->minute);
if (run->pool) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
}
if (run->storage) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
}
if (run->msgs) {
- sendit(sock, " --> ");
+ sendit(sock, " --> ");
dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
}
/* If another Run record is chained in, go print it */
goto next_run;
}
} else {
- sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
+ sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
}
break;
case R_POOL:
case R_MSGS:
sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
if (res->res_msgs.mail_cmd)
- sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
+ sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
if (res->res_msgs.operator_cmd)
- sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
+ sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
break;
default:
sendit(sock, "Unknown resource type %d in dump_resource.\n", type);
for (i=0; items[i].name; i++) {
if (items[i].flags & ITEM_REQUIRED) {
if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
- Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
+ Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
items[i].name, resources[rindex]);
}
}
/* If this triggers, take a look at lib/parse_conf.h */
if (i >= MAX_RES_ITEMS) {
- Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
+ Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
}
}
}
/* Resources containing another resource */
case R_DIRECTOR:
if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource %s\n", res_all.res_dir.hdr.name);
+ Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource %s\n", res_all.res_dir.hdr.name);
}
res->res_dir.messages = res_all.res_dir.messages;
break;
case R_JOB:
case R_JOBDEFS:
if ((res = (URES *)GetResWithName(type, res_all.res_dir.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find Job resource %s\n",
+ Emsg1(M_ERROR_TERM, 0, "Cannot find Job resource %s\n",
res_all.res_dir.hdr.name);
}
res->res_job.messages = res_all.res_job.messages;
break;
case R_COUNTER:
if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find Counter resource %s\n", res_all.res_counter.hdr.name);
+ Emsg1(M_ERROR_TERM, 0, "Cannot find Counter resource %s\n", res_all.res_counter.hdr.name);
}
res->res_counter.Catalog = res_all.res_counter.Catalog;
res->res_counter.WrapCounter = res_all.res_counter.WrapCounter;
case R_CLIENT:
if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find Client resource %s\n", res_all.res_client.hdr.name);
+ Emsg1(M_ERROR_TERM, 0, "Cannot find Client resource %s\n", res_all.res_client.hdr.name);
}
res->res_client.catalog = res_all.res_client.catalog;
break;
case R_SCHEDULE:
/*
* Schedule is a bit different in that it contains a RUN record
- * chain which isn't a "named" resource. This chain was linked
+ * chain which isn't a "named" resource. This chain was linked
* in by run_conf.c during pass 2, so here we jam the pointer
* into the Schedule resource.
*/
if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find Schedule resource %s\n", res_all.res_client.hdr.name);
+ Emsg1(M_ERROR_TERM, 0, "Cannot find Schedule resource %s\n", res_all.res_client.hdr.name);
}
res->res_sch.run = res_all.res_sch.run;
break;
default:
- Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
+ Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
error = 1;
break;
}
memcpy(res, &res_all, size);
if (!res_head[rindex]) {
res_head[rindex] = (RES *)res; /* store first entry */
- Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
+ Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
res->res_dir.hdr.name, rindex);
} else {
RES *next;
for (next=res_head[rindex]; next->next; next=next->next) {
if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
Emsg2(M_ERROR_TERM, 0,
- _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
+ _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
resources[rindex].name, res->res_dir.hdr.name);
}
}
next->next = (RES *)res;
- Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
+ Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
res->res_dir.hdr.name, rindex, pass);
}
}
if (pass == 1) {
if (((alist **)item->value)[item->code] == NULL) {
((alist **)item->value)[item->code] = New(alist(10, owned_by_alist));
- Dmsg1(900, "Defined new ACL alist at %d\n", item->code);
+ Dmsg1(900, "Defined new ACL alist at %d\n", item->code);
}
((alist **)item->value)[item->code]->append(bstrdup(lc->str));
- Dmsg2(900, "Appended to %d %s\n", item->code, lc->str);
+ Dmsg2(900, "Appended to %d %s\n", item->code, lc->str);
}
token = lex_get_token(lc, T_ALL);
if (token == T_COMMA) {
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
R_CONSOLE,
R_JOBDEFS,
R_FIRST = R_DIRECTOR,
- R_LAST = R_JOBDEFS /* keep this updated */
+ R_LAST = R_JOBDEFS /* keep this updated */
};
/* Job Level keyword structure */
struct s_jl {
- const char *level_name; /* level keyword */
- int level; /* level */
- int job_type; /* JobType permitting this level */
+ const char *level_name; /* level keyword */
+ int level; /* level */
+ int job_type; /* JobType permitting this level */
};
/* Job Type keyword structure */
*
*/
struct DIRRES {
- RES hdr;
+ RES hdr;
dlist *DIRaddrs;
- char *password; /* Password for UA access */
- int enable_ssl; /* Use SSL for UA */
- char *query_file; /* SQL query file */
- char *working_directory; /* WorkingDirectory */
+ char *password; /* Password for UA access */
+ int enable_ssl; /* Use SSL for UA */
+ char *query_file; /* SQL query file */
+ char *working_directory; /* WorkingDirectory */
const char *scripts_directory; /* ScriptsDirectory */
- char *pid_directory; /* PidDirectory */
- char *subsys_directory; /* SubsysDirectory */
- int require_ssl; /* Require SSL for all connections */
- MSGS *messages; /* Daemon message handler */
- uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */
- utime_t FDConnectTimeout; /* timeout for connect in seconds */
- utime_t SDConnectTimeout; /* timeout in seconds */
+ char *pid_directory; /* PidDirectory */
+ char *subsys_directory; /* SubsysDirectory */
+ int require_ssl; /* Require SSL for all connections */
+ MSGS *messages; /* Daemon message handler */
+ uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */
+ utime_t FDConnectTimeout; /* timeout for connect in seconds */
+ utime_t SDConnectTimeout; /* timeout in seconds */
};
Command_ACL,
FileSet_ACL,
Catalog_ACL,
- Num_ACL /* keep last */
+ Num_ACL /* keep last */
};
/*
* Console Resource
*/
struct CONRES {
- RES hdr;
- char *password; /* UA server password */
- int enable_ssl; /* Use SSL */
- alist *ACL_lists[Num_ACL]; /* pointers to ACLs */
+ RES hdr;
+ char *password; /* UA server password */
+ int enable_ssl; /* Use SSL */
+ alist *ACL_lists[Num_ACL]; /* pointers to ACLs */
};
*
*/
struct CAT {
- RES hdr;
+ RES hdr;
- int db_port; /* Port -- not yet implemented */
- char *db_address; /* host name for remote access */
- char *db_socket; /* Socket for local access */
+ int db_port; /* Port -- not yet implemented */
+ char *db_address; /* host name for remote access */
+ char *db_socket; /* Socket for local access */
char *db_password;
char *db_user;
char *db_name;
- int mult_db_connections; /* set if multiple connections wanted */
+ int mult_db_connections; /* set if multiple connections wanted */
};
*
*/
struct CLIENT {
- RES hdr;
+ RES hdr;
- int FDport; /* Where File daemon listens */
- int AutoPrune; /* Do automatic pruning? */
- utime_t FileRetention; /* file retention period in seconds */
- utime_t JobRetention; /* job retention period in seconds */
+ int FDport; /* Where File daemon listens */
+ int AutoPrune; /* Do automatic pruning? */
+ utime_t FileRetention; /* file retention period in seconds */
+ utime_t JobRetention; /* job retention period in seconds */
char *address;
char *password;
- CAT *catalog; /* Catalog resource */
- uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
- uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
- int enable_ssl; /* Use SSL */
+ CAT *catalog; /* Catalog resource */
+ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
+ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
+ int enable_ssl; /* Use SSL */
};
/*
*
*/
struct STORE {
- RES hdr;
+ RES hdr;
- int SDport; /* port where Directors connect */
- int SDDport; /* data port for File daemon */
+ int SDport; /* port where Directors connect */
+ int SDDport; /* data port for File daemon */
char *address;
char *password;
char *media_type;
char *dev_name;
- int autochanger; /* set if autochanger */
- uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
- uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
- int enable_ssl; /* Use SSL */
+ int autochanger; /* set if autochanger */
+ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
+ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
+ int enable_ssl; /* Use SSL */
};
-#define MAX_STORE 2 /* Max storage directives in Job */
+#define MAX_STORE 2 /* Max storage directives in Job */
/*
* Job Resource
*/
struct JOB {
- RES hdr;
-
- int JobType; /* job type (backup, verify, restore */
- int JobLevel; /* default backup/verify level */
- int Priority; /* Job priority */
- int RestoreJobId; /* What -- JobId to restore */
- char *RestoreWhere; /* Where on disk to restore -- directory */
- char *RestoreBootstrap; /* Bootstrap file */
- char *RunBeforeJob; /* Run program before Job */
- char *RunAfterJob; /* Run program after Job */
- char *RunAfterFailedJob; /* Run program after Job that errs */
- char *ClientRunBeforeJob; /* Run client program before Job */
- char *ClientRunAfterJob; /* Run client program after Job */
- char *WriteBootstrap; /* Where to write bootstrap Job updates */
- int replace; /* How (overwrite, ..) */
- utime_t MaxRunTime; /* max run time in seconds */
- utime_t MaxWaitTime; /* max blocking time in seconds */
- utime_t MaxStartDelay; /* max start delay in seconds */
- int PrefixLinks; /* prefix soft links with Where path */
- int PruneJobs; /* Force pruning of Jobs */
- int PruneFiles; /* Force pruning of Files */
- int PruneVolumes; /* Force pruning of Volumes */
- int SpoolAttributes; /* Set to spool attributes in SD */
- int spool_data; /* Set to spool data in SD */
- int rerun_failed_levels; /* Upgrade to rerun failed levels */
- uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
- int RescheduleOnError; /* Set to reschedule on error */
- int RescheduleTimes; /* Number of times to reschedule job */
- utime_t RescheduleInterval; /* Reschedule interval */
- utime_t JobRetention; /* job retention period in seconds */
-
- MSGS *messages; /* How and where to send messages */
- SCHED *schedule; /* When -- Automatic schedule */
- CLIENT *client; /* Who to backup */
- FILESET *fileset; /* What to backup -- Fileset */
+ RES hdr;
+
+ int JobType; /* job type (backup, verify, restore */
+ int JobLevel; /* default backup/verify level */
+ int Priority; /* Job priority */
+ int RestoreJobId; /* What -- JobId to restore */
+ char *RestoreWhere; /* Where on disk to restore -- directory */
+ char *RestoreBootstrap; /* Bootstrap file */
+ char *RunBeforeJob; /* Run program before Job */
+ char *RunAfterJob; /* Run program after Job */
+ char *RunAfterFailedJob; /* Run program after Job that errs */
+ char *ClientRunBeforeJob; /* Run client program before Job */
+ char *ClientRunAfterJob; /* Run client program after Job */
+ char *WriteBootstrap; /* Where to write bootstrap Job updates */
+ int replace; /* How (overwrite, ..) */
+ utime_t MaxRunTime; /* max run time in seconds */
+ utime_t MaxWaitTime; /* max blocking time in seconds */
+ utime_t MaxStartDelay; /* max start delay in seconds */
+ int PrefixLinks; /* prefix soft links with Where path */
+ int PruneJobs; /* Force pruning of Jobs */
+ int PruneFiles; /* Force pruning of Files */
+ int PruneVolumes; /* Force pruning of Volumes */
+ int SpoolAttributes; /* Set to spool attributes in SD */
+ int spool_data; /* Set to spool data in SD */
+ int rerun_failed_levels; /* Upgrade to rerun failed levels */
+ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
+ int RescheduleOnError; /* Set to reschedule on error */
+ int RescheduleTimes; /* Number of times to reschedule job */
+ utime_t RescheduleInterval; /* Reschedule interval */
+ utime_t JobRetention; /* job retention period in seconds */
+ bool write_part_after_job; /* Set to write part after job in SD */
+
+ MSGS *messages; /* How and where to send messages */
+ SCHED *schedule; /* When -- Automatic schedule */
+ CLIENT *client; /* Who to backup */
+ FILESET *fileset; /* What to backup -- Fileset */
alist *storage[MAX_STORE]; /* Where is device -- Storage daemon */
- POOL *pool; /* Where is media -- Media Pool */
- POOL *full_pool; /* Pool for Full backups */
- POOL *inc_pool; /* Pool for Incremental backups */
- POOL *dif_pool; /* Pool for Differental backups */
- JOB *verify_job; /* Job name to verify */
- JOB *jobdefs; /* Job defaults */
- uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
+ POOL *pool; /* Where is media -- Media Pool */
+ POOL *full_pool; /* Pool for Full backups */
+ POOL *inc_pool; /* Pool for Incremental backups */
+ POOL *dif_pool; /* Pool for Differental backups */
+ JOB *verify_job; /* Job name to verify */
+ JOB *jobdefs; /* Job defaults */
+ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
};
-#undef MAX_FOPTS
+#undef MAX_FOPTS
#define MAX_FOPTS 34
/* File options structure */
struct FOPTS {
- char opts[MAX_FOPTS]; /* options string */
- alist regex; /* regex string(s) */
- alist regexdir; /* regex string(s) for directories */
- alist regexfile; /* regex string(s) for files */
- alist wild; /* wild card strings */
- alist wilddir; /* wild card strings for directories */
- alist wildfile; /* wild card strings for files */
- alist base; /* list of base names */
- alist fstype; /* file system type limitation */
- char *reader; /* reader program */
- char *writer; /* writer program */
+ char opts[MAX_FOPTS]; /* options string */
+ alist regex; /* regex string(s) */
+ alist regexdir; /* regex string(s) for directories */
+ alist regexfile; /* regex string(s) for files */
+ alist wild; /* wild card strings */
+ alist wilddir; /* wild card strings for directories */
+ alist wildfile; /* wild card strings for files */
+ alist base; /* list of base names */
+ alist fstype; /* file system type limitation */
+ char *reader; /* reader program */
+ char *writer; /* writer program */
};
/* This is either an include item or an exclude item */
struct INCEXE {
- FOPTS *current_opts; /* points to current options structure */
- FOPTS **opts_list; /* options list */
- int num_opts; /* number of options items */
- alist name_list; /* filename list -- holds char * */
+ FOPTS *current_opts; /* points to current options structure */
+ FOPTS **opts_list; /* options list */
+ int num_opts; /* number of options items */
+ alist name_list; /* filename list -- holds char * */
};
/*
*
*/
struct FILESET {
- RES hdr;
+ RES hdr;
- bool new_include; /* Set if new include used */
- INCEXE **include_items; /* array of incexe structures */
- int num_includes; /* number in array */
+ bool new_include; /* Set if new include used */
+ INCEXE **include_items; /* array of incexe structures */
+ int num_includes; /* number in array */
INCEXE **exclude_items;
int num_excludes;
- bool have_MD5; /* set if MD5 initialized */
- struct MD5Context md5c; /* MD5 of include/exclude */
- char MD5[30]; /* base 64 representation of MD5 */
+ bool have_MD5; /* set if MD5 initialized */
+ struct MD5Context md5c; /* MD5 of include/exclude */
+ char MD5[30]; /* base 64 representation of MD5 */
int ignore_fs_changes; /* Don't force Full if FS changed */
};
*
*/
struct SCHED {
- RES hdr;
+ RES hdr;
RUN *run;
};
* Counter Resource
*/
struct COUNTER {
- RES hdr;
-
- int32_t MinValue; /* Minimum value */
- int32_t MaxValue; /* Maximum value */
- int32_t CurrentValue; /* Current value */
- COUNTER *WrapCounter; /* Wrap counter name */
- CAT *Catalog; /* Where to store */
- bool created; /* Created in DB */
+ RES hdr;
+
+ int32_t MinValue; /* Minimum value */
+ int32_t MaxValue; /* Maximum value */
+ int32_t CurrentValue; /* Current value */
+ COUNTER *WrapCounter; /* Wrap counter name */
+ CAT *Catalog; /* Where to store */
+ bool created; /* Created in DB */
};
/*
*
*/
struct POOL {
- RES hdr;
-
- char *pool_type; /* Pool type */
- char *label_format; /* Label format string */
- char *cleaning_prefix; /* Cleaning label prefix */
- int use_catalog; /* maintain catalog for media */
- int catalog_files; /* maintain file entries in catalog */
- int use_volume_once; /* write on volume only once */
- int accept_any_volume; /* accept any volume */
- int purge_oldest_volume; /* purge oldest volume */
- int recycle_oldest_volume; /* attempt to recycle oldest volume */
- int recycle_current_volume; /* attempt recycle of current volume */
- uint32_t max_volumes; /* max number of volumes */
- utime_t VolRetention; /* volume retention period in seconds */
- utime_t VolUseDuration; /* duration volume can be used */
- uint32_t MaxVolJobs; /* Maximum jobs on the Volume */
- uint32_t MaxVolFiles; /* Maximum files on the Volume */
- uint64_t MaxVolBytes; /* Maximum bytes on the Volume */
- int AutoPrune; /* default for pool auto prune */
- int Recycle; /* default for media recycle yes/no */
+ RES hdr;
+
+ char *pool_type; /* Pool type */
+ char *label_format; /* Label format string */
+ char *cleaning_prefix; /* Cleaning label prefix */
+ int use_catalog; /* maintain catalog for media */
+ int catalog_files; /* maintain file entries in catalog */
+ int use_volume_once; /* write on volume only once */
+ int accept_any_volume; /* accept any volume */
+ int purge_oldest_volume; /* purge oldest volume */
+ int recycle_oldest_volume; /* attempt to recycle oldest volume */
+ int recycle_current_volume; /* attempt recycle of current volume */
+ uint32_t max_volumes; /* max number of volumes */
+ utime_t VolRetention; /* volume retention period in seconds */
+ utime_t VolUseDuration; /* duration volume can be used */
+ uint32_t MaxVolJobs; /* Maximum jobs on the Volume */
+ uint32_t MaxVolFiles; /* Maximum files on the Volume */
+ uint64_t MaxVolBytes; /* Maximum bytes on the Volume */
+ int AutoPrune; /* default for pool auto prune */
+ int Recycle; /* default for media recycle yes/no */
};
CONRES res_con;
CLIENT res_client;
STORE res_store;
- CAT res_cat;
- JOB res_job;
+ CAT res_cat;
+ JOB res_job;
FILESET res_fs;
SCHED res_sch;
POOL res_pool;
MSGS res_msgs;
COUNTER res_counter;
- RES hdr;
+ RES hdr;
};
/* Run structure contained in Schedule Resource */
struct RUN {
- RUN *next; /* points to next run record */
- int level; /* level override */
- int Priority; /* priority override */
+ RUN *next; /* points to next run record */
+ int level; /* level override */
+ int Priority; /* priority override */
int job_type;
- bool spool_data; /* Data spooling override */
- bool spool_data_set; /* Data spooling override given */
- POOL *pool; /* Pool override */
- POOL *full_pool; /* Pool override */
- POOL *inc_pool; /* Pool override */
- POOL *dif_pool; /* Pool override */
- STORE *storage; /* Storage override */
- MSGS *msgs; /* Messages override */
+ bool spool_data; /* Data spooling override */
+ bool spool_data_set; /* Data spooling override given */
+ bool write_part_after_job; /* Write part after job override */
+ bool write_part_after_job_set; /* Write part after job override given */
+
+ POOL *pool; /* Pool override */
+ POOL *full_pool; /* Pool override */
+ POOL *inc_pool; /* Pool override */
+ POOL *dif_pool; /* Pool override */
+ STORE *storage; /* Storage override */
+ MSGS *msgs; /* Messages override */
char *since;
int level_no;
- int minute; /* minute to run job */
- time_t last_run; /* last time run */
- time_t next_run; /* next time to run */
+ int minute; /* minute to run job */
+ time_t last_run; /* last time run */
+ time_t next_run; /* next time to run */
char hour[nbytes_for_bits(24)]; /* bit set for each hour */
char mday[nbytes_for_bits(31)]; /* bit set for each day of month */
char month[nbytes_for_bits(12)]; /* bit set for each month */
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
if (!jcr->file_bsock) {
fd = bnet_connect(jcr, retry_interval, max_retry_time,
- _("File daemon"), jcr->client->address,
+ _("File daemon"), jcr->client->address,
NULL, jcr->client->FDport, verbose);
if (fd == NULL) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
if (bget_dirmsg(fd) > 0) {
Dmsg1(110, "<filed: %s", fd->msg);
if (strncmp(fd->msg, OKjob, strlen(OKjob)) != 0) {
- Jmsg(jcr, M_FATAL, 0, _("File daemon \"%s\" rejected Job command: %s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("File daemon \"%s\" rejected Job command: %s\n"),
jcr->client->hdr.name, fd->msg);
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
cr.JobRetention = jcr->client->JobRetention;
bstrncpy(cr.Uname, fd->msg+strlen(OKjob)+1, sizeof(cr.Uname));
if (!db_update_client_record(jcr, jcr->db, &cr)) {
- Jmsg(jcr, M_WARNING, 0, _("Error updating Client record. ERR=%s\n"),
+ Jmsg(jcr, M_WARNING, 0, _("Error updating Client record. ERR=%s\n"),
db_strerror(jcr->db));
}
}
jcr->jr.JobId = 0; /* flag for db_find_job_start time */
if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) {
/* No job found, so upgrade this one to Full */
- Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
- Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n"));
- bsnprintf(since, since_len, " (upgraded from %s)",
+ Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
+ Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n"));
+ bsnprintf(since, since_len, " (upgraded from %s)",
level_to_str(jcr->JobLevel));
jcr->JobLevel = jcr->jr.JobLevel = L_FULL;
} else {
if (jcr->job->rerun_failed_levels) {
if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, jcr->stime, JobLevel)) {
- Jmsg(jcr, M_INFO, 0, _("Prior failed job found. Upgrading to %s.\n"),
+ Jmsg(jcr, M_INFO, 0, _("Prior failed job found. Upgrading to %s.\n"),
level_to_str(JobLevel));
- bsnprintf(since, since_len, " (upgraded from %s)",
+ bsnprintf(since, since_len, " (upgraded from %s)",
level_to_str(jcr->JobLevel));
jcr->JobLevel = jcr->jr.JobLevel = JobLevel;
jcr->jr.JobId = jcr->JobId;
break;
}
}
- bstrncpy(since, ", since=", since_len);
+ bstrncpy(since, ", since=", since_len);
bstrncat(since, jcr->stime, since_len);
}
jcr->jr.JobId = jcr->JobId;
stime = str_to_utime(jcr->stime);
bnet_fsend(fd, levelcmd, "since_utime ", edit_uint64(stime, ed1), 0);
while (bget_dirmsg(fd) >= 0) { /* allow him to poll us to sync clocks */
- Jmsg(jcr, M_INFO, 0, "%s\n", fd->msg);
+ Jmsg(jcr, M_INFO, 0, "%s\n", fd->msg);
}
break;
case L_SINCE:
for (int j=0; j<ie->name_list.size(); j++) {
p = (char *)ie->name_list.get(j);
switch (*p) {
- case '|':
+ case '|':
p++; /* skip over the | */
- fd->msg = edit_job_codes(jcr, fd->msg, p, "");
- bpipe = open_bpipe(fd->msg, 0, "r");
+ fd->msg = edit_job_codes(jcr, fd->msg, p, "");
+ bpipe = open_bpipe(fd->msg, 0, "r");
if (!bpipe) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
p, be.strerror());
goto bail_out;
}
/* Copy File options */
if (ie->num_opts) {
bstrncpy(buf, ie->opts_list[0]->opts, sizeof(buf));
- bstrncat(buf, " ", sizeof(buf));
+ bstrncat(buf, " ", sizeof(buf));
} else {
- bstrncpy(buf, "0 ", sizeof(buf));
+ bstrncpy(buf, "0 ", sizeof(buf));
}
- Dmsg1(500, "Opts=%s\n", buf);
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) {
- fd->msglen = Mmsg(fd->msg, "%s", buf);
- Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
+ fd->msglen = Mmsg(fd->msg, "%s", buf);
+ Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
if (!bnet_send(fd)) {
- Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
+ Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
}
}
if ((stat=close_bpipe(bpipe)) != 0) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Error running program %p: ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Error running program %p: ERR=%s\n"),
p, be.strerror(stat));
goto bail_out;
}
break;
- case '<':
+ case '<':
p++; /* skip over < */
- if ((ffd = fopen(p, "r")) == NULL) {
- Jmsg(jcr, M_FATAL, 0, _("Cannot open %s file: %s. ERR=%s\n"),
- list==INC_LIST?"included":"excluded", p, strerror(errno));
+ if ((ffd = fopen(p, "r")) == NULL) {
+ Jmsg(jcr, M_FATAL, 0, _("Cannot open %s file: %s. ERR=%s\n"),
+ list==INC_LIST?"included":"excluded", p, strerror(errno));
goto bail_out;
}
/* Copy File options */
if (ie->num_opts) {
bstrncpy(buf, ie->opts_list[0]->opts, sizeof(buf));
- bstrncat(buf, " ", sizeof(buf));
+ bstrncat(buf, " ", sizeof(buf));
} else {
- bstrncpy(buf, "0 ", sizeof(buf));
+ bstrncpy(buf, "0 ", sizeof(buf));
}
- Dmsg1(500, "Opts=%s\n", buf);
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) {
- fd->msglen = Mmsg(fd->msg, "%s", buf);
+ fd->msglen = Mmsg(fd->msg, "%s", buf);
if (!bnet_send(fd)) {
- Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
+ Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
}
}
fclose(ffd);
break;
- case '\\':
- p++; /* skip over \ */
+ case '\\':
+ p++; /* skip over \ */
/* Note, fall through wanted */
default:
if (ie->num_opts) {
- Dmsg2(500, "numopts=%d opts=%s\n", ie->num_opts, NPRT(ie->opts_list[0]->opts));
+ Dmsg2(500, "numopts=%d opts=%s\n", ie->num_opts, NPRT(ie->opts_list[0]->opts));
pm_strcpy(fd->msg, ie->opts_list[0]->opts);
- pm_strcat(fd->msg, " ");
+ pm_strcat(fd->msg, " ");
} else {
- pm_strcpy(fd->msg, "0 ");
+ pm_strcpy(fd->msg, "0 ");
}
fd->msglen = pm_strcat(fd->msg, p);
- Dmsg1(500, "Inc/Exc name=%s\n", fd->msg);
+ Dmsg1(500, "Inc/Exc name=%s\n", fd->msg);
if (!bnet_send(fd)) {
- Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
+ Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
}
break;
if (include) {
ie = fileset->include_items[i];
- bnet_fsend(fd, "I\n");
+ bnet_fsend(fd, "I\n");
} else {
ie = fileset->exclude_items[i];
- bnet_fsend(fd, "E\n");
+ bnet_fsend(fd, "E\n");
}
for (j=0; j<ie->num_opts; j++) {
FOPTS *fo = ie->opts_list[j];
- bnet_fsend(fd, "O %s\n", fo->opts);
+ bnet_fsend(fd, "O %s\n", fo->opts);
for (k=0; k<fo->regex.size(); k++) {
- bnet_fsend(fd, "R %s\n", fo->regex.get(k));
+ bnet_fsend(fd, "R %s\n", fo->regex.get(k));
}
for (k=0; k<fo->regexdir.size(); k++) {
- bnet_fsend(fd, "RD %s\n", fo->regexdir.get(k));
+ bnet_fsend(fd, "RD %s\n", fo->regexdir.get(k));
}
for (k=0; k<fo->regexfile.size(); k++) {
- bnet_fsend(fd, "RF %s\n", fo->regexfile.get(k));
+ bnet_fsend(fd, "RF %s\n", fo->regexfile.get(k));
}
for (k=0; k<fo->wild.size(); k++) {
- bnet_fsend(fd, "W %s\n", fo->wild.get(k));
+ bnet_fsend(fd, "W %s\n", fo->wild.get(k));
}
for (k=0; k<fo->wilddir.size(); k++) {
- bnet_fsend(fd, "WD %s\n", fo->wilddir.get(k));
+ bnet_fsend(fd, "WD %s\n", fo->wilddir.get(k));
}
for (k=0; k<fo->wildfile.size(); k++) {
- bnet_fsend(fd, "WF %s\n", fo->wildfile.get(k));
+ bnet_fsend(fd, "WF %s\n", fo->wildfile.get(k));
}
for (k=0; k<fo->base.size(); k++) {
- bnet_fsend(fd, "B %s\n", fo->base.get(k));
+ bnet_fsend(fd, "B %s\n", fo->base.get(k));
}
for (k=0; k<fo->fstype.size(); k++) {
- bnet_fsend(fd, "X %s\n", fo->fstype.get(k));
+ bnet_fsend(fd, "X %s\n", fo->fstype.get(k));
}
if (fo->reader) {
- bnet_fsend(fd, "D %s\n", fo->reader);
+ bnet_fsend(fd, "D %s\n", fo->reader);
}
if (fo->writer) {
- bnet_fsend(fd, "T %s\n", fo->writer);
+ bnet_fsend(fd, "T %s\n", fo->writer);
}
- bnet_fsend(fd, "N\n");
+ bnet_fsend(fd, "N\n");
}
for (j=0; j<ie->name_list.size(); j++) {
p = (char *)ie->name_list.get(j);
switch (*p) {
- case '|':
+ case '|':
p++; /* skip over the | */
- fd->msg = edit_job_codes(jcr, fd->msg, p, "");
- bpipe = open_bpipe(fd->msg, 0, "r");
+ fd->msg = edit_job_codes(jcr, fd->msg, p, "");
+ bpipe = open_bpipe(fd->msg, 0, "r");
if (!bpipe) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
p, be.strerror());
goto bail_out;
}
- bstrncpy(buf, "F ", sizeof(buf));
- Dmsg1(500, "Opts=%s\n", buf);
+ bstrncpy(buf, "F ", sizeof(buf));
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) {
- fd->msglen = Mmsg(fd->msg, "%s", buf);
- Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
+ fd->msglen = Mmsg(fd->msg, "%s", buf);
+ Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
if (!bnet_send(fd)) {
- Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
+ Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
}
}
if ((stat=close_bpipe(bpipe)) != 0) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. ERR=%s\n"),
p, be.strerror(stat));
goto bail_out;
}
break;
- case '<':
+ case '<':
p++; /* skip over < */
- if ((ffd = fopen(p, "r")) == NULL) {
+ if ((ffd = fopen(p, "r")) == NULL) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Cannot open included file: %s. ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Cannot open included file: %s. ERR=%s\n"),
p, be.strerror());
goto bail_out;
}
- bstrncpy(buf, "F ", sizeof(buf));
- Dmsg1(500, "Opts=%s\n", buf);
+ bstrncpy(buf, "F ", sizeof(buf));
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) {
- fd->msglen = Mmsg(fd->msg, "%s", buf);
+ fd->msglen = Mmsg(fd->msg, "%s", buf);
if (!bnet_send(fd)) {
- Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
+ Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
}
}
fclose(ffd);
break;
- case '\\':
- p++; /* skip over \ */
+ case '\\':
+ p++; /* skip over \ */
/* Note, fall through wanted */
default:
- pm_strcpy(fd->msg, "F ");
+ pm_strcpy(fd->msg, "F ");
fd->msglen = pm_strcat(fd->msg, p);
- Dmsg1(500, "Inc/Exc name=%s\n", fd->msg);
+ Dmsg1(500, "Inc/Exc name=%s\n", fd->msg);
if (!bnet_send(fd)) {
- Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
+ Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
}
break;
}
}
- bnet_fsend(fd, "N\n");
+ bnet_fsend(fd, "N\n");
}
if (!include) { /* If we just did excludes */
break; /* all done */
jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen);
if ((len = sscanf(fd->msg, "%ld %d %s", &file_index, &stream, Opts_SIG)) != 3) {
- Jmsg(jcr, M_FATAL, 0, _("<filed: bad attributes, expected 3 fields got %d\n"
+ Jmsg(jcr, M_FATAL, 0, _("<filed: bad attributes, expected 3 fields got %d\n"
"msglen=%d msg=%s\n"), len, fd->msglen, fd->msg);
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
ar.PathId = 0;
ar.FilenameId = 0;
- Dmsg2(111, "dird<filed: stream=%d %s\n", stream, jcr->fname);
- Dmsg1(120, "dird<filed: attr=%s\n", attr);
+ Dmsg2(111, "dird<filed: stream=%d %s\n", stream, jcr->fname);
+ Dmsg1(120, "dird<filed: attr=%s\n", attr);
if (!db_create_file_attributes_record(jcr, jcr->db, &ar)) {
- Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+ Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
set_jcr_job_status(jcr, JS_Error);
continue;
}
jcr->FileId = ar.FileId;
} else if (stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE) {
if (jcr->FileIndex != (uint32_t)file_index) {
- Jmsg2(jcr, M_ERROR, 0, _("MD5/SHA1 index %d not same as attributes %d\n"),
+ Jmsg2(jcr, M_ERROR, 0, _("MD5/SHA1 index %d not same as attributes %d\n"),
file_index, jcr->FileIndex);
set_jcr_job_status(jcr, JS_Error);
continue;
}
db_escape_string(SIG, Opts_SIG, strlen(Opts_SIG));
- Dmsg2(120, "SIGlen=%d SIG=%s\n", strlen(SIG), SIG);
+ Dmsg2(120, "SIGlen=%d SIG=%s\n", strlen(SIG), SIG);
if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIG,
stream==STREAM_MD5_SIGNATURE?MD5_SIG:SHA1_SIG)) {
- Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+ Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
set_jcr_job_status(jcr, JS_Error);
}
}
* Version $Id$
*/
/*
- Copyright (C) 2003-2004 Kern Sibbald
+ Copyright (C) 2003-2005 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
}
regfree(&preg);
if (item->code == 1) {
- type = "regexdir";
+ type = "regexdir";
res_incexe.current_opts->regexdir.append(bstrdup(lc->str));
newsize = res_incexe.current_opts->regexdir.size();
} else if (item->code == 2) {
- type = "regexfile";
+ type = "regexfile";
res_incexe.current_opts->regexfile.append(bstrdup(lc->str));
newsize = res_incexe.current_opts->regexfile.size();
} else {
- type = "regex";
+ type = "regex";
res_incexe.current_opts->regex.append(bstrdup(lc->str));
newsize = res_incexe.current_opts->regex.size();
}
case T_UNQUOTED_STRING:
case T_QUOTED_STRING:
if (item->code == 1) {
- type = "wilddir";
+ type = "wilddir";
res_incexe.current_opts->wilddir.append(bstrdup(lc->str));
newsize = res_incexe.current_opts->wilddir.size();
} else if (item->code == 2) {
- type = "wildfile";
+ type = "wildfile";
res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
newsize = res_incexe.current_opts->wildfile.size();
} else {
- type = "wild";
+ type = "wild";
res_incexe.current_opts->wild.append(bstrdup(lc->str));
newsize = res_incexe.current_opts->wild.size();
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald
+ Copyright (C) 2000-2005 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
jcr->fileset = job->fileset;
jcr->messages = job->messages;
jcr->spool_data = job->spool_data;
+ jcr->write_part_after_job = job->write_part_after_job;
if (jcr->RestoreBootstrap) {
free(jcr->RestoreBootstrap);
jcr->RestoreBootstrap = NULL;
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald
+ Copyright (C) 2000-2005 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
/* Commands sent to Storage daemon */
static char jobcmd[] = "JobId=%d job=%s job_name=%s client_name=%s "
-"type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s SpoolData=%d";
+"type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s SpoolData=%d WritePartAfterJob=%d";
static char use_device[] = "use device=%s media_type=%s pool_name=%s pool_type=%s\n";
/* Response from Storage daemon */
Dmsg2(200, "bnet_connect to Storage daemon %s:%d\n", store->address,
store->SDport);
sd = bnet_connect(jcr, retry_interval, max_retry_time,
- _("Storage daemon"), store->address,
+ _("Storage daemon"), store->address,
NULL, store->SDport, verbose);
if (sd == NULL) {
return false;
bnet_fsend(sd, jobcmd, jcr->JobId, jcr->Job, jcr->job->hdr.name,
jcr->client->hdr.name, jcr->JobType, jcr->JobLevel,
jcr->fileset->hdr.name, !jcr->pool->catalog_files,
- jcr->job->SpoolAttributes, jcr->fileset->MD5, jcr->spool_data);
+ jcr->job->SpoolAttributes, jcr->fileset->MD5, jcr->spool_data, jcr->write_part_after_job);
Dmsg1(200, "Jobcmd=%s\n", sd->msg);
unbash_spaces(jcr->job->hdr.name);
unbash_spaces(jcr->client->hdr.name);
Dmsg1(110, "<stored: %s", sd->msg);
if (sscanf(sd->msg, OKjob, &jcr->VolSessionId,
&jcr->VolSessionTime, &auth_key) != 3) {
- Dmsg1(100, "BadJob=%s\n", sd->msg);
- Jmsg(jcr, M_FATAL, 0, _("Storage daemon rejected Job command: %s\n"), sd->msg);
+ Dmsg1(100, "BadJob=%s\n", sd->msg);
+ Jmsg(jcr, M_FATAL, 0, _("Storage daemon rejected Job command: %s\n"), sd->msg);
return 0;
} else {
jcr->sd_auth_key = bstrdup(auth_key);
- Dmsg1(150, "sd_auth_key=%s\n", jcr->sd_auth_key);
+ Dmsg1(150, "sd_auth_key=%s\n", jcr->sd_auth_key);
}
} else {
Jmsg(jcr, M_FATAL, 0, _("<stored: bad response to Job command: %s\n"),
bash_spaces(pool_name);
bnet_fsend(sd, use_device, device_name.c_str(),
media_type.c_str(), pool_name.c_str(), pool_type.c_str());
- Dmsg1(110, ">stored: %s", sd->msg);
- status = response(jcr, sd, OK_device, "Use Device", NO_DISPLAY);
+ Dmsg1(110, ">stored: %s", sd->msg);
+ status = response(jcr, sd, OK_device, "Use Device", NO_DISPLAY);
if (!status) {
pm_strcpy(pool_type, sd->msg); /* save message */
- Jmsg(jcr, M_FATAL, 0, _("\n"
- " Storage daemon didn't accept Device \"%s\" because:\n %s"),
+ Jmsg(jcr, M_FATAL, 0, _("\n"
+ " Storage daemon didn't accept Device \"%s\" because:\n %s"),
device_name.c_str(), pool_type.c_str()/* sd->msg */);
}
}
*/
/*
-
- Copyright (C) 2004 Kern Sibbald
+ Copyright (C) 2000-2005 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
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
/* Keywords (RHS) permitted in Run records */
static struct s_kw RunFields[] = {
- {"pool", 'P'},
- {"fullpool", 'f'},
- {"incrementalpool", 'i'},
- {"differentialpool", 'd'},
- {"level", 'L'},
- {"storage", 'S'},
- {"messages", 'M'},
- {"priority", 'p'},
- {"spooldata", 's'},
+ {"pool", 'P'},
+ {"fullpool", 'f'},
+ {"incrementalpool", 'i'},
+ {"differentialpool", 'd'},
+ {"level", 'L'},
+ {"storage", 'S'},
+ {"messages", 'M'},
+ {"priority", 'p'},
+ {"spooldata", 's'},
+ {"writepartafterjob", 'W'},
{NULL, 0}
};
if (strcasecmp(lc->str, RunFields[i].name) == 0) {
found = true;
if (lex_get_token(lc, T_ALL) != T_EQUALS) {
- scan_err1(lc, "Expected an equals, got: %s", lc->str);
+ scan_err1(lc, "Expected an equals, got: %s", lc->str);
/* NOT REACHED */
}
switch (RunFields[i].token) {
- case 's': /* Data spooling */
+ case 's': /* Data spooling */
token = lex_get_token(lc, T_NAME);
- if (strcasecmp(lc->str, "yes") == 0) {
+ if (strcasecmp(lc->str, "yes") == 0) {
lrun.spool_data = true;
lrun.spool_data_set = true;
- } else if (strcasecmp(lc->str, "no") == 0) {
+ } else if (strcasecmp(lc->str, "no") == 0) {
lrun.spool_data = false;
lrun.spool_data_set = true;
} else {
- scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
+ scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
}
break;
- case 'L': /* level */
+ case 'W': /* Write part after job */
+ token = lex_get_token(lc, T_NAME);
+ if (strcasecmp(lc->str, "yes") == 0) {
+ lrun.write_part_after_job = true;
+ lrun.write_part_after_job_set = true;
+ } else if (strcasecmp(lc->str, "no") == 0) {
+ lrun.write_part_after_job = false;
+ lrun.write_part_after_job_set = true;
+ } else {
+ scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
+ }
+ break;
+ case 'L': /* level */
token = lex_get_token(lc, T_NAME);
for (j=0; joblevels[j].level_name; j++) {
if (strcasecmp(lc->str, joblevels[j].level_name) == 0) {
}
}
if (j != 0) {
- scan_err1(lc, _("Job level field: %s not found in run record"), lc->str);
+ scan_err1(lc, _("Job level field: %s not found in run record"), lc->str);
/* NOT REACHED */
}
break;
- case 'p': /* Priority */
+ case 'p': /* Priority */
token = lex_get_token(lc, T_PINT32);
if (pass == 2) {
lrun.Priority = lc->pint32_val;
}
break;
- case 'P': /* Pool */
- case 'f': /* FullPool */
- case 'i': /* IncPool */
- case 'd': /* DifPool */
+ case 'P': /* Pool */
+ case 'f': /* FullPool */
+ case 'i': /* IncPool */
+ case 'd': /* DifPool */
token = lex_get_token(lc, T_NAME);
if (pass == 2) {
res = GetResWithName(R_POOL, lc->str);
if (res == NULL) {
- scan_err1(lc, "Could not find specified Pool Resource: %s",
+ scan_err1(lc, "Could not find specified Pool Resource: %s",
lc->str);
/* NOT REACHED */
}
switch(RunFields[i].token) {
- case 'P':
+ case 'P':
lrun.pool = (POOL *)res;
break;
- case 'f':
+ case 'f':
lrun.full_pool = (POOL *)res;
break;
- case 'i':
+ case 'i':
lrun.inc_pool = (POOL *)res;
break;
- case 'd':
+ case 'd':
lrun.dif_pool = (POOL *)res;
break;
}
}
break;
- case 'S': /* storage */
+ case 'S': /* storage */
token = lex_get_token(lc, T_NAME);
if (pass == 2) {
res = GetResWithName(R_STORAGE, lc->str);
if (res == NULL) {
- scan_err1(lc, "Could not find specified Storage Resource: %s",
+ scan_err1(lc, "Could not find specified Storage Resource: %s",
lc->str);
/* NOT REACHED */
}
lrun.storage = (STORE *)res;
}
break;
- case 'M': /* messages */
+ case 'M': /* messages */
token = lex_get_token(lc, T_NAME);
if (pass == 2) {
res = GetResWithName(R_MSGS, lc->str);
if (res == NULL) {
- scan_err1(lc, "Could not find specified Messages Resource: %s",
+ scan_err1(lc, "Could not find specified Messages Resource: %s",
lc->str);
/* NOT REACHED */
}
}
break;
default:
- scan_err1(lc, "Expected a keyword name, got: %s", lc->str);
+ scan_err1(lc, "Expected a keyword name, got: %s", lc->str);
/* NOT REACHED */
break;
} /* end switch */
state = s_mday;
code = atoi(lc->str) - 1;
if (code < 0 || code > 30) {
- scan_err0(lc, _("Day number out of range (1-31)"));
+ scan_err0(lc, _("Day number out of range (1-31)"));
}
break;
case T_NAME: /* this handles drop through from keyword */
case T_UNQUOTED_STRING:
- if (strchr(lc->str, (int)'-')) {
+ if (strchr(lc->str, (int)'-')) {
state = s_range;
break;
}
- if (strchr(lc->str, (int)':')) {
+ if (strchr(lc->str, (int)':')) {
state = s_time;
break;
}
- if (lc->str_len == 3 && (lc->str[0] == 'w' || lc->str[0] == 'W') &&
+ if (lc->str_len == 3 && (lc->str[0] == 'w' || lc->str[0] == 'W') &&
is_an_integer(lc->str+1)) {
code = atoi(lc->str+1);
if (code < 0 || code > 53) {
- scan_err0(lc, _("Week number out of range (0-53)"));
+ scan_err0(lc, _("Week number out of range (0-53)"));
}
state = s_woy; /* week of year */
break;
}
}
if (i != 0) {
- scan_err1(lc, _("Job type field: %s in run record not found"), lc->str);
+ scan_err1(lc, _("Job type field: %s in run record not found"), lc->str);
/* NOT REACHED */
}
break;
case T_COMMA:
continue;
default:
- scan_err2(lc, _("Unexpected token: %d:%s"), token, lc->str);
+ scan_err2(lc, _("Unexpected token: %d:%s"), token, lc->str);
/* NOT REACHED */
break;
}
break;
case s_time: /* time */
if (!have_at) {
- scan_err0(lc, _("Time must be preceded by keyword AT."));
+ scan_err0(lc, _("Time must be preceded by keyword AT."));
/* NOT REACHED */
}
if (!have_hour) {
clear_bits(0, 23, lrun.hour);
}
- p = strchr(lc->str, ':');
+ p = strchr(lc->str, ':');
if (!p) {
- scan_err0(lc, _("Time logic error.\n"));
+ scan_err0(lc, _("Time logic error.\n"));
/* NOT REACHED */
}
*p++ = 0; /* separate two halves */
code = atoi(lc->str);
len = strlen(p);
- if (len > 2 && p[len-1] == 'm') {
- if (p[len-2] == 'a') {
+ if (len > 2 && p[len-1] == 'm') {
+ if (p[len-2] == 'a') {
pm = 0;
- } else if (p[len-2] == 'p') {
+ } else if (p[len-2] == 'p') {
pm = 1;
} else {
- scan_err0(lc, _("Bad time specification."));
+ scan_err0(lc, _("Bad time specification."));
/* NOT REACHED */
}
} else {
code += 12;
}
if (code < 0 || code > 23 || code2 < 0 || code2 > 59) {
- scan_err0(lc, _("Bad time specification."));
+ scan_err0(lc, _("Bad time specification."));
/* NOT REACHED */
}
/****FIXME**** convert to UTC */
have_at = true;
break;
case s_range:
- p = strchr(lc->str, '-');
+ p = strchr(lc->str, '-');
if (!p) {
- scan_err0(lc, _("Range logic error.\n"));
+ scan_err0(lc, _("Range logic error.\n"));
}
*p++ = 0; /* separate two halves */
code = atoi(lc->str) - 1;
code2 = atoi(p) - 1;
if (code < 0 || code > 30 || code2 < 0 || code2 > 30) {
- scan_err0(lc, _("Bad day range specification."));
+ scan_err0(lc, _("Bad day range specification."));
}
if (!have_mday) {
clear_bits(0, 30, lrun.mday);
}
/* Check for week of year range */
if (strlen(lc->str) == 3 && strlen(p) == 3 &&
- (lc->str[0] == 'w' || lc->str[0] == 'W') &&
- (p[0] == 'w' || p[0] == 'W') &&
+ (lc->str[0] == 'w' || lc->str[0] == 'W') &&
+ (p[0] == 'w' || p[0] == 'W') &&
is_an_integer(lc->str+1) && is_an_integer(p+1)) {
code = atoi(lc->str+1);
code2 = atoi(p+1);
if (code < 0 || code > 53 || code2 < 0 || code2 > 53) {
- scan_err0(lc, _("Week number out of range (0-53)"));
+ scan_err0(lc, _("Week number out of range (0-53)"));
}
if (!have_woy) {
clear_bits(0, 53, lrun.woy);
}
}
if (i != 0 || (state != s_month && state != s_wday && state != s_wom)) {
- scan_err0(lc, _("Invalid month, week or position day range"));
+ scan_err0(lc, _("Invalid month, week or position day range"));
/* NOT REACHED */
}
}
}
if (i != 0 || state != state2 || code == code2) {
- scan_err0(lc, _("Invalid month, weekday or position range"));
+ scan_err0(lc, _("Invalid month, weekday or position range"));
/* NOT REACHED */
}
if (state == s_wday) {
set_bits(0, 11, lrun.month);
break;
default:
- scan_err0(lc, _("Unexpected run state\n"));
+ scan_err0(lc, _("Unexpected run state\n"));
/* NOT REACHED */
break;
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald
+ Copyright (C) 2000-2005 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
if (one_shot_job_to_run) { /* one shot */
job = (JOB *)GetResWithName(R_JOB, one_shot_job_to_run);
if (!job) {
- Emsg1(M_ABORT, 0, _("Job %s not found\n"), one_shot_job_to_run);
+ Emsg1(M_ABORT, 0, _("Job %s not found\n"), one_shot_job_to_run);
}
- Dmsg1(5, "Found one_shot_job_to_run %s\n", one_shot_job_to_run);
+ Dmsg1(5, "Found one_shot_job_to_run %s\n", one_shot_job_to_run);
jcr = new_jcr(sizeof(JCR), dird_free_jcr);
set_jcr_defaults(jcr, job);
return jcr;
if (run->spool_data_set) {
jcr->spool_data = run->spool_data;
}
+ if (run->write_part_after_job_set) {
+ jcr->write_part_after_job = run->write_part_after_job;
+ }
Dmsg0(200, "Leave wait_for_next_job()\n");
return jcr;
}
* Find runs scheduled between now and the next hour.
*/
#ifdef xxxx
- Dmsg0(000, "\n");
- Dmsg6(000, "run h=%d m=%d md=%d wd=%d wom=%d woy=%d\n",
+ Dmsg0(000, "\n");
+ Dmsg6(000, "run h=%d m=%d md=%d wd=%d wom=%d woy=%d\n",
hour, month, mday, wday, wom, woy);
- Dmsg6(000, "bitset bsh=%d bsm=%d bsmd=%d bswd=%d bswom=%d bswoy=%d\n",
+ Dmsg6(000, "bitset bsh=%d bsm=%d bsmd=%d bswd=%d bswom=%d bswoy=%d\n",
bit_is_set(hour, run->hour),
bit_is_set(month, run->month),
bit_is_set(mday, run->mday),
bit_is_set(wom, run->wom),
bit_is_set(woy, run->woy));
- Dmsg6(000, "nh_run h=%d m=%d md=%d wd=%d wom=%d woy=%d\n",
+ Dmsg6(000, "nh_run h=%d m=%d md=%d wd=%d wom=%d woy=%d\n",
nh_hour, nh_month, nh_mday, nh_wday, nh_wom, nh_woy);
- Dmsg6(000, "nh_bitset bsh=%d bsm=%d bsmd=%d bswd=%d bswom=%d bswoy=%d\n",
+ Dmsg6(000, "nh_bitset bsh=%d bsm=%d bsmd=%d bswd=%d bswom=%d bswoy=%d\n",
bit_is_set(nh_hour, run->hour),
bit_is_set(nh_month, run->month),
bit_is_set(nh_mday, run->mday),
bit_is_set(nh_wom, run->wom) &&
bit_is_set(nh_woy, run->woy);
- Dmsg2(200, "run_now=%d run_nh=%d\n", run_now, run_nh);
+ Dmsg2(200, "run_now=%d run_nh=%d\n", run_now, run_nh);
/* find time (time_t) job is to be run */
localtime_r(&now, &tm); /* reset tm structure */
if (ji->runtime > je->runtime ||
(ji->runtime == je->runtime && ji->Priority > je->Priority)) {
jobs_to_run->insert_before(je, ji);
- dump_job(je, "Inserted job");
+ dump_job(je, "Inserted job");
inserted = true;
break;
}
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald
+ Copyright (C) 2000-2005 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
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
if (code != '\0') {
++item;
}
- int subcode = ' '; /* A space is always a valid subcode */
+ int subcode = ' '; /* A space is always a valid subcode */
if (item[0] != '\0' && item[0] != ' ') {
subcode = item[0];
++item;
for (k=0; k<fo->regex.size(); k++) {
Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
}
- for (k=0; k<fo->regexdir.size(); k++) {
- Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
- }
- for (k=0; k<fo->regexfile.size(); k++) {
- Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
- }
- for (k=0; k<fo->wild.size(); k++) {
- Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
- }
- for (k=0; k<fo->wilddir.size(); k++) {
- Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
- }
- for (k=0; k<fo->wildfile.size(); k++) {
- Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
- }
+ for (k=0; k<fo->regexdir.size(); k++) {
+ Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
+ }
+ for (k=0; k<fo->regexfile.size(); k++) {
+ Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
+ }
+ for (k=0; k<fo->wild.size(); k++) {
+ Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
+ }
+ for (k=0; k<fo->wilddir.size(); k++) {
+ Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
+ }
+ for (k=0; k<fo->wildfile.size(); k++) {
+ Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
+ }
for (k=0; k<fo->base.size(); k++) {
Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
}
for (k=0; k<fo->regex.size(); k++) {
Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
}
- for (k=0; k<fo->regexdir.size(); k++) {
- Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
- }
- for (k=0; k<fo->regexfile.size(); k++) {
- Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
- }
- for (k=0; k<fo->wild.size(); k++) {
- Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
- }
- for (k=0; k<fo->wilddir.size(); k++) {
- Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
- }
- for (k=0; k<fo->wildfile.size(); k++) {
- Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
- }
+ for (k=0; k<fo->regexdir.size(); k++) {
+ Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
+ }
+ for (k=0; k<fo->regexfile.size(); k++) {
+ Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
+ }
+ for (k=0; k<fo->wild.size(); k++) {
+ Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
+ }
+ for (k=0; k<fo->wilddir.size(); k++) {
+ Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
+ }
+ for (k=0; k<fo->wildfile.size(); k++) {
+ Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
+ }
for (k=0; k<fo->base.size(); k++) {
Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
}
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald
+ Copyright (C) 2000-2005 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
* 3. Repeat step 1
*
* NOTE: We keep track of two bacula file descriptors:
- * 1. bfd for file data.
+ * 1. bfd for file data.
* This fd is opened for non empty files when an attribute stream is
* encountered and closed when we find the next attribute stream.
- * 2. alt_bfd for alternate data streams
+ * 2. alt_bfd for alternate data streams
* This fd is opened every time we encounter a new alternate data
* stream for the current file. When we find any other stream, we
* close it again.
- * The expected size of the stream, alt_len, should be set when
- * opening the fd.
+ * The expected size of the stream, alt_len, should be set when
+ * opening the fd.
*/
binit(&bfd);
binit(&altbfd);
/* First we expect a Stream Record Header */
if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
&stream, &size) != 5) {
- Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
+ Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
goto bail_out;
}
Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
/* * Now we expect the Stream Data */
if (bget_msg(sd) < 0) {
- Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
+ Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
goto bail_out;
}
if (size != (uint32_t)sd->msglen) {
- Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
+ Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
goto bail_out;
}
Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
switch (stream) {
case STREAM_UNIX_ATTRIBUTES:
case STREAM_UNIX_ATTRIBUTES_EX:
- Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
+ Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
/*
* If extracting, it was from previous stream, so
* close the output file.
*/
if (extract) {
if (size > 0 && !is_bopen(&bfd)) {
- Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
+ Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
}
set_attributes(jcr, attr, &bfd);
extract = false;
- Dmsg0(30, "Stop extracting.\n");
+ Dmsg0(30, "Stop extracting.\n");
} else if (is_bopen(&bfd)) {
- Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
+ Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
bclose(&bfd);
}
goto bail_out;
}
if (file_index != attr->file_index) {
- Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
file_index, attr->file_index);
- Dmsg0(100, "File index error\n");
+ Dmsg0(100, "File index error\n");
goto bail_out;
}
- Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
+ Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
attr->attr, attr->attrEx);
attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
if (!is_stream_supported(attr->data_stream)) {
if (!non_support_data++) {
- Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
+ Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
stream_to_ascii(attr->data_stream));
}
continue;
* Now determine if we are extracting or not.
*/
jcr->num_files_examined++;
- Dmsg1(30, "Outfile=%s\n", attr->ofname);
+ Dmsg1(30, "Outfile=%s\n", attr->ofname);
extract = false;
stat = create_file(jcr, attr, &bfd, jcr->replace);
switch (stat) {
if (extract) {
if (prev_stream != stream) {
if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
- Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s\n"), jcr->last_fname);
+ Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s\n"), jcr->last_fname);
extract = false;
continue;
}
alt_size = rsrc_len;
- Dmsg0(30, "Restoring resource fork\n");
+ Dmsg0(30, "Restoring resource fork\n");
}
flags = 0;
if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags) < 0) {
case STREAM_HFSPLUS_ATTRIBUTES:
#ifdef HAVE_DARWIN_OS
- Dmsg0(30, "Restoring Finder Info\n");
+ Dmsg0(30, "Restoring Finder Info\n");
if (sd->msglen != 32) {
- Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
+ Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
continue;
}
if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
- Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
+ Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
continue;
}
#else
/* Recover Acess ACL from stream and check it */
acl = acl_from_text(sd->msg);
if (acl_valid(acl) != 0) {
- Jmsg1(jcr, M_WARNING, 0, "Failure in the ACL of %s! FD is not able to restore it!\n", jcr->last_fname);
+ Jmsg1(jcr, M_WARNING, 0, "Failure in the ACL of %s! FD is not able to restore it!\n", jcr->last_fname);
acl_free(acl);
}
if (attr->type == FT_DIREND) {
/* Directory */
if (acl_set_file(jcr->last_fname, ACL_TYPE_ACCESS, acl) != 0) {
- Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore ACL of directory: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
+ Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore ACL of directory: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
}
/* File or Link */
} else if (acl_set_file(jcr->last_fname, ACL_TYPE_ACCESS, acl) != 0) {
- Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore ACL of file: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
+ Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore ACL of file: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
}
acl_free(acl);
- Dmsg1(200, "ACL of file: %s successfully restored!\n", jcr->last_fname);
+ Dmsg1(200, "ACL of file: %s successfully restored!\n", jcr->last_fname);
break;
#else
non_support_acl++;
/* Recover Default ACL from stream and check it */
acl = acl_from_text(sd->msg);
if (acl_valid(acl) != 0) {
- Jmsg1(jcr, M_WARNING, 0, "Failure in the Default ACL of %s! FD is not able to restore it!\n", jcr->last_fname);
+ Jmsg1(jcr, M_WARNING, 0, "Failure in the Default ACL of %s! FD is not able to restore it!\n", jcr->last_fname);
acl_free(acl);
}
if (attr->type == FT_DIREND) {
/* Directory */
if (acl_set_file(jcr->last_fname, ACL_TYPE_DEFAULT, acl) != 0) {
- Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore Default ACL of directory: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
+ Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore Default ACL of directory: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
}
}
acl_free(acl);
- Dmsg1(200, "Default ACL of file: %s successfully restored!\n", jcr->last_fname);
+ Dmsg1(200, "Default ACL of file: %s successfully restored!\n", jcr->last_fname);
break;
#else
non_support_acl++;
case STREAM_PROGRAM_NAMES:
case STREAM_PROGRAM_DATA:
if (!non_support_progname) {
- Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
+ Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
non_support_progname++;
}
break;
default:
/* If extracting, wierd stream (not 1 or 2), close output file anyway */
if (extract) {
- Dmsg1(30, "Found wierd stream %d\n", stream);
+ Dmsg1(30, "Found wierd stream %d\n", stream);
if (size > 0 && !is_bopen(&bfd)) {
- Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
+ Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
}
set_attributes(jcr, attr, &bfd);
extract = false;
} else if (is_bopen(&bfd)) {
- Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
+ Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
bclose(&bfd);
}
- Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
- Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
+ Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
+ Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
break;
} /* end switch(stream) */
if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
berrno be;
be.set_errno(bfd->berrno);
- Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
+ Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
edit_uint64(*addr, ec1), jcr->last_fname, be.strerror());
return -1;
}
Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
(const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
+ Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
jcr->last_fname, zlib_strerror(stat));
return -1;
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
bstrncat(ff->VerifyOpts, fo->VerifyOpts, sizeof(ff->VerifyOpts));
}
for (j=0; j<incexe->name_list.size(); j++) {
- Dmsg1(100, "F %s\n", (char *)incexe->name_list.get(j));
+ Dmsg1(100, "F %s\n", (char *)incexe->name_list.get(j));
char *fname = (char *)incexe->name_list.get(j);
if (find_one_file(jcr, ff, our_callback, his_pkt, fname, (dev_t)-1, 1) == 0) {
return 0; /* error return */
while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
/* Copy options for this file */
bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
- Dmsg1(100, "find_files: file=%s\n", inc->fname);
+ Dmsg1(100, "find_files: file=%s\n", inc->fname);
if (!file_is_excluded(ff, inc->fname)) {
if (find_one_file(jcr, ff, callback, his_pkt, inc->fname, (dev_t)-1, 1) ==0) {
return 0; /* error return */
for (k=0; k<fo->wilddir.size(); k++) {
if (fnmatch((char *)fo->wilddir.get(k), ff->fname, fnmode|ic) == 0) {
if (ff->flags & FO_EXCLUDE) {
- Dmsg2(100, "Exclude wilddir: %s file=%s\n", (char *)fo->wilddir.get(k),
+ Dmsg2(100, "Exclude wilddir: %s file=%s\n", (char *)fo->wilddir.get(k),
ff->fname);
- return false; /* reject file */
+ return false; /* reject file */
}
return true; /* accept file */
}
for (k=0; k<fo->wildfile.size(); k++) {
if (fnmatch((char *)fo->wildfile.get(k), ff->fname, fnmode|ic) == 0) {
if (ff->flags & FO_EXCLUDE) {
- Dmsg2(100, "Exclude wildfile: %s file=%s\n", (char *)fo->wildfile.get(k),
+ Dmsg2(100, "Exclude wildfile: %s file=%s\n", (char *)fo->wildfile.get(k),
ff->fname);
- return false; /* reject file */
+ return false; /* reject file */
}
return true; /* accept file */
}
for (k=0; k<fo->wild.size(); k++) {
if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|ic) == 0) {
if (ff->flags & FO_EXCLUDE) {
- Dmsg2(100, "Exclude wild: %s file=%s\n", (char *)fo->wild.get(k),
+ Dmsg2(100, "Exclude wild: %s file=%s\n", (char *)fo->wild.get(k),
ff->fname);
return false; /* reject file */
}
regmatch_t pmatch[nmatch];
if (regexec((regex_t *)fo->regexdir.get(k), ff->fname, nmatch, pmatch, 0) == 0) {
if (ff->flags & FO_EXCLUDE) {
- return false; /* reject file */
+ return false; /* reject file */
}
return true; /* accept file */
}
regmatch_t pmatch[nmatch];
if (regexec((regex_t *)fo->regexfile.get(k), ff->fname, nmatch, pmatch, 0) == 0) {
if (ff->flags & FO_EXCLUDE) {
- return false; /* reject file */
+ return false; /* reject file */
}
return true; /* accept file */
}
ic = (fo->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0;
for (k=0; k<fo->wild.size(); k++) {
if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|ic) == 0) {
- Dmsg1(100, "Reject wild1: %s\n", ff->fname);
+ Dmsg1(100, "Reject wild1: %s\n", ff->fname);
return false; /* reject file */
}
}
? FNM_CASEFOLD : 0;
for (j=0; j<incexe->name_list.size(); j++) {
if (fnmatch((char *)incexe->name_list.get(j), ff->fname, fnmode|ic) == 0) {
- Dmsg1(100, "Reject wild2: %s\n", ff->fname);
+ Dmsg1(100, "Reject wild2: %s\n", ff->fname);
return false; /* reject file */
}
}
if (accept_file(ff)) {
return ff->callback(ff, hpkt);
} else {
- Dmsg1(100, "Skip file %s\n", ff->fname);
+ Dmsg1(100, "Skip file %s\n", ff->fname);
return -1; /* ignore this file */
}
/*
* File types as returned by find_files()
*
- * Kern Sibbald MIM
+ * Kern Sibbald MMI
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald
+ Copyright (C) 2001-2005 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
* Status codes returned by create_file()
*/
enum {
- CF_SKIP = 1, /* skip file (not newer or something) */
- CF_ERROR, /* error creating file */
- CF_EXTRACT, /* file created, data to extract */
- CF_CREATED /* file created, no data to extract */
+ CF_SKIP = 1, /* skip file (not newer or something) */
+ CF_ERROR, /* error creating file */
+ CF_EXTRACT, /* file created, data to extract */
+ CF_CREATED /* file created, no data to extract */
};
/* Options saved int "options" of the include/exclude lists.
* They are directly jammed ito "flag" of ff packet
*/
-#define FO_MD5 (1<<1) /* Do MD5 checksum */
-#define FO_GZIP (1<<2) /* Do Zlib compression */
-#define FO_NO_RECURSION (1<<3) /* no recursion in directories */
-#define FO_MULTIFS (1<<4) /* multiple file systems */
-#define FO_SPARSE (1<<5) /* do sparse file checking */
-#define FO_IF_NEWER (1<<6) /* replace if newer */
-#define FO_NOREPLACE (1<<7) /* never replace */
-#define FO_READFIFO (1<<8) /* read data from fifo */
-#define FO_SHA1 (1<<9) /* Do SHA1 checksum */
-#define FO_PORTABLE (1<<10) /* Use portable data format -- no BackupWrite */
-#define FO_MTIMEONLY (1<<11) /* Use mtime rather than mtime & ctime */
-#define FO_KEEPATIME (1<<12) /* Reset access time */
-#define FO_EXCLUDE (1<<13) /* Exclude file */
-#define FO_ACL (1<<14) /* Backup ACLs */
+#define FO_MD5 (1<<1) /* Do MD5 checksum */
+#define FO_GZIP (1<<2) /* Do Zlib compression */
+#define FO_NO_RECURSION (1<<3) /* no recursion in directories */
+#define FO_MULTIFS (1<<4) /* multiple file systems */
+#define FO_SPARSE (1<<5) /* do sparse file checking */
+#define FO_IF_NEWER (1<<6) /* replace if newer */
+#define FO_NOREPLACE (1<<7) /* never replace */
+#define FO_READFIFO (1<<8) /* read data from fifo */
+#define FO_SHA1 (1<<9) /* Do SHA1 checksum */
+#define FO_PORTABLE (1<<10) /* Use portable data format -- no BackupWrite */
+#define FO_MTIMEONLY (1<<11) /* Use mtime rather than mtime & ctime */
+#define FO_KEEPATIME (1<<12) /* Reset access time */
+#define FO_EXCLUDE (1<<13) /* Exclude file */
+#define FO_ACL (1<<14) /* Backup ACLs */
#define FO_NO_HARDLINK (1<<15) /* don't handle hard links */
-#define FO_IGNORECASE (1<<16) /* Ignore file name case */
-#define FO_HFSPLUS (1<<17) /* Resource forks and Finder Info */
+#define FO_IGNORECASE (1<<16) /* Ignore file name case */
+#define FO_HFSPLUS (1<<17) /* Resource forks and Finder Info */
struct s_included_file {
struct s_included_file *next;
- uint32_t options; /* backup options */
- int level; /* compression level */
- int len; /* length of fname */
- int pattern; /* set if wild card pattern */
- char VerifyOpts[20]; /* Options for verify */
+ uint32_t options; /* backup options */
+ int level; /* compression level */
+ int len; /* length of fname */
+ int pattern; /* set if wild card pattern */
+ char VerifyOpts[20]; /* Options for verify */
char fname[1];
};
* of the structure are passed by the Director to the
* File daemon and recompiled back into this structure
*/
-#undef MAX_FOPTS
+#undef MAX_FOPTS
#define MAX_FOPTS 30
enum {
/* File options structure */
struct findFOPTS {
- uint32_t flags; /* options in bits */
- int GZIP_level; /* GZIP level */
- char VerifyOpts[MAX_FOPTS]; /* verify options */
- alist regex; /* regex string(s) */
- alist regexdir; /* regex string(s) for directories */
- alist regexfile; /* regex string(s) for files */
- alist wild; /* wild card strings */
- alist wilddir; /* wild card strings for directories */
- alist wildfile; /* wild card strings for files */
- alist base; /* list of base names */
- alist fstype; /* file system type limitation */
- char *reader; /* reader program */
- char *writer; /* writer program */
+ uint32_t flags; /* options in bits */
+ int GZIP_level; /* GZIP level */
+ char VerifyOpts[MAX_FOPTS]; /* verify options */
+ alist regex; /* regex string(s) */
+ alist regexdir; /* regex string(s) for directories */
+ alist regexfile; /* regex string(s) for files */
+ alist wild; /* wild card strings */
+ alist wilddir; /* wild card strings for directories */
+ alist wildfile; /* wild card strings for files */
+ alist base; /* list of base names */
+ alist fstype; /* file system type limitation */
+ char *reader; /* reader program */
+ char *writer; /* writer program */
};
/* This is either an include item or an exclude item */
struct findINCEXE {
- findFOPTS *current_opts; /* points to current options structure */
- alist opts_list; /* options list */
- alist name_list; /* filename list -- holds char * */
+ findFOPTS *current_opts; /* points to current options structure */
+ alist opts_list; /* options list */
+ alist name_list; /* filename list -- holds char * */
};
/*
*/
struct findFILESET {
int state;
- findINCEXE *incexe; /* current item */
+ findINCEXE *incexe; /* current item */
alist include_list;
alist exclude_list;
};
#ifdef HAVE_DARWIN_OS
struct HFSPLUS_INFO {
- unsigned long length; /* Mandatory field */
- char fndrinfo[32]; /* Finder Info */
- off_t rsrclength; /* Size of resource fork */
+ unsigned long length; /* Mandatory field */
+ char fndrinfo[32]; /* Finder Info */
+ off_t rsrclength; /* Size of resource fork */
};
#endif
* first argument to the find_files callback subroutine.
*/
struct FF_PKT {
- char *fname; /* filename */
- char *link; /* link if file linked */
- POOLMEM *sys_fname; /* system filename */
- struct stat statp; /* stat packet */
- int32_t FileIndex; /* FileIndex of this file */
- int32_t LinkFI; /* FileIndex of main hard linked file */
- struct f_link *linked; /* Set if this file is hard linked */
- int type; /* FT_ type from above */
- int ff_errno; /* errno */
- BFILE bfd; /* Bacula file descriptor */
- time_t save_time; /* start of incremental time */
- bool dereference; /* follow links (not implemented) */
- bool null_output_device; /* using null output device */
- bool incremental; /* incremental save */
+ char *fname; /* filename */
+ char *link; /* link if file linked */
+ POOLMEM *sys_fname; /* system filename */
+ struct stat statp; /* stat packet */
+ int32_t FileIndex; /* FileIndex of this file */
+ int32_t LinkFI; /* FileIndex of main hard linked file */
+ struct f_link *linked; /* Set if this file is hard linked */
+ int type; /* FT_ type from above */
+ int ff_errno; /* errno */
+ BFILE bfd; /* Bacula file descriptor */
+ time_t save_time; /* start of incremental time */
+ bool dereference; /* follow links (not implemented) */
+ bool null_output_device; /* using null output device */
+ bool incremental; /* incremental save */
char VerifyOpts[20];
struct s_included_file *included_files_list;
struct s_excluded_file *excluded_files_list;
int (*callback)(FF_PKT *, void *); /* User's callback */
/* Values set by accept_file while processing Options */
- uint32_t flags; /* backup options */
- int GZIP_level; /* compression level */
- char *reader; /* reader program */
- char *writer; /* writer program */
- alist fstypes; /* allowed file system types */
+ uint32_t flags; /* backup options */
+ int GZIP_level; /* compression level */
+ char *reader; /* reader program */
+ char *writer; /* writer program */
+ alist fstypes; /* allowed file system types */
/* List of all hard linked files found */
- struct f_link *linklist; /* hard linked files */
+ struct f_link *linklist; /* hard linked files */
/* Darwin specific things. So as not to clutter every bclose()
* with an #ifdef, we always include rsrc_bfd */
- BFILE rsrc_bfd; /* fd for resource forks */
+ BFILE rsrc_bfd; /* fd for resource forks */
#ifdef HAVE_DARWIN_OS
struct HFSPLUS_INFO hfsinfo; /* Finder Info and resource fork size */
#endif
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-20054 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
*/
/*
- Copyright (C) Kern Sibbald
+ Copyright (C) 2005 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
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
bool acquired_resource_locks; /* set if resource locks acquired */
bool term_wait_inited; /* Set when cond var inited */
bool fn_printed; /* printed filename */
+ bool write_part_after_job; /* Write part after job in SD */
#endif /* DIRECTOR_DAEMON */
bool spool_data; /* set to spool data */
int CurVol; /* Current Volume count */
DIRRES* director; /* Director resource */
-
+ bool write_part_after_job; /* Set to write part after job */
+
uint32_t FileId; /* Last file id inserted */
/* Parmaters for Open Read Session */
return stat1;
}
+/*
+ * Run an external program. Optionally wait a specified number
+ * of seconds. Program killed if wait exceeded (it is done by the
+ * watchdog, as fgets is a blocking function).
+ * Return the full output from the program (not only the first line).
+ *
+ * Contrary to my normal calling conventions, this program
+ *
+ * Returns: 0 on success
+ * non-zero on error == berrno status
+ *
+ */
+int run_program_full_output(char *prog, int wait, POOLMEM *results)
+{
+ BPIPE *bpipe;
+ int stat1, stat2;
+ char *mode;
+ POOLMEM* tmp;
+
+ if (results == NULL) {
+ return run_program(prog, wait, NULL);
+ }
+
+ tmp = get_pool_memory(PM_MESSAGE);
+
+ mode = (char *)"r";
+ bpipe = open_bpipe(prog, wait, mode);
+ if (!bpipe) {
+ return ENOENT;
+ }
+
+ results[0] = 0;
+
+ while (1) {
+ fgets(tmp, sizeof_pool_memory(tmp), bpipe->rfd);
+ Dmsg1(200, "Run program fgets=%s", tmp);
+ pm_strcat(results, tmp);
+ if (feof(bpipe->rfd)) {
+ stat1 = 0;
+ Dmsg1(100, "Run program fgets stat=%d\n", stat1);
+ break;
+ } else {
+ stat1 = ferror(bpipe->rfd);
+ }
+ if (stat1 < 0) {
+ Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
+ break;
+ } else if (stat1 != 0) {
+ Dmsg1(100, "Run program fgets stat=%d\n", stat1);
+ }
+ }
+
+ stat2 = close_bpipe(bpipe);
+ stat1 = stat2 != 0 ? stat2 : stat1;
+
+ Dmsg1(100, "Run program returning %d\n", stat);
+ free_pool_memory(tmp);
+ return stat1;
+}
/*
* Build argc and argv from a string
int do_shell_expansion (char *name, int name_len);
void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
int run_program (char *prog, int wait, POOLMEM *results);
+int run_program_full_output (char *prog, int wait, POOLMEM *results);
const char * job_type_to_str (int type);
const char * job_status_to_str (int stat);
const char * job_level_to_str (int level);
* Version $Id$
*/
/*
- Copyright (C) 2002-2004 Kern Sibbald and John Walker
+ Copyright (C) 2002-2005 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
int i;
DCR *dcr = jcr->dcr;
DEVICE *dev;
-
+ int vol_label_status;
+
/* Called for each volume */
if (!dcr) {
dcr = new_dcr(jcr, jcr->device->dev);
}
bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
+ /* Volume info is always needed because of VolParts */
+ Dmsg0(200, "dir_get_volume_info\n");
+ if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
+ Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ }
+
+ dcr->dev->num_parts = dcr->VolCatInfo.VolCatParts;
+
for (i=0; i<5; i++) {
dcr->dev->state &= ~ST_LABEL; /* force reread of label */
if (job_canceled(jcr)) {
- Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
+ Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
goto get_out; /* error return */
}
/*
* If it is a tape, it checks the volume name
*/
for ( ; !(dev->state & ST_OPENED); ) {
- Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
+ Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
if (dev->dev_errno == EIO) { /* no tape loaded */
goto default_path;
}
- Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"),
+
+ /* If we have a device that requires mount,
+ * we need to try to open the label, so the info can be reported
+ * if a wrong volume has been mounted. */
+ if (dev_cap(dev, CAP_REQMOUNT) && (dcr->VolCatInfo.VolCatParts > 0)) {
+ break;
+ }
+
+ Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"),
dev_name(dev), dcr->VolumeName, strerror_dev(dev));
goto get_out;
}
- Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
+ Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
+ }
+
+ if (dev_cap(dev, CAP_REQMOUNT)) {
+ vol_label_status = read_dev_volume_label_guess(dcr, 0);
+ }
+ else {
+ vol_label_status = read_dev_volume_label(dcr);
}
+
/****FIXME***** do not reread label if ioctl() says we are
* correctly possitioned. Possibly have way user can turn
* this optimization (to be implemented) off.
*/
Dmsg0(200, "calling read-vol-label\n");
- switch (read_dev_volume_label(dcr)) {
+ switch (vol_label_status) {
case VOL_OK:
vol_ok = true;
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
* error messages when nothing is mounted.
*/
if (tape_previously_mounted) {
- Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
}
goto default_path;
case VOL_NAME_ERROR:
}
/* Fall through */
default:
- Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
default_path:
tape_previously_mounted = true;
- Dmsg0(200, "dir_get_volume_info\n");
- if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
- Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+
+ /* If the device requires mount, close it, so the device can be ejected.
+ * FIXME: This should perhaps be done for all devices. */
+ if (dev_cap(dev, CAP_REQMOUNT)) {
+ force_close_dev(dev);
}
+
/* Call autochanger only once unless ask_sysop called */
if (try_autochanger) {
int stat;
- Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
+ Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
dcr->VolumeName, dcr->VolCatInfo.Slot);
stat = autoload_device(dcr, 0, NULL);
if (stat > 0) {
continue;
}
}
+
/* Mount a specific volume and no other */
- Dmsg0(200, "calling dir_ask_sysop\n");
+ Dmsg0(200, "calling dir_ask_sysop\n");
if (!dir_ask_sysop_to_mount_volume(dcr)) {
goto get_out; /* error return */
}
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
!(dir_find_next_appendable_volume(dcr) &&
strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
- Dmsg0(190, "Wrong tape mounted.\n");
+ Dmsg0(190, "Wrong tape mounted.\n");
if (dev->num_writers != 0) {
DEVICE *d = ((DEVRES *)dev->device)->dev;
uint32_t open_vols = 0;
block_device(dev, BST_DOING_ACQUIRE);
unlock_device(dev);
} else {
- Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev));
+ Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev));
goto get_out;
}
}
/* Wrong tape mounted, release it, then fall through to get correct one */
- Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
+ Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
release = true;
do_mount = true;
} else {
* we do not need to do mount_next_write_volume(), unless
* we need to recycle the tape.
*/
- recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
- Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
+ recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
+ Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
if (recycle && dev->num_writers != 0) {
- Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
- " because it is in use by another job.\n"));
+ Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
+ " because it is in use by another job.\n"));
goto get_out;
}
if (dev->num_writers == 0) {
/* Not already in append mode, so mount the device */
Dmsg0(190, "Not in append mode, try mount.\n");
if (dev_state(dev, ST_READ)) {
- Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
+ Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
goto get_out;
}
ASSERT(dev->num_writers == 0);
P(mutex); /* re-lock */
if (!mounted) {
if (!job_canceled(jcr)) {
- /* Reduce "noise" -- don't print if job canceled */
- Jmsg(jcr, M_FATAL, 0, _("Could not ready device \"%s\" for append.\n"),
+ /* Reduce "noise" -- don't print if job canceled */
+ Jmsg(jcr, M_FATAL, 0, _("Could not ready device \"%s\" for append.\n"),
dev_name(dev));
}
goto get_out;
dev->num_writers--;
Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
if (dev_state(dev, ST_LABEL)) {
- Dmsg0(100, "dir_create_jobmedia_record. Release\n");
+ Dmsg0(100, "dir_create_jobmedia_record. Release\n");
if (!dir_create_jobmedia_record(dcr)) {
- Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
dcr->VolCatInfo.VolCatName, jcr->Job);
}
/* If no more writers, write an EOF */
dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
/* Note! do volume update before close, which zaps VolCatInfo */
- Dmsg0(100, "dir_update_vol_info. Release0\n");
+ Dmsg0(100, "dir_update_vol_info. Release0\n");
dir_update_volume_info(dcr, false); /* send Volume info to Director */
}
bpipe = open_bpipe(alert, 0, "r");
if (bpipe) {
while (fgets(line, sizeof(line), bpipe->rfd)) {
- Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
+ Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
}
status = close_bpipe(bpipe);
} else {
}
if (status != 0) {
berrno be;
- Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
+ Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
alert, be.strerror(status));
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
if (n == BNET_SIGNAL && ds->msglen == BNET_EOD) {
break; /* end of data */
}
- Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"),
+ Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"),
bnet_strerror(ds));
ok = false;
break;
p++;
}
if (!B_ISSPACE(*p) || !B_ISDIGIT(*(p+1))) {
- Jmsg1(jcr, M_FATAL, 0, _("Malformed data header from FD: %s\n"), ds->msg);
+ Jmsg1(jcr, M_FATAL, 0, _("Malformed data header from FD: %s\n"), ds->msg);
ok = false;
break;
}
if (!(file_index > 0 && (file_index == last_file_index ||
file_index == last_file_index + 1))) {
- Jmsg0(jcr, M_FATAL, 0, _("File index from FD not positive or sequential\n"));
+ Jmsg0(jcr, M_FATAL, 0, _("File index from FD not positive or sequential\n"));
ok = false;
break;
}
rec.data_len = ds->msglen;
rec.data = ds->msg; /* use message buffer */
- Dmsg4(850, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
+ Dmsg4(850, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex),
rec.data_len);
while (!write_record_to_block(dcr->block, &rec)) {
- Dmsg2(850, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
+ Dmsg2(850, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
rec.remainder);
if (!write_block_to_device(dcr)) {
- Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
+ Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(dev), strerror_dev(dev));
- Jmsg(jcr, M_FATAL, 0, _("Fatal device error: ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Fatal device error: ERR=%s\n"),
strerror_dev(dev));
ok = false;
break;
}
}
if (!ok) {
- Dmsg0(400, "Not OK\n");
+ Dmsg0(400, "Not OK\n");
break;
}
jcr->JobBytes += rec.data_len; /* increment bytes this job */
- Dmsg4(850, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
+ Dmsg4(850, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
FI_to_ascii(rec.FileIndex), rec.VolSessionId,
stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
if (are_attributes_spooled(jcr)) {
jcr->dir_bsock->spool = true;
}
- Dmsg0(850, "Send attributes to dir.\n");
+ Dmsg0(850, "Send attributes to dir.\n");
if (!dir_update_file_attributes(dcr, &rec)) {
jcr->dir_bsock->spool = false;
- Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
bnet_strerror(jcr->dir_bsock));
ok = false;
break;
jcr->dir_bsock->spool = false;
}
}
- Dmsg0(350, "Enter bnet_get\n");
+ Dmsg0(350, "Enter bnet_get\n");
}
Dmsg1(350, "End read loop with FD. Stat=%d\n", n);
if (is_bnet_error(ds)) {
- Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds));
- Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
+ Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds));
+ Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
bnet_strerror(ds));
ok = false;
break;
*/
if (ok || dev_can_write(dev)) {
if (!write_session_label(dcr, EOS_LABEL)) {
- Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
+ Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
strerror_dev(dev));
set_jcr_job_status(jcr, JS_ErrorTerminated);
ok = false;
}
if (dev->VolCatInfo.VolCatName[0] == 0) {
- Dmsg0(000, "NULL Volume name. This shouldn't happen!!!\n");
+ Dmsg0(000, "NULL Volume name. This shouldn't happen!!!\n");
}
Dmsg0(90, "back from write_end_session_label()\n");
/* Flush out final partial block of this session */
if (!write_block_to_device(dcr)) {
- Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
+ Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
set_jcr_job_status(jcr, JS_ErrorTerminated);
ok = false;
}
} else {
commit_data_spool(jcr);
}
+
+ /* If the device is nor a tape, nor a fifo, 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.
+ */
+ if (!(dcr->dev->state & (ST_TAPE|ST_FIFO)) && (jcr->write_part_after_job) && (dcr->dev->part_size > 0)) {
+ Dmsg0(100, "Writing last part because write_part_after_job is set.\n");
+ if (dcr->dev->part < dcr->dev->num_parts) {
+ Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
+ dev->part, dev->num_parts, dev_name(dev));
+ dcr->dev->dev_errno = EIO;
+ ok = false;
+ }
+
+ if (ok && (open_next_part(dcr->dev) < 0)) {
+ Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
+ dev_name(dcr->dev), strerror_dev(dcr->dev));
+ dcr->dev->dev_errno = EIO;
+ ok = false;
+ }
+
+ dcr->dev->VolCatInfo.VolCatParts = dcr->dev->num_parts;
+ }
Dmsg1(200, "calling release device JobStatus=%d\n", jcr->JobStatus);
/* Release the device */
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s"
" VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u"
" VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s"
- " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s\n";
+ " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s"
+ " VolParts=%u\n";
static char Create_job_media[] = "CatReq Job=%s CreateJobMedia"
" FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u"
" StartBlock=%u EndBlock=%u\n";
" 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";
+ " VolReadTime=%" lld " VolWriteTime=%" lld " EndFile=%u EndBlock=%u VolParts=%u";
static char OK_create[] = "1000 OK CreateJobMedia\n";
&vol.VolCatCapacityBytes, vol.VolCatStatus,
&vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles,
&InChanger, &vol.VolReadTime, &vol.VolWriteTime,
- &vol.EndFile, &vol.EndBlock);
- if (n != 19) {
+ &vol.EndFile, &vol.EndBlock, &vol.VolCatParts);
+ if (n != 20) {
Dmsg2(100, "Bad response from Dir fields=%d: %s\n", n, dir->msg);
Mmsg(jcr->errmsg, _("Error getting Volume info: %s\n"), dir->msg);
return false;
for (int vol_index=1; vol_index < 3; vol_index++) {
bnet_fsend(dir, Find_media, jcr->Job, vol_index);
if (do_get_volume_info(dcr)) {
- Dmsg2(300, "JobId=%d got possible Vol=%s\n", jcr->JobId, dcr->VolumeName);
+ Dmsg2(300, "JobId=%d got possible Vol=%s\n", jcr->JobId, dcr->VolumeName);
bool found = false;
/*
* Walk through all jobs and see if the volume is
free_locked_jcr(njcr);
continue; /* us */
}
- Dmsg2(300, "Compare to JobId=%d using Vol=%s\n", njcr->JobId, njcr->dcr->VolumeName);
+ Dmsg2(300, "Compare to JobId=%d using Vol=%s\n", njcr->JobId, njcr->dcr->VolumeName);
if (njcr->dcr && strcmp(dcr->VolumeName, njcr->dcr->VolumeName) == 0) {
found = true;
- Dmsg1(400, "Vol in use by JobId=%u\n", njcr->JobId);
+ Dmsg1(400, "Vol in use by JobId=%u\n", njcr->JobId);
free_locked_jcr(njcr);
break;
}
}
unlock_jcr_chain();
if (!found) {
- Dmsg0(400, "dir_find_next_appendable_volume return true\n");
+ Dmsg0(400, "dir_find_next_appendable_volume return true\n");
return true; /* Got good Volume */
}
} else {
- Dmsg0(200, "No volume info, return false\n");
+ Dmsg0(200, "No volume info, return false\n");
return false;
}
}
LastWritten, vol->VolCatStatus, vol->Slot, label,
InChanger, /* bool in structure */
edit_uint64(vol->VolReadTime, ed3),
- edit_uint64(vol->VolWriteTime, ed4) );
+ edit_uint64(vol->VolWriteTime, ed4),
+ vol->VolCatParts );
Dmsg1(300, "update_volume_info(): %s", dir->msg);
unbash_spaces(vol->VolCatName);
for ( ;; ) {
if (job_canceled(jcr)) {
Mmsg(dev->errmsg,
- _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
+ _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
jcr->Job, dcr->dev_name);
- Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
return false;
}
/* First pass, we *know* there are no appendable volumes, so no need to call */
if (!unmounted && ((dcr->VolumeName[0] && !dev_cap(dev, CAP_REM) &&
dev_cap(dev, CAP_LABEL)) ||
(dcr->VolumeName[0] && dcr->VolCatInfo.Slot))) {
- Dmsg0(400, "Return 1 from mount without wait.\n");
+ Dmsg0(400, "Return 1 from mount without wait.\n");
return true;
}
jstat = JS_WaitMount;
"Please mount Volume \"%s\" on Storage Device \"%s\" for Job %s\n"
"Use \"mount\" command to release Job.\n"),
dcr->VolumeName, dcr->dev_name, jcr->Job);
- Dmsg3(400, "Mount %s on %s for Job %s\n",
+ Dmsg3(400, "Mount %s on %s for Job %s\n",
dcr->VolumeName, dcr->dev_name, jcr->Job);
}
} else {
stat = wait_for_sysop(dcr);
if (dev->poll) {
- Dmsg1(400, "Poll timeout in create append vol on device %s\n", dev_name(dev));
+ Dmsg1(400, "Poll timeout in create append vol on device %s\n", dev_name(dev));
continue;
}
if (stat == ETIMEDOUT) {
if (!double_dev_wait_time(dev)) {
- Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device \"%s\" for Job %s\n"),
+ Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device \"%s\" for Job %s\n"),
dev_name(dev), jcr->Job);
- Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
- Dmsg1(400, "Gave up waiting on device %s\n", dev_name(dev));
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
+ Dmsg1(400, "Gave up waiting on device %s\n", dev_name(dev));
return false; /* exceeded maximum waits */
}
continue;
}
if (stat == EINVAL) {
berrno be;
- Mmsg2(dev->errmsg, _("pthread error in mount_next_volume stat=%d ERR=%s\n"),
+ Mmsg2(dev->errmsg, _("pthread error in mount_next_volume stat=%d ERR=%s\n"),
stat, be.strerror(stat));
- Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
return false;
}
if (stat != 0) {
berrno be;
- Jmsg(jcr, M_WARNING, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
+ Jmsg(jcr, M_WARNING, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
be.strerror(stat));
}
Dmsg1(400, "Someone woke me for device %s\n", dev_name(dev));
ASSERT(dev->dev_blocked);
for ( ;; ) {
if (job_canceled(jcr)) {
- Mmsg(dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
+ Mmsg(dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
jcr->Job, dcr->dev_name);
return false;
}
if (!dev->poll) {
- msg = _("Please mount");
- Jmsg(jcr, M_MOUNT, 0, _("%s Volume \"%s\" on Storage Device \"%s\" for Job %s\n"),
+ msg = _("Please mount");
+ Jmsg(jcr, M_MOUNT, 0, _("%s Volume \"%s\" on Storage Device \"%s\" for Job %s\n"),
msg, dcr->VolumeName, dcr->dev_name, jcr->Job);
- Dmsg3(400, "Mount \"%s\" on device \"%s\" for Job %s\n",
+ Dmsg3(400, "Mount \"%s\" on device \"%s\" for Job %s\n",
dcr->VolumeName, dcr->dev_name, jcr->Job);
}
stat = wait_for_sysop(dcr); ; /* wait on device */
if (dev->poll) {
- Dmsg1(400, "Poll timeout in mount vol on device %s\n", dev_name(dev));
- Dmsg1(400, "Blocked=%s\n", edit_blocked_reason(dev));
+ Dmsg1(400, "Poll timeout in mount vol on device %s\n", dev_name(dev));
+ Dmsg1(400, "Blocked=%s\n", edit_blocked_reason(dev));
return true;
}
if (stat == ETIMEDOUT) {
if (!double_dev_wait_time(dev)) {
- Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device \"%s\" for Job %s\n"),
+ Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device \"%s\" for Job %s\n"),
dev_name(dev), jcr->Job);
- Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
- Dmsg1(400, "Gave up waiting on device %s\n", dev_name(dev));
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
+ Dmsg1(400, "Gave up waiting on device %s\n", dev_name(dev));
return false; /* exceeded maximum waits */
}
continue;
}
if (stat == EINVAL) {
berrno be;
- Mmsg2(dev->errmsg, _("pthread error in mount_volume stat=%d ERR=%s\n"),
+ Mmsg2(dev->errmsg, _("pthread error in mount_volume stat=%d ERR=%s\n"),
stat, be.strerror(stat));
- Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
return false;
}
if (stat != 0) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
+ Jmsg(jcr, M_FATAL, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
be.strerror(stat));
}
Dmsg1(400, "Someone woke me for device %s\n", dev_name(dev));
/* send heartbeats */
if (jcr->file_bsock) {
bnet_sig(jcr->file_bsock, BNET_HEARTBEAT);
- Dmsg0(400, "Send heartbeat to FD.\n");
+ Dmsg0(400, "Send heartbeat to FD.\n");
}
if (jcr->dir_bsock) {
bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT);
break; /* on error return */
}
if (dev->rem_wait_sec <= 0) { /* on exceeding wait time return */
- Dmsg0(400, "Exceed wait time.\n");
+ Dmsg0(400, "Exceed wait time.\n");
break;
}
if (!unmounted && dev->vol_poll_interval &&
(now - first_start >= dev->vol_poll_interval)) {
- Dmsg1(400, "In wait blocked=%s\n", edit_blocked_reason(dev));
+ Dmsg1(400, "In wait blocked=%s\n", edit_blocked_reason(dev));
dev->poll = true; /* returning a poll event */
break;
}
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
block->bufp = block->buf + bhl;
if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) {
dev->dev_errno = EIO;
- Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
+ Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
dev->file, dev->block_num, BLKHDR1_ID, Id);
if (block->read_errors == 0 || verbose >= 2) {
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
}
block->read_errors++;
return false;
block->bufp = block->buf + bhl;
if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) {
dev->dev_errno = EIO;
- Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
+ Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
dev->file, dev->block_num, BLKHDR2_ID, Id);
if (block->read_errors == 0 || verbose >= 2) {
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
}
block->read_errors++;
return false;
Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
dev->file, dev->block_num, BLKHDR2_ID, Id);
if (block->read_errors == 0 || verbose >= 2) {
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
}
block->read_errors++;
unser_uint32(block->VolSessionId);
Mmsg3(dev->errmsg, _("Volume data error at %u:%u! Block length %u is insane (too large), probably due to a bad archive.\n"),
dev->file, dev->block_num, block_len);
if (block->read_errors == 0 || verbose >= 2) {
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
}
block->read_errors++;
return false;
block_len-BLKHDR_CS_LENGTH);
if (BlockCheckSum != CheckSum) {
dev->dev_errno = EIO;
- Mmsg5(dev->errmsg, _("Volume data error at %u:%u! Block checksum mismatch in block %u: calc=%x blk=%x\n"),
+ Mmsg5(dev->errmsg, _("Volume data error at %u:%u! Block checksum mismatch in block %u: calc=%x blk=%x\n"),
dev->file, dev->block_num, (unsigned)BlockNumber, BlockCheckSum, CheckSum);
if (block->read_errors == 0 || verbose >= 2) {
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
}
block->read_errors++;
if (!forge_on) {
/* Create a jobmedia record for this job */
if (!dir_create_jobmedia_record(dcr)) {
dev->dev_errno = EIO;
- Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
dcr->VolCatInfo.VolCatName, jcr->Job);
set_new_volume_parameters(dcr);
stat = false;
dev->file_size = 0; /* reset file size */
if (dev_state(dev, ST_TAPE) && weof_dev(dev, 1) != 0) { /* write eof */
- Dmsg0(190, "WEOF error in max file size.\n");
+ Dmsg0(190, "WEOF error in max file size.\n");
terminate_writing_volume(dcr);
dev->dev_errno = ENOSPC;
return false;
/* Create a JobMedia record so restore can seek */
if (!dir_create_jobmedia_record(dcr)) {
- Dmsg0(190, "Error from create_job_media.\n");
+ Dmsg0(190, "Error from create_job_media.\n");
dev->dev_errno = EIO;
- Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
dcr->VolCatInfo.VolCatName, jcr->Job);
terminate_writing_volume(dcr);
dev->dev_errno = EIO;
}
dev->VolCatInfo.VolCatFiles = dev->file;
if (!dir_update_volume_info(dcr, false)) {
- Dmsg0(190, "Error from update_vol_info.\n");
+ Dmsg0(190, "Error from update_vol_info.\n");
terminate_writing_volume(dcr);
dev->dev_errno = EIO;
return false;
/* Set new file/block parameters for current dcr */
set_new_file_parameters(dcr);
}
+
+ /* Limit maximum part size to value specified by user (not applicable to tapes/fifos) */
+ if (!(dev->state & (ST_TAPE|ST_FIFO)) &&
+ (dev->max_part_size > 0) &&
+ ((dev->part_size + block->binbuf) >= dev->max_part_size)) {
+ if (dev->part < dev->num_parts) {
+ Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
+ dev->part, dev->num_parts, dev_name(dev));
+ dev->dev_errno = EIO;
+ return false;
+ }
+
+ if (open_next_part(dev) < 0) {
+ Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ dev->dev_errno = EIO;
+ return false;
+ }
+
+ dev->VolCatInfo.VolCatParts = dev->num_parts;
+
+ if (!dir_update_volume_info(dcr, false)) {
+ Dmsg0(190, "Error from update_vol_info.\n");
+ dev->dev_errno = EIO;
+ return false;
+ }
+ }
+
+ if (dev->free_space_errno < 0) { /* Error while getting free space */
+ char ed1[50];
+ char ed2[50];
+ Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
+ dev->VolCatInfo.VolCatName,
+ dev->file, dev->block_num, dev->dev_name,
+ edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
+ dev->free_space_errno, dev->errmsg);
+ dev->dev_errno = -dev->free_space_errno;
+ return false;
+ }
+
+ if (((dev->free_space_errno > 0) && ((dev->part_size + block->binbuf) >= dev->free_space))) {
+ char ed1[50];
+ char ed2[50];
+ Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
+ Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"),
+ dev->VolCatInfo.VolCatName,
+ dev->file, dev->block_num, dev->dev_name,
+ edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
+ dev->free_space_errno);
+ terminate_writing_volume(dcr);
+ dev->dev_errno = ENOSPC;
+ return false;
+ }
dev->VolCatInfo.VolCatWrites++;
Dmsg1(300, "Write block of %u bytes\n", wlen);
dev->dev_errno = ENOSPC; /* out of space */
}
if (dev->dev_errno != ENOSPC) {
- Jmsg4(jcr, M_ERROR, 0, _("Write error at %u:%u on device %s. ERR=%s.\n"),
+ Jmsg4(jcr, M_ERROR, 0, _("Write error at %u:%u on device %s. ERR=%s.\n"),
dev->file, dev->block_num, dev->dev_name, be.strerror());
}
} else {
dev->dev_errno = ENOSPC; /* out of space */
}
if (dev->dev_errno == ENOSPC) {
- Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s. Write of %u bytes got %d.\n"),
+ Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s. Write of %u bytes got %d.\n"),
dev->VolCatInfo.VolCatName,
dev->file, dev->block_num, dev->dev_name, wlen, stat);
}
/* Now back up over what we wrote and read the last block */
if (!bsf_dev(dev, 1)) {
ok = false;
- Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
+ Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
}
if (ok && dev_cap(dev, CAP_TWOEOF) && !bsf_dev(dev, 1)) {
ok = false;
- Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
+ Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
}
/* Backspace over record */
if (ok && !bsr_dev(dev, 1)) {
ok = false;
- Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
+ Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
/*
* On FreeBSD systems, if the user got here, it is likely that his/her
- * tape drive is "frozen". The correct thing to do is a
+ * tape drive is "frozen". The correct thing to do is a
* rewind(), but if we do that, higher levels in cleaning up, will
* most likely write the EOS record over the beginning of the
* tape. The rewind *is* done later in mount.c when another
/* Note, this can destroy dev->errmsg */
dcr->block = lblock;
if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
- Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), dev->errmsg);
} else {
if (lblock->BlockNumber+1 == block->BlockNumber) {
- Jmsg(jcr, M_INFO, 0, _("Re-read of last block succeeded.\n"));
+ Jmsg(jcr, M_INFO, 0, _("Re-read of last block succeeded.\n"));
} else {
Jmsg(jcr, M_ERROR, 0, _(
"Re-read of last block failed. Last block=%u Current block=%u.\n"),
dcr->WroteVol = true;
dev->file_addr += wlen; /* update file address */
dev->file_size += wlen;
+ dev->part_size += wlen;
Dmsg2(300, "write_block: wrote block %d bytes=%d\n", dev->block_num, wlen);
empty_block(block);
if (weof_dev(dev, 1) != 0) { /* end the tape */
dev->VolCatInfo.VolCatErrors++;
Jmsg(dcr->jcr, M_ERROR, 0, "Error writing final EOF to tape. This tape may not be readable.\n"
- "%s", dev->errmsg);
+ "%s", dev->errmsg);
ok = false;
Dmsg0(100, "WEOF error.\n");
}
dev->VolCatInfo.VolCatFiles = dev->file;
+
+ if (dev_cap(dev, CAP_REQMOUNT)) { /* Write the current (and last) part. */
+ open_next_part(dev);
+ }
+
if (!dir_update_volume_info(dcr, false)) {
ok = false;
}
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
DEV_BLOCK *block = dcr->block;
-
+
if (dev_state(dev, ST_EOT)) {
return false;
}
block->read_len = 0;
return false;
}
+
+ /*Dmsg1(200, "dev.c 111->file_size=%u\n",(unsigned int)dev->file_size);
+ Dmsg1(200, "dev.c lseek=%u\n",(unsigned int)lseek(dev->fd, 0, SEEK_CUR));
+ Dmsg1(200, "dev.c dev->part_start=%u\n",(unsigned int)dev->part_start);
+ Dmsg1(200, "dev.c dev->file_size-dev->part_start=%u\n",(unsigned int)dev->file_size-dev->part_start);
+ Dmsg1(200, "dev.c dev->part_size=%u\n", (unsigned int)dev->part_size);
+ Dmsg1(200, "dev.c dev->part=%u\n", (unsigned int)dev->part);
+ Dmsg1(200, "dev.c dev->VolCatInfo.VolCatParts=%u\n", (unsigned int)dev->VolCatInfo.VolCatParts);
+ Dmsg3(200, "dev.c Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), ((dev->file_size-dev->part_start) == dev->part_size), (dev->part <= dev->VolCatInfo.VolCatParts));*/
+ /* Check for part file end */
+ if ((dev->num_parts > 0) &&
+ ((dev->file_size-dev->part_start) == dev->part_size) &&
+ (dev->part < dev->num_parts)) {
+ if (open_next_part(dev) < 0) {
+ Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ dev->dev_errno = EIO;
+ return false;
+ }
+ }
+
retry = 0;
do {
// uint32_t *bp = (uint32_t *)block->buf;
Pmsg1(000, "%s", dev->errmsg);
/* Attempt to reposition to re-read the block */
if (dev->state & ST_TAPE) {
- Dmsg0(200, "BSR for reread; block too big for buffer.\n");
+ Dmsg0(200, "BSR for reread; block too big for buffer.\n");
if (!bsr_dev(dev, 1)) {
- Jmsg(jcr, M_ERROR, 0, "%s", strerror_dev(dev));
+ Jmsg(jcr, M_ERROR, 0, "%s", strerror_dev(dev));
block->read_len = 0;
return false;
}
} else {
- Dmsg0(200, "Seek to beginning of block for reread.\n");
- off_t pos = lseek(dev->fd, (off_t)0, SEEK_CUR); /* get curr pos */
+ Dmsg0(200, "Seek to beginning of block for reread.\n");
+ off_t pos = lseek_dev(dev, (off_t)0, SEEK_CUR); /* get curr pos */
pos -= block->read_len;
- lseek(dev->fd, pos, SEEK_SET);
+ lseek_dev(dev, pos, SEEK_SET);
dev->file_addr = pos;
}
Mmsg1(dev->errmsg, _("Setting block buffer size to %u bytes.\n"), block->block_len);
*/
Dmsg0(200, "At end of read block\n");
if (block->read_len > block->block_len && !(dev->state & ST_TAPE)) {
- off_t pos = lseek(dev->fd, (off_t)0, SEEK_CUR); /* get curr pos */
+ off_t pos = lseek_dev(dev, (off_t)0, SEEK_CUR); /* get curr pos */
pos -= (block->read_len - block->block_len);
- lseek(dev->fd, pos, SEEK_SET);
+ lseek_dev(dev, pos, SEEK_SET);
Dmsg2(200, "Did lseek blk_size=%d rdlen=%d\n", block->block_len,
block->read_len);
dev->file_addr = pos;
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
/* Forward referenced functions */
void set_os_device_parameters(DEVICE *dev);
+int mount_dev(DEVICE* dev, int timeout);
+int unmount_dev(DEVICE* dev, int timeout);
+int write_part(DEVICE *dev);
+char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg);
+void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name);
+void update_free_space_dev(DEVICE* dev);
/*
* Allocate and initialize the DEVICE structure
dev->dev_errno = errno;
}
Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name,
- be.strerror());
+ be.strerror());
return NULL;
}
+
+ /* If the device requires mount :
+ * - Check that the mount point is available
+ * - Check that (un)mount commands are defined
+ */
+ if (device->cap_bits & CAP_REQMOUNT) {
+ if (stat(device->mount_point, &statp) < 0) {
+ berrno be;
+ if (dev) {
+ dev->dev_errno = errno;
+ }
+ Emsg2(M_FATAL, 0, "Unable to stat mount point %s : %s\n", device->mount_point,
+ be.strerror());
+ return NULL;
+ }
+ if (!device->mount_command || !device->unmount_command) {
+ Emsg0(M_FATAL, 0, "Mount and unmount commands must defined for a device which requires mount.\n");
+ return NULL;
+ }
+ if (!device->write_part_command) {
+ Emsg0(M_FATAL, 0, "Write part command must be defined for a device which requires mount.\n");
+ return NULL;
+ }
+ }
+
tape = false;
fifo = false;
if (S_ISDIR(statp.st_mode)) {
dev->vol_poll_interval = device->vol_poll_interval;
dev->max_spool_size = device->max_spool_size;
dev->drive_index = device->drive_index;
+ if (tape) { /* No parts on tapes */
+ dev->max_part_size = 0;
+ }
+ else {
+ dev->max_part_size = device->max_part_size;
+ }
/* Sanity check */
if (dev->vol_poll_interval && dev->vol_poll_interval < 60) {
dev->vol_poll_interval = 60;
dev->fd = -1;
dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link));
Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev_is_tape(dev), dev->dev_name);
-
+
return dev;
}
+/*
+ * Write the current volume/part filename to archive_name.
+ */
+
+void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name) {
+ char partnumber[20];
+
+ if (dev_cap(dev, CAP_REQMOUNT)) {
+ /* If we try to open the last part, just open it from disk,
+ * otherwise, open it from the spooling directory */
+ if (dev->part < dev->num_parts) {
+ pm_strcpy(archive_name, dev->device->mount_point);
+ }
+ else {
+ /* Use the working directory if spool directory is not defined */
+ if (dev->device->spool_directory) {
+ pm_strcpy(archive_name, dev->device->spool_directory);
+ } else {
+ pm_strcpy(archive_name, working_directory);
+ }
+ }
+ }
+ else {
+ pm_strcpy(archive_name, dev->dev_name);
+ }
+
+ if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
+ pm_strcat(archive_name, "/");
+ }
+ pm_strcat(archive_name, VolName);
+ /* if part != 0, append .# to the filename (where # is the part number) */
+ if (dev->part != 0) {
+ pm_strcat(archive_name, ".");
+ bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part);
+ pm_strcat(archive_name, partnumber);
+ }
+}
+
/* Open the device with the operating system and
* initialize buffer pointers.
*
int
open_dev(DEVICE *dev, char *VolName, int mode)
{
- POOLMEM *archive_name;
-
if (dev->state & ST_OPENED) {
/*
* *****FIXME***** how to handle two threads wanting
Dmsg3(29, "open_dev: tape=%d dev_name=%s vol=%s\n", dev_is_tape(dev),
dev->dev_name, dev->VolCatInfo.VolCatName);
dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
- dev->file_size = 0;
if (dev->state & (ST_TAPE|ST_FIFO)) {
+ dev->file_size = 0;
int timeout;
Dmsg0(29, "open_dev: device is tape\n");
if (mode == OPEN_READ_WRITE) {
} else if (mode == OPEN_WRITE_ONLY) {
dev->mode = O_WRONLY | O_BINARY;
} else {
- Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
+ Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
}
timeout = dev->max_open_wait;
errno = 0;
continue;
}
if (errno == EBUSY && timeout-- > 0) {
- Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, be.strerror());
+ Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, be.strerror());
bmicrosleep(1, 0);
continue;
}
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"),
+ Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"),
dev->dev_name, be.strerror());
/* Stop any open timer we set */
if (dev->tid) {
}
Dmsg1(29, "open_dev: tape %d opened\n", dev->fd);
} else {
+ POOL_MEM archive_name(PM_FNAME);
+ struct stat filestat;
/*
* Handle opening of File Archive (not a tape)
- */
+ */
+ if (dev->part == 0) {
+ dev->file_size = 0;
+ }
+ dev->part_size = 0;
+
+ /* if num_parts has not been set, but VolCatInfo is available, copy
+ * it from the VolCatInfo.VolCatParts */
+ if (dev->num_parts < dev->VolCatInfo.VolCatParts) {
+ dev->num_parts = dev->VolCatInfo.VolCatParts;
+ }
+
if (VolName == NULL || *VolName == 0) {
- Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"),
+ Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"),
dev->dev_name);
return -1;
}
- archive_name = get_pool_memory(PM_FNAME);
- pm_strcpy(archive_name, dev->dev_name);
- if (archive_name[strlen(archive_name)] != '/') {
- pm_strcat(archive_name, "/");
+ get_filename(dev, VolName, archive_name);
+
+ if (dev_cap(dev, CAP_REQMOUNT) && (dev->num_parts > 0)) {
+ if (mount_dev(dev, 1) < 0) {
+ Mmsg(dev->errmsg, _("Could not mount device %s.\n"),
+ dev->dev_name);
+ Emsg0(M_FATAL, 0, dev->errmsg);
+ dev->fd = -1;
+ return dev->fd;
+ }
}
- pm_strcat(archive_name, VolName);
- Dmsg1(29, "open_dev: device is disk %s\n", archive_name);
+
+ Dmsg2(29, "open_dev: device is disk %s (mode:%d)\n", archive_name.c_str(), mode);
+ dev->openmode = mode;
+
+ /* If we are not trying to access the last part, set mode to OPEN_READ_ONLY,
+ * as writing would be an error.
+ */
+ if (dev->part < dev->num_parts) {
+ mode = OPEN_READ_ONLY;
+ }
+
if (mode == OPEN_READ_WRITE) {
dev->mode = O_CREAT | O_RDWR | O_BINARY;
} else if (mode == OPEN_READ_ONLY) {
} else if (mode == OPEN_WRITE_ONLY) {
dev->mode = O_WRONLY | O_BINARY;
} else {
- Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
+ Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
}
/* If creating file, give 0640 permissions */
- if ((dev->fd = open(archive_name, dev->mode, 0640)) < 0) {
+ if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) {
berrno be;
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name, be.strerror());
+ Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror());
Emsg0(M_FATAL, 0, dev->errmsg);
} else {
dev->dev_errno = 0;
dev->state |= ST_OPENED;
dev->use_count = 1;
update_pos_dev(dev); /* update position */
+ if (fstat(dev->fd, &filestat) < 0) {
+ berrno be;
+ dev->dev_errno = errno;
+ Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror());
+ Emsg0(M_FATAL, 0, dev->errmsg);
+ }
+ else {
+ dev->part_size = filestat.st_size;
+ }
+ }
+ Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size);
+ if ((dev->mode != OPEN_READ_ONLY) && ((dev->free_space_errno == 0) || (dev->num_parts == dev->part))) {
+ update_free_space_dev(dev);
}
- Dmsg1(29, "open_dev: disk fd=%d opened\n", dev->fd);
- free_pool_memory(archive_name);
}
return dev->fd;
}
+/* (Un)mount the device */
+int do_mount_dev(DEVICE* dev, int mount, int dotimeout) {
+ POOL_MEM ocmd(PM_FNAME);
+ POOLMEM* results;
+ results = get_pool_memory(PM_MESSAGE);
+ char* icmd;
+ int status, timeout;
+
+ if (mount) {
+ icmd = dev->device->mount_command;
+ }
+ else {
+ icmd = dev->device->unmount_command;
+ }
+
+ edit_device_codes_dev(dev, ocmd.c_str(), icmd);
+
+ Dmsg2(29, "do_mount_dev: cmd=%s state=%d\n", ocmd.c_str(), dev->state & ST_MOUNTED);
+
+ if (dotimeout) {
+ /* Try at most 5 times to (un)mount the device. This should perhaps be configurable. */
+ timeout = 5;
+ }
+ else {
+ timeout = 0;
+ }
+ /* If busy retry each second */
+ while ((status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results)) != 0) {
+ if (--timeout > 0) {
+ Dmsg2(40, "Device %s cannot be (un)mounted. Retrying... ERR=%s\n", dev->dev_name, results);
+ /* Sometimes the device cannot be mounted because it is already mounted.
+ * Try to unmount it, then remount it */
+ if (mount) {
+ Dmsg1(40, "Trying to unmount the device %s...\n", dev->dev_name);
+ do_mount_dev(dev, 0, 0);
+ }
+ bmicrosleep(1, 0);
+ continue;
+ }
+ free_pool_memory(results);
+ Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->dev_name, results);
+ return -1;
+ }
+
+ if (mount) {
+ dev->state |= ST_MOUNTED;
+ }
+ else {
+ dev->state &= ~ST_MOUNTED;
+ }
+ free_pool_memory(results);
+
+ Dmsg1(29, "do_mount_dev: end_state=%d\n", dev->state & ST_MOUNTED);
+ return 0;
+}
+
+/* Only for devices that requires mount.
+ * Try to find the volume name of the loaded device, and open the
+ * first part of this volume.
+ *
+ * Returns 0 if read_dev_volume_label can now read the label,
+ * -1 if an error occured, and read_dev_volume_label_guess must abort with an IO_ERROR.
+ *
+ * To guess the device name, it lists all the files on the DVD, and searches for a
+ * file which has a minimum size (500 bytes). If this file has a numeric extension,
+ * like part files, try to open the file which has no extension (e.g. the first
+ * part file).
+ * So, if the DVD does not contains a Bacula volume, a random file is opened,
+ * and no valid label could be read from this file.
+ */
+int open_guess_name_dev(DEVICE *dev) {
+ Dmsg1(29, "open_guess_name_dev: dev=%s\n", dev->dev_name);
+ POOL_MEM guessedname(PM_FNAME);
+ DIR* dp;
+ struct dirent *entry, *result;
+ struct stat statp;
+ int index;
+ int name_max;
+
+ if (!dev_cap(dev, CAP_REQMOUNT)) {
+ Dmsg1(100, "open_guess_name_dev: device does not require mount, returning 0. dev=%s\n", dev->dev_name);
+ return 0;
+ }
+
+#ifndef HAVE_DIRENT_H
+ Dmsg0(29, "open_guess_name_dev: readdir not available, cannot guess volume name\n");
+ return 0;
+#endif
+
+ update_free_space_dev(dev);
+
+ if (mount_dev(dev, 1) < 0) {
+ /* If the device cannot be mounted, check if it is writable */
+ if (dev->free_space_errno >= 0) {
+ Dmsg1(100, "open_guess_name_dev: device cannot be mounted, but it seems to be writable, returning 0. dev=%s\n", dev->dev_name);
+ return 0;
+ }
+ else {
+ Dmsg1(100, "open_guess_name_dev: device cannot be mounted, and is not writable, returning 0. dev=%s\n", dev->dev_name);
+ /* read_dev_volume_label_guess must now check dev->free_space_errno to understand that the media is not writable. */
+ return 0;
+ }
+ }
+
+ name_max = pathconf(".", _PC_NAME_MAX);
+ if (name_max < 1024) {
+ name_max = 1024;
+ }
+
+ if (!(dp = opendir(dev->device->mount_point))) {
+ berrno be;
+ dev->dev_errno = errno;
+ Dmsg3(29, "open_guess_name_dev: failed to open dir %s (dev=%s), ERR=%s\n", dev->device->mount_point, dev->dev_name, be.strerror());
+ return -1;
+ }
+
+ entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
+ while (1) {
+ if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
+ dev->dev_errno = ENOENT;
+ Dmsg2(29, "open_guess_name_dev: failed to find suitable file in dir %s (dev=%s)\n", dev->device->mount_point, dev->dev_name);
+ closedir(dp);
+ return -1;
+ }
+
+ ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
+
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+ continue;
+ }
+
+ pm_strcpy(guessedname, dev->device->mount_point);
+ if (guessedname.c_str()[strlen(guessedname.c_str())-1] != '/') {
+ pm_strcat(guessedname, "/");
+ }
+ pm_strcat(guessedname, entry->d_name);
+
+ if (stat(guessedname.c_str(), &statp) < 0) {
+ berrno be;
+ Dmsg3(29, "open_guess_name_dev: failed to stat %s (dev=%s), ERR=%s\n",
+ guessedname.c_str(), dev->dev_name, be.strerror());
+ continue;
+ }
+
+ if (!S_ISREG(statp.st_mode) || (statp.st_size < 500)) {
+ Dmsg2(100, "open_guess_name_dev: %s is not a regular file, or less than 500 bytes (dev=%s)\n",
+ guessedname.c_str(), dev->dev_name);
+ continue;
+ }
+
+ /* Ok, we found a good file, remove the part extension if possible. */
+ for (index = strlen(guessedname.c_str())-1; index >= 0; index--) {
+ if ((guessedname.c_str()[index] == '/') ||
+ (guessedname.c_str()[index] < '0') ||
+ (guessedname.c_str()[index] > '9')) {
+ break;
+ }
+ if (guessedname.c_str()[index] == '.') {
+ guessedname.c_str()[index] = '\0';
+ break;
+ }
+ }
+
+ if ((stat(guessedname.c_str(), &statp) < 0) || (statp.st_size < 500)) {
+ /* The file with extension truncated does not exists or is too small, so use it with its extension. */
+ berrno be;
+ Dmsg3(100, "open_guess_name_dev: failed to stat %s (dev=%s), using the file with its extension, ERR=%s\n",
+ guessedname.c_str(), dev->dev_name, be.strerror());
+ pm_strcpy(guessedname, dev->device->mount_point);
+ if (guessedname.c_str()[strlen(guessedname.c_str())-1] != '/') {
+ pm_strcat(guessedname, "/");
+ }
+ pm_strcat(guessedname, entry->d_name);
+ continue;
+ }
+ break;
+ }
+
+ closedir(dp);
+
+ if (dev->fd >= 0) {
+ close(dev->fd);
+ }
+
+ if ((dev->fd = open(guessedname.c_str(), O_RDONLY | O_BINARY)) < 0) {
+ berrno be;
+ dev->dev_errno = errno;
+ Dmsg3(29, "open_guess_name_dev: failed to open %s (dev=%s), ERR=%s\n",
+ guessedname.c_str(), dev->dev_name, be.strerror());
+ if (open_first_part(dev) < 0) {
+ berrno be;
+ dev->dev_errno = errno;
+ Mmsg1(&dev->errmsg, _("Could not open_first_part, ERR=%s\n"), be.strerror());
+ Emsg0(M_FATAL, 0, dev->errmsg);
+ }
+ return -1;
+ }
+ dev->part_start = 0;
+ dev->part_size = statp.st_size;
+ dev->part = 0;
+ dev->state |= ST_OPENED;
+ dev->use_count = 1;
+
+ Dmsg2(29, "open_guess_name_dev: %s opened (dev=%s)\n", guessedname.c_str(), dev->dev_name);
+
+ return 0;
+}
+
+/* Mount the device.
+ * If timeout, wait until the mount command returns 0.
+ * If !timeout, try to mount the device only once.
+ */
+int mount_dev(DEVICE* dev, int timeout) {
+ if (dev->state & ST_MOUNTED) {
+ Dmsg0(100, "mount_dev: Device already mounted\n");
+ return 0;
+ }
+ else {
+ return do_mount_dev(dev, 1, timeout);
+ }
+}
+
+/* Unmount the device
+ * If timeout, wait until the unmount command returns 0.
+ * If !timeout, try to unmount the device only once.
+ */
+int unmount_dev(DEVICE* dev, int timeout) {
+ if (dev->state & ST_MOUNTED) {
+ return do_mount_dev(dev, 0, timeout);
+ }
+ else {
+ Dmsg0(100, "mount_dev: Device already unmounted\n");
+ return 0;
+ }
+}
+
+/* Update the free space on the device */
+void update_free_space_dev(DEVICE* dev) {
+ POOL_MEM ocmd(PM_FNAME);
+ POOLMEM* results;
+ char* icmd;
+ int timeout;
+ char* statstr;
+ long long int free;
+
+ icmd = dev->device->free_space_command;
+
+ if (!icmd) {
+ dev->free_space = 0;
+ dev->free_space_errno = 0;
+ Dmsg2(29, "update_free_space_dev: free_space=%d, free_space_errno=%d (!icmd)\n", dev->free_space, dev->free_space_errno);
+ return;
+ }
+
+ edit_device_codes_dev(dev, ocmd.c_str(), icmd);
+
+ Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
+
+ results = get_pool_memory(PM_MESSAGE);
+
+ /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */
+ timeout = 3;
+
+ while (1) {
+ if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
+ Dmsg1(100, "Free space program run : %s\n", results);
+ /* We also need negatives values, so we can't use dev->free_space, which is unsigned */
+ free = strtoll(results, &statstr, 10);
+ if (results != statstr) { /* Something parsed */
+ if (free >= 0) {
+ dev->free_space = free;
+ dev->free_space_errno = 1;
+ Mmsg0(dev->errmsg, "");
+ break;
+ }
+ else {
+ dev->free_space_errno = free;
+ dev->free_space = 0;
+ if (*statstr == '\n') {
+ statstr++;
+ }
+ if (statstr[strlen(statstr)-1] == '\n') {
+ statstr[strlen(statstr)-1] = 0;
+ }
+ Mmsg1(dev->errmsg, "Error while getting free space (%s)", statstr);
+ }
+ }
+ else {
+ dev->free_space = 0;
+ dev->free_space_errno = -EPIPE;
+ Mmsg1(dev->errmsg, "Error while getting free space (output=%s)", results);
+ }
+ }
+ else {
+ dev->free_space = 0;
+ dev->free_space_errno = -EPIPE;
+ Mmsg1(dev->errmsg, "Cannot run free space command (%s)", results);
+ }
+
+ if (--timeout > 0) {
+ Dmsg4(40, "Cannot get free space on device %s. free_space=%lld, free_space_errno=%d ERR=%s\n", dev->dev_name,
+ dev->free_space, dev->free_space_errno, dev->errmsg);
+ bmicrosleep(1, 0);
+ continue;
+ }
+
+ dev->dev_errno = -dev->free_space_errno;
+ Dmsg4(40, "Cannot get free space on device %s. free_space=%lld, free_space_errno=%d ERR=%s\n",
+ dev->dev_name, dev->free_space, dev->free_space_errno, dev->errmsg);
+ free_pool_memory(results);
+ return;
+ }
+
+ free_pool_memory(results);
+
+ Dmsg2(29, "update_free_space_dev: free_space=%lld, free_space_errno=%d\n", dev->free_space, dev->free_space_errno);
+}
+
+int write_part(DEVICE *dev) {
+ Dmsg1(29, "write_part: device is %s\n", dev->dev_name);
+
+ if (unmount_dev(dev, 1) < 0) {
+ Dmsg0(29, "write_part: unable to unmount the device\n");
+ }
+
+ POOL_MEM ocmd(PM_FNAME);
+ POOLMEM *results;
+ results = get_pool_memory(PM_MESSAGE);
+ char* icmd;
+ int status;
+ int timeout;
+
+ icmd = dev->device->write_part_command;
+
+ edit_device_codes_dev(dev, ocmd.c_str(), icmd);
+
+ /* Wait at most the time a maximum size part is written in DVD 0.5x speed
+ * FIXME: Minimum speed should be in device configuration
+ */
+ timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
+
+ Dmsg2(29, "write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
+
+ status = run_program_full_output(ocmd.c_str(), timeout, results);
+ if (status != 0) {
+ Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s", results);
+ dev->dev_errno = EIO;
+ free_pool_memory(results);
+ return -1;
+ }
+ else {
+ Dmsg1(29, "write_part: command output=%s\n", results);
+ POOL_MEM archive_name(PM_FNAME);
+ get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+ unlink(archive_name.c_str());
+ free_pool_memory(results);
+ return 0;
+ }
+}
+
+/* Open the next part file.
+ * - Close the fd
+ * - Increment part number
+ * - Reopen the device
+ */
+int open_next_part(DEVICE *dev) {
+ int state;
+
+ Dmsg3(29, "open_next_part %s %s %d\n", dev->dev_name, dev->VolCatInfo.VolCatName, dev->openmode);
+ /* When appending, do not open a new part if the current is empty */
+ if ((dev->state & ST_APPEND) && (dev->part == dev->num_parts) && (dev->part_size == 0)) {
+ Dmsg0(29, "open_next_part exited immediatly (dev->part_size == 0).\n");
+ return dev->fd;
+ }
+
+ if (dev->fd >= 0) {
+ close(dev->fd);
+ }
+
+ dev->fd = -1;
+
+ state = dev->state;
+ dev->state &= ~ST_OPENED;
+
+ if ((dev_cap(dev, CAP_REQMOUNT)) && (dev->part == dev->num_parts) && (dev->state & ST_APPEND)) {
+ if (write_part(dev) < 0) {
+ return -1;
+ }
+ }
+
+ dev->part_start += dev->part_size;
+ dev->part++;
+
+ if ((dev->num_parts < dev->part) && (dev->state & ST_APPEND)) {
+ dev->num_parts = dev->part;
+
+ /* Check that the next part file does not exists.
+ * If it does, move it away... */
+ POOL_MEM archive_name(PM_FNAME);
+ POOL_MEM archive_bkp_name(PM_FNAME);
+ struct stat buf;
+
+ get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+
+ /* Check if the next part exists. */
+ if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
+ Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
+ pm_strcpy(archive_bkp_name, archive_name.c_str());
+ pm_strcat(archive_bkp_name, ".bak");
+ unlink(archive_bkp_name.c_str());
+
+ /* First try to rename it */
+ if (rename(archive_name.c_str(), archive_bkp_name.c_str()) < 0) {
+ berrno be;
+ Dmsg3(29, "open_next_part can't rename %s to %s, ERR=%s\n",
+ archive_name.c_str(), archive_bkp_name.c_str(), be.strerror());
+ /* Then try to unlink it */
+ if (unlink(archive_name.c_str()) < 0) {
+ berrno be;
+ dev->dev_errno = errno;
+ Mmsg2(&dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"),
+ archive_name.c_str(), be.strerror());
+ Emsg0(M_FATAL, 0, dev->errmsg);
+ return -1;
+ }
+ }
+ }
+ }
+
+ if (open_dev(dev, dev->VolCatInfo.VolCatName, dev->openmode) < 0) {
+ return -1;
+ }
+ else {
+ dev->state = state;
+ return dev->fd;
+ }
+}
+
+/* Open the first part file.
+ * - Close the fd
+ * - Reopen the device
+ */
+int open_first_part(DEVICE *dev) {
+ int state;
+
+ Dmsg3(29, "open_first_part %s %s %d\n", dev->dev_name, dev->VolCatInfo.VolCatName, dev->openmode);
+ if (dev->fd >= 0) {
+ close(dev->fd);
+ }
+
+ dev->fd = -1;
+ state = dev->state;
+ dev->state &= ~ST_OPENED;
+
+ dev->part_start = 0;
+ dev->part = 0;
+
+ if (open_dev(dev, dev->VolCatInfo.VolCatName, dev->openmode)) {
+ dev->state = state;
+ return dev->fd;
+ }
+ else {
+ return 0;
+ }
+}
+
#ifdef debug_tracing
#undef rewind_dev
bool _rewind_dev(char *file, int line, DEVICE *dev)
}
#endif
+/* Protected version of lseek, which opens the right part if necessary */
+off_t lseek_dev(DEVICE *dev, off_t offset, int whence) {
+ int pos, openmode;
+
+ if (dev->num_parts == 0) { /* If there is only one part, simply call lseek. */
+ return lseek(dev->fd, offset, whence);
+ }
+
+ switch(whence) {
+ case SEEK_SET:
+ Dmsg1(100, "lseek_dev SEEK_SET called %d\n", offset);
+ if ((uint64_t)offset >= dev->part_start) {
+ if ((uint64_t)(offset - dev->part_start) < dev->part_size) {
+ /* We are staying in the current part, just seek */
+ if ((pos = lseek(dev->fd, (off_t)(offset-dev->part_start), SEEK_SET)) < 0) {
+ return pos;
+ }
+ else {
+ return pos + dev->part_start;
+ }
+ }
+ else {
+ /* Load next part, and start again */
+ if (open_next_part(dev) < 0) {
+ Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
+ return -1;
+ }
+ return lseek_dev(dev, offset, SEEK_SET);
+ }
+ }
+ else {
+ /* pos < dev->part_start :
+ * We need to access a previous part,
+ * so just load the first one, and seek again
+ * until the right one is loaded */
+ if (open_first_part(dev) < 0) {
+ Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
+ return -1;
+ }
+ return lseek_dev(dev, offset, SEEK_SET);
+ }
+ break;
+ case SEEK_CUR:
+ Dmsg1(100, "lseek_dev SEEK_CUR called %d\n", offset);
+ if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
+ return pos;
+ }
+ pos += dev->part_start;
+ if (offset == 0) {
+ return pos;
+ }
+ else { /* Not used in Bacula, but should work */
+ return lseek_dev(dev, pos, SEEK_SET);
+ }
+ break;
+ case SEEK_END:
+ Dmsg1(100, "lseek_dev SEEK_END called %d\n", offset);
+ if (offset > 0) { /* Not used by bacula */
+ Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", offset);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (dev->part == dev->num_parts) { /* The right part is already loaded */
+ if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
+ return pos;
+ }
+ else {
+ return pos + dev->part_start;
+ }
+ }
+ else {
+ /* Load the first part, then load the next until we reach the last one.
+ * This is the only way to be sure we compute the right file address. */
+ /* Save previous openmode, and open all but last part read-only (useful for DVDs) */
+ openmode = dev->openmode;
+ dev->openmode = OPEN_READ_ONLY;
+
+ /* Works because num_parts > 0. */
+ if (open_first_part(dev) < 0) {
+ Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
+ return -1;
+ }
+ while (dev->part < (dev->num_parts-1)) {
+ if (open_next_part(dev) < 0) {
+ Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
+ return -1;
+ }
+ }
+ dev->openmode = openmode;
+ if (open_next_part(dev) < 0) {
+ Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
+ return -1;
+ }
+ return lseek_dev(dev, 0, SEEK_END);
+ }
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
/*
* Rewind the device.
berrno be;
clrerror_dev(dev, MTREW);
if (i == dev->max_rewind_wait) {
- Dmsg1(200, "Rewind error, %s. retrying ...\n", be.strerror());
+ Dmsg1(200, "Rewind error, %s. retrying ...\n", be.strerror());
}
if (dev->dev_errno == EIO && i > 0) {
- Dmsg0(200, "Sleeping 5 seconds.\n");
+ Dmsg0(200, "Sleeping 5 seconds.\n");
bmicrosleep(5, 0);
continue;
}
- Mmsg2(&dev->errmsg, _("Rewind error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("Rewind error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return false;
}
break;
}
- } else if (dev->state & ST_FILE) {
- if (lseek(dev->fd, (off_t)0, SEEK_SET) < 0) {
+ } else if (dev->state & ST_FILE) {
+ if (lseek_dev(dev, (off_t)0, SEEK_SET) < 0) {
berrno be;
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return false;
}
return 1;
}
if (!(dev->state & ST_TAPE)) {
- pos = lseek(dev->fd, (off_t)0, SEEK_END);
+ pos = lseek_dev(dev, (off_t)0, SEEK_END);
// Dmsg1(100, "====== Seek to %lld\n", pos);
if (pos >= 0) {
update_pos_dev(dev);
}
dev->dev_errno = errno;
berrno be;
- Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return 0;
}
if (dev_cap(dev, CAP_MTIOCGET) && (dev_cap(dev, CAP_FASTFSF) || dev_cap(dev, CAP_EOM))) {
if (dev_cap(dev, CAP_EOM)) {
- Dmsg0(100,"Using EOM for EOM\n");
+ Dmsg0(100,"Using EOM for EOM\n");
mt_com.mt_op = MTEOM;
mt_com.mt_count = 1;
}
if ((stat=ioctl(dev->fd, MTIOCTOP, (char *)&mt_com)) < 0) {
berrno be;
clrerror_dev(dev, mt_com.mt_op);
- Dmsg1(50, "ioctl error: %s\n", be.strerror());
+ Dmsg1(50, "ioctl error: %s\n", be.strerror());
update_pos_dev(dev);
- Mmsg2(&dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return 0;
}
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
berrno be;
clrerror_dev(dev, -1);
- Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return 0;
}
*/
int file_num;
for (file_num=dev->file; !(dev->state & ST_EOT); file_num++) {
- Dmsg0(200, "eod_dev: doing fsf 1\n");
+ Dmsg0(200, "eod_dev: doing fsf 1\n");
if (!fsf_dev(dev, 1)) {
- Dmsg0(200, "fsf_dev error.\n");
+ Dmsg0(200, "fsf_dev error.\n");
return 0;
}
/*
*/
if (file_num == (int)dev->file) {
struct mtget mt_stat;
- Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num);
+ Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num);
if (dev_cap(dev, CAP_MTIOCGET) && ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 &&
mt_stat.mt_fileno >= 0) {
- Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
+ Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
dev->file = mt_stat.mt_fileno;
}
stat = 0;
stat = bsf_dev(dev, 1);
/* If BSF worked and fileno is known (not -1), set file */
if (dev_cap(dev, CAP_MTIOCGET) && ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) {
- Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
+ Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
dev->file = mt_stat.mt_fileno;
} else {
dev->file++; /* wing it -- not correct on all OSes */
if (dev->state & ST_FILE) {
dev->file = 0;
dev->file_addr = 0;
- pos = lseek(dev->fd, (off_t)0, SEEK_CUR);
+ pos = lseek_dev(dev, (off_t)0, SEEK_CUR);
if (pos < 0) {
berrno be;
dev->dev_errno = errno;
- Pmsg1(000, "Seek error: ERR=%s\n", be.strerror());
- Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
+ Pmsg1(000, "Seek error: ERR=%s\n", be.strerror());
+ Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
ok = false;
} else {
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
berrno be;
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return 0;
}
#if defined(HAVE_LINUX_OS)
if (GMT_EOF(mt_stat.mt_gstat)) {
stat |= BMT_EOF;
- Dmsg0(-20, " EOF");
+ Dmsg0(-20, " EOF");
}
if (GMT_BOT(mt_stat.mt_gstat)) {
stat |= BMT_BOT;
- Dmsg0(-20, " BOT");
+ Dmsg0(-20, " BOT");
}
if (GMT_EOT(mt_stat.mt_gstat)) {
stat |= BMT_EOT;
- Dmsg0(-20, " EOT");
+ Dmsg0(-20, " EOT");
}
if (GMT_SM(mt_stat.mt_gstat)) {
stat |= BMT_SM;
- Dmsg0(-20, " SM");
+ Dmsg0(-20, " SM");
}
if (GMT_EOD(mt_stat.mt_gstat)) {
stat |= BMT_EOD;
- Dmsg0(-20, " EOD");
+ Dmsg0(-20, " EOD");
}
if (GMT_WR_PROT(mt_stat.mt_gstat)) {
stat |= BMT_WR_PROT;
- Dmsg0(-20, " WR_PROT");
+ Dmsg0(-20, " WR_PROT");
}
if (GMT_ONLINE(mt_stat.mt_gstat)) {
stat |= BMT_ONLINE;
- Dmsg0(-20, " ONLINE");
+ Dmsg0(-20, " ONLINE");
}
if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
stat |= BMT_DR_OPEN;
- Dmsg0(-20, " DR_OPEN");
+ Dmsg0(-20, " DR_OPEN");
}
if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
stat |= BMT_IM_REP_EN;
- Dmsg0(-20, " IM_REP_EN");
+ Dmsg0(-20, " IM_REP_EN");
}
#endif /* !SunOS && !OSF */
if (dev_cap(dev, CAP_MTIOCGET)) {
- Dmsg2(-20, " file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
+ Dmsg2(-20, " file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
} else {
- Dmsg2(-20, " file=%d block=%d\n", -1, -1);
+ Dmsg2(-20, " file=%d block=%d\n", -1, -1);
}
} else {
stat |= BMT_ONLINE | BMT_BOT;
dev->block_num = dev->file = 0;
dev->file_size = 0;
dev->file_addr = 0;
+ dev->part = 0;
#ifdef MTUNLOCK
mt_com.mt_op = MTUNLOCK;
mt_com.mt_count = 1;
if (stat < 0 || ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
berrno be;
dev->state |= ST_EOT;
- Dmsg0(200, "Set ST_EOT\n");
+ Dmsg0(200, "Set ST_EOT\n");
clrerror_dev(dev, MTFSF);
- Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- Dmsg1(200, "%s", dev->errmsg);
+ Dmsg1(200, "%s", dev->errmsg);
return false;
}
Dmsg2(200, "fsf file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
mt_com.mt_op = MTFSF;
mt_com.mt_count = 1;
while (num-- && !(dev->state & ST_EOT)) {
- Dmsg0(100, "Doing read before fsf\n");
+ Dmsg0(100, "Doing read before fsf\n");
if ((stat = read(dev->fd, (char *)rbuf, rbuf_len)) < 0) {
if (errno == ENOMEM) { /* tape record exceeds buf len */
stat = rbuf_len; /* This is OK */
berrno be;
dev->state |= ST_EOT;
clrerror_dev(dev, -1);
- Dmsg2(100, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno,
+ Dmsg2(100, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno,
be.strerror());
- Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- Dmsg1(100, "%s", dev->errmsg);
+ Dmsg1(100, "%s", dev->errmsg);
break;
}
}
if (stat == 0) { /* EOF */
update_pos_dev(dev);
- Dmsg1(100, "End of File mark from read. File=%d\n", dev->file+1);
+ Dmsg1(100, "End of File mark from read. File=%d\n", dev->file+1);
/* Two reads of zero means end of tape */
if (dev->state & ST_EOF) {
dev->state |= ST_EOT;
- Dmsg0(100, "Set ST_EOT\n");
+ Dmsg0(100, "Set ST_EOT\n");
break;
} else {
dev->state |= ST_EOF;
dev->state &= ~(ST_EOF|ST_EOT);
}
- Dmsg0(100, "Doing MTFSF\n");
+ Dmsg0(100, "Doing MTFSF\n");
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0) { /* error => EOT */
berrno be;
dev->state |= ST_EOT;
- Dmsg0(100, "Set ST_EOT\n");
+ Dmsg0(100, "Set ST_EOT\n");
clrerror_dev(dev, MTFSF);
- Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
+ Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- Dmsg0(100, "Got < 0 for MTFSF\n");
- Dmsg1(100, "%s", dev->errmsg);
+ Dmsg0(100, "Got < 0 for MTFSF\n");
+ Dmsg1(100, "%s", dev->errmsg);
} else {
dev->state |= ST_EOF; /* just read EOF */
dev->file++;
}
if (dev->state & ST_EOT) {
dev->dev_errno = 0;
- Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
stat = -1;
} else {
stat = 0;
clrerror_dev(dev, MTFSR);
Dmsg1(100, "FSF fail: ERR=%s\n", be.strerror());
if (dev_cap(dev, CAP_MTIOCGET) && ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) {
- Dmsg4(100, "Adjust from %d:%d to %d:%d\n", dev->file,
+ Dmsg4(100, "Adjust from %d:%d to %d:%d\n", dev->file,
dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno);
dev->file = mt_stat.mt_fileno;
dev->block_num = mt_stat.mt_blkno;
if (!(dev_state(dev, ST_TAPE))) {
off_t pos = (((off_t)file)<<32) + block;
- Dmsg1(100, "===== lseek to %d\n", (int)pos);
- if (lseek(dev->fd, pos, SEEK_SET) == (off_t)-1) {
+ Dmsg1(100, "===== lseek_dev to %d\n", (int)pos);
+ if (lseek_dev(dev, pos, SEEK_SET) == (off_t)-1) {
berrno be;
dev->dev_errno = errno;
- Mmsg2(dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
return false;
}
if (file > dev->file) {
Dmsg1(100, "fsf %d\n", file-dev->file);
if (!fsf_dev(dev, file-dev->file)) {
- Dmsg1(100, "fsf failed! ERR=%s\n", strerror_dev(dev));
+ Dmsg1(100, "fsf failed! ERR=%s\n", strerror_dev(dev));
return false;
}
Dmsg2(100, "wanted_file=%d at_file=%d\n", file, dev->file);
{
struct mtop mt_com;
int stat;
-
+ Dmsg0(29, "weof_dev\n");
+
if (dev->fd < 0) {
dev->dev_errno = EBADF;
Mmsg0(dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n"));
return 0;
}
dev->state &= ~(ST_EOT | ST_EOF); /* remove EOF/EOT flags */
- Dmsg0(29, "weof_dev\n");
mt_com.mt_op = MTWEOF;
mt_com.mt_count = num;
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
berrno be;
clrerror_dev(dev, MTWEOF);
if (stat == -1) {
- Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
}
}
if (errno == ENOTTY || errno == ENOSYS) { /* Function not implemented */
switch (func) {
case -1:
- Emsg0(M_ABORT, 0, "Got ENOTTY on read/write!\n");
+ Emsg0(M_ABORT, 0, "Got ENOTTY on read/write!\n");
break;
case MTWEOF:
- msg = "WTWEOF";
+ msg = "WTWEOF";
dev->capabilities &= ~CAP_EOF; /* turn off feature */
break;
#ifdef MTEOM
case MTEOM:
- msg = "WTEOM";
+ msg = "WTEOM";
dev->capabilities &= ~CAP_EOM; /* turn off feature */
break;
#endif
case MTFSF:
- msg = "MTFSF";
+ msg = "MTFSF";
dev->capabilities &= ~CAP_FSF; /* turn off feature */
break;
case MTBSF:
- msg = "MTBSF";
+ msg = "MTBSF";
dev->capabilities &= ~CAP_BSF; /* turn off feature */
break;
case MTFSR:
- msg = "MTFSR";
+ msg = "MTFSR";
dev->capabilities &= ~CAP_FSR; /* turn off feature */
break;
case MTBSR:
- msg = "MTBSR";
+ msg = "MTBSR";
dev->capabilities &= ~CAP_BSR; /* turn off feature */
break;
default:
- msg = "Unknown";
+ msg = "Unknown";
break;
}
if (msg != NULL) {
dev->dev_errno = ENOSYS;
- Mmsg1(&dev->errmsg, _("This device does not support %s.\n"), msg);
+ Mmsg1(&dev->errmsg, _("This device does not support %s.\n"), msg);
Emsg0(M_ERROR, 0, dev->errmsg);
}
}
if (dev->fd >= 0) {
close(dev->fd);
}
+ if (dev_cap(dev, CAP_REQMOUNT)) {
+ if (unmount_dev(dev, 1) < 0) {
+ Dmsg1(0, "Cannot unmount device %s.\n", dev->dev_name);
+ }
+ }
+
+ /* Remove the last part file if it is empty */
+ if ((dev->state & ST_APPEND) && (dev->num_parts > 0)) {
+ struct stat statp;
+ POOL_MEM archive_name(PM_FNAME);
+ dev->part = dev->num_parts;
+ get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+ /* Check that the part file is empty */
+ if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) {
+ unlink(archive_name.c_str());
+ }
+ }
+
/* Clean up device packet so it can be reused */
dev->fd = -1;
dev->state &= ~(ST_OPENED|ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
dev->file = dev->block_num = 0;
dev->file_size = 0;
dev->file_addr = 0;
+ dev->part = 0;
+ dev->part_size = 0;
+ dev->part_start = 0;
dev->EndFile = dev->EndBlock = 0;
memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
Emsg0(M_FATAL, 0, dev->errmsg);
return;
}
- if (dev->fd >= 0 && dev->use_count == 1) {
+ /*if (dev->fd >= 0 && dev->use_count == 1) {*/
+ /* No need to check if dev->fd >= 0: it is checked again
+ * in do_close, and do_close MUST be called for volumes
+ * splitted in parts, even if dev->fd == -1. */
+ if (dev->use_count == 1) {
do_close(dev);
} else if (dev->use_count > 0) {
dev->use_count--;
bool truncate_dev(DEVICE *dev)
{
+ Dmsg1(100, "truncate_dev %s\n", dev->dev_name);
if (dev->state & ST_TAPE) {
return true; /* we don't really truncate tapes */
/* maybe we should rewind and write and eof ???? */
}
+
+ /* If there is more than one part, open the first one, and then truncate it. */
+ if (dev->num_parts > 0) {
+ dev->num_parts = 0;
+ dev->VolCatInfo.VolCatParts = 0;
+ if (open_first_part(dev) < 0) {
+ berrno be;
+ Mmsg1(&dev->errmsg, "Unable to truncate device, because I'm unable to open the first part. ERR=%s\n", be.strerror());
+ }
+ }
+
if (ftruncate(dev->fd, 0) != 0) {
berrno be;
Mmsg1(&dev->errmsg, _("Unable to truncate device. ERR=%s\n"), be.strerror());
return;
#endif
}
+
+/*
+ * Edit codes into (Un)MountCommand, Write(First)PartCommand
+ * %% = %
+ * %a = archive device name
+ * %m = mount point
+ * %v = last part name
+ *
+ * omsg = edited output message
+ * imsg = input string containing edit codes (%x)
+ *
+ */
+char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg)
+{
+ const char *p;
+ const char *str;
+ char add[20];
+
+ POOL_MEM archive_name(PM_FNAME);
+ get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+
+ *omsg = 0;
+ Dmsg1(800, "edit_device_codes: %s\n", imsg);
+ for (p=imsg; *p; p++) {
+ if (*p == '%') {
+ switch (*++p) {
+ case '%':
+ str = "%";
+ break;
+ case 'n':
+ bsnprintf(add, sizeof(add), "%d", dev->part);
+ str = add;
+ break;
+ case 'a':
+ str = dev->dev_name;
+ break;
+ case 'm':
+ str = dev->device->mount_point;
+ break;
+ case 'v':
+ str = archive_name.c_str();
+ break;
+ default:
+ add[0] = '%';
+ add[1] = *p;
+ add[2] = 0;
+ str = add;
+ break;
+ }
+ } else {
+ add[0] = *p;
+ add[1] = 0;
+ str = add;
+ }
+ Dmsg1(900, "add_str %s\n", str);
+ pm_strcat(&omsg, (char *)str);
+ Dmsg1(800, "omsg=%s\n", omsg);
+ }
+ return omsg;
+}
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
#ifndef __DEV_H
#define __DEV_H 1
-#undef DCR /* used by Bacula */
+#undef DCR /* used by Bacula */
/* #define NEW_LOCK 1 */
-#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
+#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
#define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state))
-#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
+#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
#define lock_device(d) _lock_device(__FILE__, __LINE__, (d))
#define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d))
};
/* Generic status bits returned from status_dev() */
-#define BMT_TAPE (1<<0) /* is tape device */
-#define BMT_EOF (1<<1) /* just read EOF */
-#define BMT_BOT (1<<2) /* at beginning of tape */
-#define BMT_EOT (1<<3) /* end of tape reached */
-#define BMT_SM (1<<4) /* DDS setmark */
-#define BMT_EOD (1<<5) /* DDS at end of data */
-#define BMT_WR_PROT (1<<6) /* tape write protected */
-#define BMT_ONLINE (1<<7) /* tape online */
-#define BMT_DR_OPEN (1<<8) /* tape door open */
-#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */
+#define BMT_TAPE (1<<0) /* is tape device */
+#define BMT_EOF (1<<1) /* just read EOF */
+#define BMT_BOT (1<<2) /* at beginning of tape */
+#define BMT_EOT (1<<3) /* end of tape reached */
+#define BMT_SM (1<<4) /* DDS setmark */
+#define BMT_EOD (1<<5) /* DDS at end of data */
+#define BMT_WR_PROT (1<<6) /* tape write protected */
+#define BMT_ONLINE (1<<7) /* tape online */
+#define BMT_DR_OPEN (1<<8) /* tape door open */
+#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */
/* Test capabilities */
#define dev_cap(dev, cap) ((dev)->capabilities & (cap))
/* Bits for device capabilities */
-#define CAP_EOF (1<<0) /* has MTWEOF */
-#define CAP_BSR (1<<1) /* has MTBSR */
-#define CAP_BSF (1<<2) /* has MTBSF */
-#define CAP_FSR (1<<3) /* has MTFSR */
-#define CAP_FSF (1<<4) /* has MTFSF */
-#define CAP_EOM (1<<5) /* has MTEOM */
-#define CAP_REM (1<<6) /* is removable media */
-#define CAP_RACCESS (1<<7) /* is random access device */
-#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */
-#define CAP_LABEL (1<<9) /* Label blank tapes */
-#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */
-#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */
+#define CAP_EOF (1<<0) /* has MTWEOF */
+#define CAP_BSR (1<<1) /* has MTBSR */
+#define CAP_BSF (1<<2) /* has MTBSF */
+#define CAP_FSR (1<<3) /* has MTFSR */
+#define CAP_FSF (1<<4) /* has MTFSF */
+#define CAP_EOM (1<<5) /* has MTEOM */
+#define CAP_REM (1<<6) /* is removable media */
+#define CAP_RACCESS (1<<7) /* is random access device */
+#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */
+#define CAP_LABEL (1<<9) /* Label blank tapes */
+#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */
+#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */
#define CAP_AUTOCHANGER (1<<12) /* AutoChanger */
#define CAP_OFFLINEUNMOUNT (1<<13) /* Offline before unmount */
-#define CAP_STREAM (1<<14) /* Stream device */
-#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */
-#define CAP_FASTFSF (1<<16) /* Fast forward space file */
-#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */
+#define CAP_STREAM (1<<14) /* Stream device */
+#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */
+#define CAP_FASTFSF (1<<16) /* Fast forward space file */
+#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */
#define CAP_CLOSEONPOLL (1<<18) /* Close device on polling */
#define CAP_POSITIONBLOCKS (1<<19) /* Use block positioning */
-#define CAP_MTIOCGET (1<<20) /* Basic support for fileno and blkno */
+#define CAP_MTIOCGET (1<<20) /* Basic support for fileno and blkno */
+#define CAP_REQMOUNT (1<<21) /* Require mount to read files back (typically: DVD) */
/* Test state */
#define dev_state(dev, st_state) ((dev)->state & (st_state))
/* Device state bits */
-#define ST_OPENED (1<<0) /* set when device opened */
-#define ST_TAPE (1<<1) /* is a tape device */
-#define ST_FILE (1<<2) /* is a file device */
-#define ST_FIFO (1<<3) /* is a fifo device */
-#define ST_PROG (1<<4) /* is a program device */
-#define ST_LABEL (1<<5) /* label found */
+#define ST_OPENED (1<<0) /* set when device opened */
+#define ST_TAPE (1<<1) /* is a tape device */
+#define ST_FILE (1<<2) /* is a file device */
+#define ST_FIFO (1<<3) /* is a fifo device */
+#define ST_PROG (1<<4) /* is a program device */
+#define ST_LABEL (1<<5) /* label found */
#define ST_MALLOC (1<<6) /* dev packet malloc'ed in init_dev() */
-#define ST_APPEND (1<<7) /* ready for Bacula append */
-#define ST_READ (1<<8) /* ready for Bacula read */
-#define ST_EOT (1<<9) /* at end of tape */
-#define ST_WEOT (1<<10) /* Got EOT on write */
-#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */
-#define ST_NEXTVOL (1<<12) /* Start writing on next volume */
-#define ST_SHORT (1<<13) /* Short block read */
+#define ST_APPEND (1<<7) /* ready for Bacula append */
+#define ST_READ (1<<8) /* ready for Bacula read */
+#define ST_EOT (1<<9) /* at end of tape */
+#define ST_WEOT (1<<10) /* Got EOT on write */
+#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */
+#define ST_NEXTVOL (1<<12) /* Start writing on next volume */
+#define ST_SHORT (1<<13) /* Short block read */
+#define ST_MOUNTED (1<<14) /* the device is mounted to the mount point */
/* dev_blocked states (mutually exclusive) */
enum {
- BST_NOT_BLOCKED = 0, /* not blocked */
- BST_UNMOUNTED, /* User unmounted device */
- BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */
- BST_DOING_ACQUIRE, /* Opening/validating/moving tape */
- BST_WRITING_LABEL, /* Labeling a tape */
+ BST_NOT_BLOCKED = 0, /* not blocked */
+ BST_UNMOUNTED, /* User unmounted device */
+ BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */
+ BST_DOING_ACQUIRE, /* Opening/validating/moving tape */
+ BST_WRITING_LABEL, /* Labeling a tape */
BST_UNMOUNTED_WAITING_FOR_SYSOP, /* Closed by user during mount request */
- BST_MOUNT /* Mount request */
+ BST_MOUNT /* Mount request */
};
/* Volume Catalog Information structure definition */
struct VOLUME_CAT_INFO {
/* Media info for the current Volume */
- uint32_t VolCatJobs; /* number of jobs on this Volume */
- uint32_t VolCatFiles; /* Number of files */
- uint32_t VolCatBlocks; /* Number of blocks */
- uint64_t VolCatBytes; /* Number of bytes written */
- uint32_t VolCatMounts; /* Number of mounts this volume */
- uint32_t VolCatErrors; /* Number of errors this volume */
- uint32_t VolCatWrites; /* Number of writes this volume */
- uint32_t VolCatReads; /* Number of reads this volume */
- uint64_t VolCatRBytes; /* Number of bytes read */
- uint32_t VolCatRecycles; /* Number of recycles this volume */
- uint32_t EndFile; /* Last file number */
- uint32_t EndBlock; /* Last block number */
- int32_t Slot; /* Slot in changer */
- bool InChanger; /* Set if vol in current magazine */
- uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */
- uint32_t VolCatMaxFiles; /* Maximum files to write to volume */
- uint64_t VolCatMaxBytes; /* Max bytes to write to volume */
+ uint32_t VolCatJobs; /* number of jobs on this Volume */
+ uint32_t VolCatFiles; /* Number of files */
+ uint32_t VolCatBlocks; /* Number of blocks */
+ uint64_t VolCatBytes; /* Number of bytes written */
+ uint32_t VolCatParts; /* Number of parts written */
+ uint32_t VolCatMounts; /* Number of mounts this volume */
+ uint32_t VolCatErrors; /* Number of errors this volume */
+ uint32_t VolCatWrites; /* Number of writes this volume */
+ uint32_t VolCatReads; /* Number of reads this volume */
+ uint64_t VolCatRBytes; /* Number of bytes read */
+ uint32_t VolCatRecycles; /* Number of recycles this volume */
+ uint32_t EndFile; /* Last file number */
+ uint32_t EndBlock; /* Last block number */
+ int32_t Slot; /* Slot in changer */
+ bool InChanger; /* Set if vol in current magazine */
+ uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */
+ uint32_t VolCatMaxFiles; /* Maximum files to write to volume */
+ uint64_t VolCatMaxBytes; /* Max bytes to write to volume */
uint64_t VolCatCapacityBytes; /* capacity estimate */
- uint64_t VolReadTime; /* time spent reading */
- uint64_t VolWriteTime; /* time spent writing this Volume */
- char VolCatStatus[20]; /* Volume status */
+ uint64_t VolReadTime; /* time spent reading */
+ uint64_t VolWriteTime; /* time spent writing this Volume */
+ char VolCatStatus[20]; /* Volume status */
char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */
};
typedef struct s_steal_lock {
- pthread_t no_wait_id; /* id of no wait thread */
- int dev_blocked; /* state */
- int dev_prev_blocked; /* previous blocked state */
+ pthread_t no_wait_id; /* id of no wait thread */
+ int dev_blocked; /* state */
+ int dev_prev_blocked; /* previous blocked state */
} bsteal_lock_t;
-struct DEVRES; /* Device resource defined in stored_conf.h */
+struct DEVRES; /* Device resource defined in stored_conf.h */
/*
* Device structure definition. There is one of these for
*/
struct DEVICE {
public:
- DEVICE *next; /* pointer to next open device */
- DEVICE *prev; /* pointer to prev open device */
- JCR *attached_jcrs; /* attached JCR list */
- dlist *attached_dcrs; /* attached DCR list */
- pthread_mutex_t mutex; /* access control */
+ DEVICE *next; /* pointer to next open device */
+ DEVICE *prev; /* pointer to prev open device */
+ JCR *attached_jcrs; /* attached JCR list */
+ dlist *attached_dcrs; /* attached DCR list */
+ pthread_mutex_t mutex; /* access control */
pthread_mutex_t spool_mutex; /* mutex for updating spool_size */
- pthread_cond_t wait; /* thread wait variable */
+ pthread_cond_t wait; /* thread wait variable */
pthread_cond_t wait_next_vol; /* wait for tape to be mounted */
- pthread_t no_wait_id; /* this thread must not wait */
- int dev_blocked; /* set if we must wait (i.e. change tape) */
- int dev_prev_blocked; /* previous blocked state */
- int num_waiting; /* number of threads waiting */
- int num_writers; /* number of writing threads */
+ pthread_t no_wait_id; /* this thread must not wait */
+ int dev_blocked; /* set if we must wait (i.e. change tape) */
+ int dev_prev_blocked; /* previous blocked state */
+ int num_waiting; /* number of threads waiting */
+ int num_writers; /* number of writing threads */
/* New access control in process of being implemented */
- brwlock_t lock; /* New mutual exclusion lock */
+ brwlock_t lock; /* New mutual exclusion lock */
- int use_count; /* usage count on this device */
- int fd; /* file descriptor */
- int capabilities; /* capabilities mask */
- int state; /* state mask */
- int dev_errno; /* Our own errno */
- int mode; /* read/write modes */
- uint32_t drive_index; /* Autochanger drive index */
- POOLMEM *dev_name; /* device name */
- char *errmsg; /* nicely edited error message */
- uint32_t block_num; /* current block number base 0 */
- uint32_t file; /* current file number base 0 */
- uint64_t file_addr; /* Current file read/write address */
- uint64_t file_size; /* Current file size */
- uint32_t EndBlock; /* last block written */
- uint32_t EndFile; /* last file written */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint64_t max_volume_size; /* max bytes to put on one volume */
- uint64_t max_file_size; /* max file size to put in one file on volume */
- uint64_t volume_capacity; /* advisory capacity */
- uint64_t max_spool_size; /* maximum spool file size */
- uint64_t spool_size; /* curren spool size */
- uint32_t max_rewind_wait; /* max secs to allow for rewind */
- uint32_t max_open_wait; /* max secs to allow for open */
- uint32_t max_open_vols; /* max simultaneous open volumes */
- utime_t vol_poll_interval; /* interval between polling Vol mount */
- DEVRES *device; /* pointer to Device Resource */
- btimer_t *tid; /* timer id */
+ int use_count; /* usage count on this device */
+ int fd; /* file descriptor */
+ int capabilities; /* capabilities mask */
+ int state; /* state mask */
+ int dev_errno; /* Our own errno */
+ int mode; /* read/write modes */
+ int openmode; /* parameter passed to open_dev (useful to reopen the device) */
+ uint32_t drive_index; /* Autochanger drive index */
+ POOLMEM *dev_name; /* device name */
+ char *errmsg; /* nicely edited error message */
+ uint32_t block_num; /* current block number base 0 */
+ uint32_t file; /* current file number base 0 */
+ uint64_t file_addr; /* Current file read/write address */
+ uint64_t file_size; /* Current file size */
+ uint32_t EndBlock; /* last block written */
+ uint32_t EndFile; /* last file written */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint64_t max_volume_size; /* max bytes to put on one volume */
+ uint64_t max_file_size; /* max file size to put in one file on volume */
+ uint64_t volume_capacity; /* advisory capacity */
+ uint64_t max_spool_size; /* maximum spool file size */
+ uint64_t spool_size; /* current spool size */
+ uint32_t max_rewind_wait; /* max secs to allow for rewind */
+ uint32_t max_open_wait; /* max secs to allow for open */
+ uint32_t max_open_vols; /* max simultaneous open volumes */
+
+ uint64_t max_part_size; /* max part size */
+ uint64_t part_size; /* current part size */
+ uint32_t part; /* current part number */
+ uint64_t part_start; /* current part start address (relative to the whole volume) */
+ uint32_t num_parts; /* number of parts (total) */
+ uint64_t free_space; /* current free space on medium (without the current part) */
+ int free_space_errno; /* indicates:
+ * - free_space_errno == 0: ignore free_space.
+ * - free_space_errno < 0: an error occured.
+ * - free_space_errno > 0: free_space is valid. */
+
+ utime_t vol_poll_interval; /* interval between polling Vol mount */
+ DEVRES *device; /* pointer to Device Resource */
+ btimer_t *tid; /* timer id */
- VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
- VOLUME_LABEL VolHdr; /* Actual volume label */
+ VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
+ VOLUME_LABEL VolHdr; /* Actual volume label */
/* Device wait times ***FIXME*** look at durations */
char BadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */
- bool poll; /* set to poll Volume */
+ bool poll; /* set to poll Volume */
int min_wait;
int max_wait;
int max_num_wait;
*/
class DCR {
public:
- dlink dev_link; /* link to attach to dev */
- JCR *jcr; /* pointer to JCR */
- DEVICE *dev; /* pointer to device */
- DEV_BLOCK *block; /* pointer to block */
- DEV_RECORD *rec; /* pointer to record */
- int spool_fd; /* fd if spooling */
- bool spool_data; /* set to spool data */
- bool spooling; /* set when actually spooling */
- bool dev_locked; /* set if dev already locked */
- bool NewVol; /* set if new Volume mounted */
- bool WroteVol; /* set if Volume written */
- bool NewFile; /* set when EOF written */
- uint32_t VolFirstIndex; /* First file index this Volume */
- uint32_t VolLastIndex; /* Last file index this Volume */
- uint32_t FileIndex; /* Current File Index */
- uint32_t EndFile; /* End file written */
- uint32_t StartFile; /* Start write file */
- uint32_t StartBlock; /* Start write block */
- uint32_t EndBlock; /* Ending block written */
- int64_t spool_size; /* Current spool size */
- int64_t max_spool_size; /* Max job spool size */
+ dlink dev_link; /* link to attach to dev */
+ JCR *jcr; /* pointer to JCR */
+ DEVICE *dev; /* pointer to device */
+ DEV_BLOCK *block; /* pointer to block */
+ DEV_RECORD *rec; /* pointer to record */
+ int spool_fd; /* fd if spooling */
+ bool spool_data; /* set to spool data */
+ bool spooling; /* set when actually spooling */
+ bool dev_locked; /* set if dev already locked */
+ bool NewVol; /* set if new Volume mounted */
+ bool WroteVol; /* set if Volume written */
+ bool NewFile; /* set when EOF written */
+ uint32_t VolFirstIndex; /* First file index this Volume */
+ uint32_t VolLastIndex; /* Last file index this Volume */
+ uint32_t FileIndex; /* Current File Index */
+ uint32_t EndFile; /* End file written */
+ uint32_t StartFile; /* Start write file */
+ uint32_t StartBlock; /* Start write block */
+ uint32_t EndBlock; /* Ending block written */
+ int64_t spool_size; /* Current spool size */
+ int64_t max_spool_size; /* Max job spool size */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
char pool_name[MAX_NAME_LENGTH]; /* pool name */
char pool_type[MAX_NAME_LENGTH]; /* pool type */
char media_type[MAX_NAME_LENGTH]; /* media type */
char dev_name[MAX_NAME_LENGTH]; /* dev name */
- VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
+ VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
};
* dependent. Arrgggg!
*/
#ifndef MTEOM
-#ifdef MTSEOD
+#ifdef MTSEOD
#define MTEOM MTSEOD
#endif
#ifdef MTEOD
*
*/
/*
- Copyright (C) 2001-2004 Kern Sibbald and John Walker
+ Copyright (C) 2001-2005 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
for (i=0; cmds[i].cmd; i++) {
if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
- Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd);
+ Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd);
bnet_fsend(bs, illegal_cmd);
bnet_sig(bs, BNET_EOD);
break;
}
if (!cmds[i].func(jcr)) { /* do command */
quit = true; /* error, get out */
- Dmsg1(190, "Command %s requsts quit\n", cmds[i].cmd);
+ Dmsg1(190, "Command %s requsts quit\n", cmds[i].cmd);
}
found = true; /* indicate command found */
break;
if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
if (!(jcr=get_jcr_by_full_name(Job))) {
- bnet_fsend(dir, _("3992 Job %s not found.\n"), Job);
+ bnet_fsend(dir, _("3992 Job %s not found.\n"), Job);
} else {
P(jcr->mutex);
oldStatus = jcr->JobStatus;
jcr->dcr->dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
pthread_cond_signal(&jcr->dcr->dev->wait_next_vol);
}
- bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job);
+ bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job);
free_jcr(jcr);
}
} else {
if (!(dev->state & ST_OPENED)) {
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
force_close_dev(dev);
- /* Under certain "safe" conditions, we can steal the lock */
+ /* Under certain "safe" conditions, we can steal the lock */
} else if (dev->dev_blocked &&
(dev->dev_blocked == BST_UNMOUNTED ||
dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
} else if (dev_state(dev, ST_READ) || dev->num_writers) {
if (dev_state(dev, ST_READ)) {
- bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"),
+ bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"),
dev_name(dev));
} else {
- bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"),
+ bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"),
dev_name(dev), dev->num_writers);
}
} else { /* device not being used */
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
/* See what we have for a Volume */
label_status = read_dev_volume_label(dcr);
+
+ if (dev_cap(dev, CAP_REQMOUNT)) {
+ label_status = read_dev_volume_label_guess(dcr, 1);
+ }
+ else {
+ label_status = read_dev_volume_label(dcr);
+ }
+
switch(label_status) {
case VOL_NAME_ERROR:
case VOL_VERSION_ERROR:
case VOL_OK:
if (!relabel) {
bnet_fsend(dir, _(
- "3911 Cannot label Volume because it is already labeled: \"%s\"\n"),
+ "3911 Cannot label Volume because it is already labeled: \"%s\"\n"),
dev->VolHdr.VolName);
break;
}
/* Relabel request. If oldname matches, continue */
if (strcmp(oldname, dev->VolHdr.VolName) != 0) {
- bnet_fsend(dir, _("Wrong volume mounted.\n"));
+ bnet_fsend(dir, _("Wrong volume mounted.\n"));
break;
}
/* Fall through wanted! */
case VOL_IO_ERROR:
case VOL_NO_LABEL:
if (!write_new_volume_label_to_dev(dcr, newname, poolname)) {
- bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
+ bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
break;
}
bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
foreach_res(device, R_DEVICE) {
/* Find resource, and make sure we were able to open it */
if (strcmp(device->hdr.name, dname.c_str()) == 0 && device->dev) {
- Dmsg1(20, "Found device %s\n", device->hdr.name);
+ Dmsg1(20, "Found device %s\n", device->hdr.name);
jcr->device = device;
found = true;
break;
switch (dev->dev_blocked) { /* device blocked? */
case BST_WAITING_FOR_SYSOP:
/* Someone is waiting, wake him */
- Dmsg0(100, "Waiting for mount. Attempting to wake thread\n");
+ Dmsg0(100, "Waiting for mount. Attempting to wake thread\n");
dev->dev_blocked = BST_MOUNT;
- bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev_name(dev));
+ bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev_name(dev));
pthread_cond_signal(&dev->wait_next_vol);
break;
case BST_UNMOUNTED:
/* We freed the device, so reopen it and wake any waiting threads */
if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
- bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
+ bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
break;
}
read_dev_volume_label(dcr);
if (dev->dev_blocked == BST_UNMOUNTED) {
/* We blocked the device, so unblock it */
- Dmsg0(100, "Unmounted. Unblocking device\n");
+ Dmsg0(100, "Unmounted. Unblocking device\n");
read_label(dcr); /* this should not be necessary */
unblock_device(dev);
} else {
- Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n");
+ Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n");
dev->dev_blocked = BST_MOUNT;
}
if (dev_state(dev, ST_LABEL)) {
- bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
+ bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
dev_name(dev), dev->VolHdr.VolName);
} else {
- bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
- "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
+ bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
+ "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
dev_name(dev));
}
pthread_cond_signal(&dev->wait_next_vol);
break;
case BST_DOING_ACQUIRE:
- bnet_fsend(dir, _("3001 Device %s is mounted; doing acquire.\n"),
+ bnet_fsend(dir, _("3001 Device %s is mounted; doing acquire.\n"),
dev_name(dev));
break;
case BST_WRITING_LABEL:
- bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev_name(dev));
break;
case BST_NOT_BLOCKED:
if (dev_state(dev, ST_OPENED)) {
if (dev_state(dev, ST_LABEL)) {
- bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
+ bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
dev_name(dev), dev->VolHdr.VolName);
} else {
- bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
- "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
+ bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
+ "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
dev_name(dev));
}
} else {
if (!dev_is_tape(dev)) {
- bnet_fsend(dir, _("3906 cannot mount non-tape.\n"));
+ bnet_fsend(dir, _("3906 cannot mount non-tape.\n"));
break;
}
if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
- bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
+ bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
break;
}
read_label(dcr);
if (dev_state(dev, ST_LABEL)) {
- bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
+ bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
dev_name(dev), dev->VolHdr.VolName);
} else {
- bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
- "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
+ bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
+ "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
dev_name(dev));
}
}
break;
default:
- bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked);
+ bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked);
break;
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
pm_strcpy(jcr->errmsg, dir->msg);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!(dev->state & ST_OPENED)) {
- Dmsg0(90, "Device already unmounted\n");
- bnet_fsend(dir, _("3901 Device \"%s\" is already unmounted.\n"), dev_name(dev));
+ Dmsg0(90, "Device already unmounted\n");
+ bnet_fsend(dir, _("3901 Device \"%s\" is already unmounted.\n"), dev_name(dev));
} else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
- Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
+ Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
open_dev(dev, NULL, 0); /* fake open for close */
offline_or_rewind_dev(dev);
force_close_dev(dev);
dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
- bnet_fsend(dir, _("3001 Device \"%s\" unmounted.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3001 Device \"%s\" unmounted.\n"), dev_name(dev));
} else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
- bnet_fsend(dir, _("3902 Device \"%s\" is busy in acquire.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3902 Device \"%s\" is busy in acquire.\n"), dev_name(dev));
} else if (dev->dev_blocked == BST_WRITING_LABEL) {
- bnet_fsend(dir, _("3903 Device \"%s\" is being labeled.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3903 Device \"%s\" is being labeled.\n"), dev_name(dev));
} else if (dev_state(dev, ST_READ) || dev->num_writers) {
if (dev_state(dev, ST_READ)) {
- Dmsg0(90, "Device in read mode\n");
- bnet_fsend(dir, _("3904 Device \"%s\" is busy reading.\n"), dev_name(dev));
+ Dmsg0(90, "Device in read mode\n");
+ bnet_fsend(dir, _("3904 Device \"%s\" is busy reading.\n"), dev_name(dev));
} else {
- Dmsg1(90, "Device busy with %d writers\n", dev->num_writers);
- bnet_fsend(dir, _("3905 Device %s is busy with %d writer(s).\n"),
+ Dmsg1(90, "Device busy with %d writers\n", dev->num_writers);
+ bnet_fsend(dir, _("3905 Device %s is busy with %d writer(s).\n"),
dev_name(dev), dev->num_writers);
}
} else { /* device not being used */
- Dmsg0(90, "Device not in use, unmounting\n");
+ Dmsg0(90, "Device not in use, unmounting\n");
/* On FreeBSD, I am having ASSERT() failures in block_device()
* and I can only imagine that the thread id that we are
* leaving in no_wait_id is being re-used. So here,
open_dev(dev, NULL, 0); /* fake open for close */
offline_or_rewind_dev(dev);
force_close_dev(dev);
- bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev_name(dev));
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!(dev->state & ST_OPENED)) {
- Dmsg0(90, "Device already released\n");
- bnet_fsend(dir, _("3911 Device %s already released.\n"), dev_name(dev));
+ Dmsg0(90, "Device already released\n");
+ bnet_fsend(dir, _("3911 Device %s already released.\n"), dev_name(dev));
} else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
- Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
+ Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
- bnet_fsend(dir, _("3912 Device %s waiting for mount.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3912 Device %s waiting for mount.\n"), dev_name(dev));
} else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
- bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"), dev_name(dev));
} else if (dev->dev_blocked == BST_WRITING_LABEL) {
- bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), dev_name(dev));
} else if (dev_state(dev, ST_READ) || dev->num_writers) {
if (dev_state(dev, ST_READ)) {
- Dmsg0(90, "Device in read mode\n");
- bnet_fsend(dir, _("3915 Device %s is busy with 1 reader.\n"), dev_name(dev));
+ Dmsg0(90, "Device in read mode\n");
+ bnet_fsend(dir, _("3915 Device %s is busy with 1 reader.\n"), dev_name(dev));
} else {
- Dmsg1(90, "Device busy with %d writers\n", dev->num_writers);
- bnet_fsend(dir, _("3916 Device %s is busy with %d writer(s).\n"),
+ Dmsg1(90, "Device busy with %d writers\n", dev->num_writers);
+ bnet_fsend(dir, _("3916 Device %s is busy with %d writer(s).\n"),
dev_name(dev), dev->num_writers);
}
} else { /* device not being used */
- Dmsg0(90, "Device not in use, unmounting\n");
+ Dmsg0(90, "Device not in use, unmounting\n");
release_volume(jcr->dcr);
- bnet_fsend(dir, _("3012 Device %s released.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3012 Device %s released.\n"), dev_name(dev));
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev_is_tape(dev)) {
- bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev_name(dev));
} else if (!(dev->state & ST_OPENED)) {
autochanger_list(dcr, dir);
- /* Under certain "safe" conditions, we can steal the lock */
+ /* Under certain "safe" conditions, we can steal the lock */
} else if (dev->dev_blocked &&
(dev->dev_blocked == BST_UNMOUNTED ||
dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
autochanger_list(dcr, dir);
} else if (dev_state(dev, ST_READ) || dev->num_writers) {
if (dev_state(dev, ST_READ)) {
- bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), dev_name(dev));
+ bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), dev_name(dev));
} else {
- bnet_fsend(dir, _("3902 Device %s is busy with %d writer(s).\n"),
+ bnet_fsend(dir, _("3902 Device %s is busy with %d writer(s).\n"),
dev_name(dev), dev->num_writers);
}
} else { /* device not being used */
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else { /* error on scanf */
pm_strcpy(jcr->errmsg, dir->msg);
if (!dev_state(dev, ST_OPENED)) {
read_volume_label(jcr, dev, Slot);
force_close_dev(dev);
- /* Under certain "safe" conditions, we can steal the lock */
+ /* Under certain "safe" conditions, we can steal the lock */
} else if (dev->dev_blocked &&
(dev->dev_blocked == BST_UNMOUNTED ||
dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
read_volume_label(jcr, dev, Slot);
} else if (dev_state(dev, ST_READ) || dev->num_writers) {
if (dev_state(dev, ST_READ)) {
- bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"),
+ bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"),
dev_name(dev));
} else {
- bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"),
+ bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"),
dev_name(dev), dev->num_writers);
}
} else { /* device not being used */
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
pm_strcpy(jcr->errmsg, dir->msg);
/* Ensure that the device is open -- autoload_device() closes it */
for ( ; !(dev->state & ST_OPENED); ) {
if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) {
- bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"),
+ bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
return false;
}
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
/* Requests from the Director daemon */
static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
- "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
- "SpoolData=%d";
+ "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
+ "SpoolData=%d WritePartAfterJob=%d";
static char use_device[] = "use device=%127s media_type=%127s pool_name=%127s pool_type=%127s\n";
static char use_devices[] = "use devices=%127s media_type=%127s pool_name=%127s pool_type=%127s\n";
char auth_key[100];
BSOCK *dir = jcr->dir_bsock;
POOL_MEM job_name, client_name, job, fileset_name, fileset_md5;
- int JobType, level, spool_attributes, no_attributes, spool_data;
+ int JobType, level, spool_attributes, no_attributes, spool_data, write_part_after_job;
struct timeval tv;
struct timezone tz;
struct timespec timeout;
if (sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(),
client_name.c_str(),
&JobType, &level, fileset_name.c_str(), &no_attributes,
- &spool_attributes, fileset_md5.c_str(), &spool_data) != 11) {
+ &spool_attributes, fileset_md5.c_str(), &spool_data, &write_part_after_job) != 12) {
pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, BAD_job, jcr->errmsg);
Emsg1(M_FATAL, 0, _("Bad Job Command from Director: %s\n"), jcr->errmsg);
jcr->no_attributes = no_attributes;
jcr->spool_attributes = spool_attributes;
jcr->spool_data = spool_data;
+ jcr->write_part_after_job = write_part_after_job;
jcr->fileset_md5 = get_pool_memory(PM_NAME);
pm_strcpy(jcr->fileset_md5, fileset_md5);
while (!quit) {
bool ok;
if (bnet_recv(dir) <= 0) {
- Jmsg0(jcr, M_FATAL, 0, _("No Device from Director\n"));
+ Jmsg0(jcr, M_FATAL, 0, _("No Device from Director\n"));
return false;
}
if (!dcr) {
return false;
}
- Dmsg1(120, "Found device %s\n", device->hdr.name);
+ Dmsg1(120, "Found device %s\n", device->hdr.name);
bstrncpy(dcr->pool_name, pool_name, name_len);
bstrncpy(dcr->pool_type, pool_type, name_len);
bstrncpy(dcr->media_type, media_type, name_len);
bstrncpy(dcr->dev_name, dev_name, name_len);
jcr->device = device;
- Dmsg1(220, "Got: %s", dir->msg);
+ Dmsg1(220, "Got: %s", dir->msg);
return bnet_fsend(dir, OK_device);
}
}
if (verbose) {
unbash_spaces(dir->msg);
pm_strcpy(jcr->errmsg, dir->msg);
- Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
+ Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
}
- Jmsg(jcr, M_FATAL, 0, _("\n"
- " Device \"%s\" with MediaType \"%s\" requested by Dir not found in SD Device resources.\n"),
+ Jmsg(jcr, M_FATAL, 0, _("\n"
+ " Device \"%s\" with MediaType \"%s\" requested by Dir not found in SD Device resources.\n"),
dev_name.c_str(), media_type.c_str());
bnet_fsend(dir, NO_device, dev_name.c_str());
} else {
unbash_spaces(dir->msg);
pm_strcpy(jcr->errmsg, dir->msg);
if (verbose) {
- Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
+ Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
}
- Jmsg(jcr, M_FATAL, 0, _("Bad Use Device command: %s\n"), jcr->errmsg);
+ Jmsg(jcr, M_FATAL, 0, _("Bad Use Device command: %s\n"), jcr->errmsg);
bnet_fsend(dir, BAD_use, jcr->errmsg);
}
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
if (dev_state(dev, ST_LABEL)) { /* did we already read label? */
/* Compare Volume Names allow special wild card */
if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) {
- Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
+ Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
dev_name(dev), VolName, dev->VolHdr.VolName);
/*
* Cancel Job if too many label errors
* => we are in a loop
*/
if (!dev->poll && jcr->label_errors++ > 100) {
- Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
}
return VOL_NAME_ERROR;
}
return VOL_NO_MEDIA;
}
bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
-
+
/* Read the Volume label block */
record = new_record();
empty_block(block);
Dmsg0(90, "Big if statement in read_volume_label\n");
if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula "
- "labeled Volume, because: ERR=%s"), NPRT(VolName), dev_name(dev),
+ "labeled Volume, because: ERR=%s"), NPRT(VolName), dev_name(dev),
strerror_dev(dev));
Dmsg1(30, "%s", jcr->errmsg);
} else if (!read_record_from_block(block, record)) {
free_record(record);
if (forge_on || jcr->ignore_label_errors) {
dev->state |= ST_LABEL; /* set has Bacula label */
- Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
return VOL_OK;
}
empty_block(block);
* => we are in a loop
*/
if (!dev->poll && jcr->label_errors++ > 100) {
- Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
}
return VOL_NAME_ERROR;
}
return VOL_OK;
}
+/* Read the volume label by guessing the volume name. (only for mounted devices)
+ * write is true if we are reading the label before writing to the device.
+ *
+ * If the volume name cannot be guessed :
+ * Writing : returns the label of the current file (on the harddisk).
+ * Reading : returns an error
+ */
+int read_dev_volume_label_guess(DCR *dcr, bool write) {
+ int vol_label_status;
+ Dmsg3(100, "Enter read_dev_volume_label_guess device=%s vol=%s dev_Vol=%s\n",
+ dev_name(dcr->dev), dcr->VolumeName, dcr->dev->VolHdr.VolName);
+
+ if (!dev_cap(dcr->dev, CAP_REQMOUNT)) {
+ Dmsg0(100, "Leave read_dev_volume_label_guess !CAP_REQMOUNT\n");
+ return read_dev_volume_label(dcr);
+ }
+
+ if (!write && (dcr->VolCatInfo.VolCatParts == 0)) {
+ Dmsg0(100, "Leave read_dev_volume_label_guess !writing, and VolCatParts == 0\n");
+ return read_dev_volume_label(dcr);
+ }
+
+ /* For mounted devices, tries to guess the volume name, and read the label if possible.
+ */
+ if (open_guess_name_dev(dcr->dev) < 0) {
+ if ((!write) || (dcr->VolCatInfo.VolCatParts > 0)) {
+ Mmsg2(dcr->jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula labeled Volume."),
+ dev_name(dcr->dev), dcr->VolumeName);
+ Dmsg0(100, "Leave read_dev_volume_label_guess VOL_IO_ERROR (!open_guess_name_dev)\n");
+ return VOL_NO_LABEL;
+ }
+
+ if (write && (dcr->dev->free_space_errno < 0)) {
+ Dmsg0(100, "Leave read_dev_volume_label_guess !free_space VOL_NO_MEDIA\n");
+ Mmsg2(dcr->jcr->errmsg, _("free_space error on %s. The current medium is probably not writable. ERR=%s.\n"),
+ dcr->dev->dev_name, dcr->dev->errmsg);
+ return VOL_NO_MEDIA;
+ }
+
+ /* If we can't guess the name, and we are writing, just reopen the right file with open_first_part. */
+ if (open_first_part(dcr->dev) < 0) {
+ berrno be;
+ Mmsg2(dcr->jcr->errmsg, _("open_first_part error on %s. ERR=%s.\n"),
+ dcr->dev->dev_name, be.strerror());
+ Dmsg0(100, "Leave read_dev_volume_label_guess VOL_IO_ERROR (!open_guess_name_dev && !open_first_part)\n");
+ return VOL_IO_ERROR;
+ }
+
+ Dmsg0(100, "Leave read_dev_volume_label_guess !open_guess_name_dev\n");
+ return read_dev_volume_label(dcr);
+ }
+ else {
+ if (write && (dcr->dev->free_space_errno < 0)) {
+ Dmsg0(100, "Leave read_dev_volume_label_guess !free_space VOL_NO_MEDIA\n");
+ Mmsg2(dcr->jcr->errmsg, _("free_space error on %s. The current medium is probably not writable. ERR=%s.\n"),
+ dcr->dev->dev_name, dcr->dev->errmsg);
+ return VOL_NO_MEDIA;
+ }
+
+ vol_label_status = read_dev_volume_label(dcr);
+
+ if ((!write) || (dcr->VolCatInfo.VolCatParts > 0)) {
+ Dmsg0(100, "Leave read_dev_volume_label_guess (open_guess_name_dev && (!write || dcr->VolCatInfo.VolCatParts > 0))\n");
+ return vol_label_status;
+ }
+
+ if (open_first_part(dcr->dev) < 0) {
+ berrno be;
+ Mmsg2(dcr->jcr->errmsg, _("open_first_part error on %s. ERR=%s.\n"),
+ dcr->dev->dev_name, be.strerror());
+ Dmsg0(100, "Leave read_dev_volume_label_guess VOL_IO_ERROR (open_guess_name_dev && !open_first_part)\n");
+ return VOL_IO_ERROR;
+ }
+
+ /* When writing, if the guessed volume name is no the right volume name,
+ * report the error, otherwise, just continue with the right file.
+ */
+ if (vol_label_status != VOL_NAME_ERROR) {
+ Dmsg0(100, "Leave read_dev_volume_label_guess (open_guess_name_dev && !VOL_NAME_ERROR)\n");
+ dcr->dev->state &= ~ST_LABEL;
+ return read_dev_volume_label(dcr);
+ }
+ else {
+ Dmsg0(100, "Leave read_dev_volume_label_guess (open_guess_name_dev && VOL_NAME_ERROR)\n");
+ return vol_label_status;
+ }
+ }
+}
+
/* unser_volume_label
*
* Unserialize the Volume label into the device Volume_Label
if (!can_write_record_to_block(block, rec)) {
Dmsg0(100, "Cannot write session label to block.\n");
if (!write_block_to_device(dcr)) {
- Dmsg0(90, "Got session label write_block_to_dev error.\n");
+ Dmsg0(90, "Got session label write_block_to_dev error.\n");
/* ****FIXME***** errno is not set here */
- Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
dev_vol_name(dev), strerror(errno));
free_record(rec);
return false;
}
Dmsg6(20, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
- "remainder=%d\n", jcr->JobId,
+ "remainder=%d\n", jcr->JobId,
FI_to_ascii(rec->FileIndex), rec->VolSessionId,
stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len,
rec->remainder);
File = dev->file;
switch (dev->VolHdr.LabelType) {
case PRE_LABEL:
- LabelType = "PRE_LABEL";
+ LabelType = "PRE_LABEL";
break;
case VOL_LABEL:
- LabelType = "VOL_LABEL";
+ LabelType = "VOL_LABEL";
break;
case EOM_LABEL:
- LabelType = "EOM_LABEL";
+ LabelType = "EOM_LABEL";
break;
case SOS_LABEL:
- LabelType = "SOS_LABEL";
+ LabelType = "SOS_LABEL";
break;
case EOS_LABEL:
- LabelType = "EOS_LABEL";
+ LabelType = "EOS_LABEL";
break;
case EOT_LABEL:
goto bail_out;
default:
LabelType = buf;
- sprintf(buf, "Unknown %d", dev->VolHdr.LabelType);
+ sprintf(buf, "Unknown %d", dev->VolHdr.LabelType);
break;
}
dump_session_label(rec, type);
break;
case EOM_LABEL:
- Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
+ Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
break;
case EOT_LABEL:
- Pmsg0(-1, _("End of physical tape.\n"));
+ Pmsg0(-1, _("End of physical tape.\n"));
break;
default:
- Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
+ Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
break;
}
switch (rec->FileIndex) {
case SOS_LABEL:
unser_session_label(&label, rec);
- Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c Type=%c\n",
+ Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c Type=%c\n",
type, rec->VolSessionId, rec->VolSessionTime, rec->Stream,
label.JobLevel, label.JobType);
break;
case EOS_LABEL:
char ed1[30], ed2[30];
unser_session_label(&label, rec);
- Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c Type=%c\n",
+ Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c Type=%c\n",
type, rec->VolSessionId, rec->VolSessionTime, rec->Stream,
label.JobLevel, label.JobType);
- Pmsg4(-1, " Files=%s Bytes=%s Errors=%d Status=%c\n",
+ Pmsg4(-1, " Files=%s Bytes=%s Errors=%d Status=%c\n",
edit_uint64_with_commas(label.JobFiles, ed1),
edit_uint64_with_commas(label.JobBytes, ed2),
label.JobErrors, (char)label.JobStatus);
case PRE_LABEL:
case VOL_LABEL:
default:
- Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
+ Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
break;
case EOT_LABEL:
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
/* Last ditch effort before giving up, force operator to respond */
dcr->VolCatInfo.Slot = 0;
if (!dir_ask_sysop_to_mount_volume(dcr)) {
- Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
dev_name(dev));
return false;
}
if (job_canceled(jcr)) {
return false;
}
- Dmsg2(100, "After find_next_append. Vol=%s Slot=%d\n",
- dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot);
+ Dmsg3(100, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
+ dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot, dcr->VolCatInfo.VolCatParts);
+
+ dev->num_parts = dcr->VolCatInfo.VolCatParts;
/*
* Get next volume and ready it for append
}
/* Ensure the device is open */
- if (!open_device(dcr)) {
- if (dev->poll) {
- goto mount_next_vol;
- } else {
- return false;
+ /* If we have a device that requires mount, we first want to guess
+ * which device is loaded, so we continue (if the wrong device is
+ * loaded, open_device would fail). */
+ if (!dev_cap(dev, CAP_REQMOUNT)) {
+ if (!open_device(dcr)) {
+ if (dev->poll) {
+ goto mount_next_vol;
+ }
+ else {
+ return false;
+ }
}
}
+ else {
+ /* Just copy the VolCatName in the device resource (usually done by open_dev).
+ * It is necessary so we can open the real files later. */
+ bstrncpy(dcr->dev->VolCatInfo.VolCatName, dcr->VolCatInfo.VolCatName, sizeof(dcr->dev->VolCatInfo.VolCatName));
+ }
/*
* Now make sure we have the right tape mounted
vol_label_status = VOL_OK;
create_volume_label(dev, dcr->VolumeName, "Default");
dev->VolHdr.LabelType = PRE_LABEL;
- } else {
+ } else if (dev_cap(dev, CAP_REQMOUNT)) {
+ vol_label_status = read_dev_volume_label_guess(dcr, 1);
+ }
+ else {
vol_label_status = read_dev_volume_label(dcr);
}
if (job_canceled(jcr)) {
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
- Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
+ Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
dcr->VolumeName, dev_name(dev));
mark_volume_in_error(dcr);
goto mount_next_vol;
/* If polling and got a previous bad name, ignore it */
if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolName) == 0) {
ask = true;
- Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n",
+ Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n",
dcr->VolumeName);
goto mount_next_vol;
}
bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
bstrncpy(dev->BadVolName, dev->VolHdr.VolName, sizeof(dev->BadVolName));
- Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
- " Current Volume \"%s\" not acceptable because:\n"
- " %s"),
+ Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
+ " Current Volume \"%s\" not acceptable because:\n"
+ " %s"),
VolCatInfo.VolCatName, dev->VolHdr.VolName,
jcr->dir_bsock->msg);
/* Restore desired volume name, note device info out of sync */
*/
if (dev_cap(dev, CAP_LABEL) && (dcr->VolCatInfo.VolCatBytes == 0 ||
(!dev_is_tape(dev) && strcmp(dcr->VolCatInfo.VolCatStatus,
- "Recycle") == 0))) {
- Dmsg0(100, "Create volume label\n");
+ "Recycle") == 0))) {
+ Dmsg0(100, "Create volume label\n");
/* Create a new Volume label and write it to the device */
if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName,
dcr->pool_name)) {
- Dmsg0(100, "!write_vol_label\n");
+ Dmsg0(100, "!write_vol_label\n");
goto mount_next_vol;
}
- Dmsg0(100, "dir_update_vol_info. Set Append\n");
- /* Copy Director's info into the device info */
+ Dmsg0(100, "dir_update_vol_info. Set Append\n");
+ /* Copy Director's info into the device info */
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
if (!dir_update_volume_info(dcr, true)) { /* indicate tape labeled */
return false;
}
- Jmsg(jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
+ Jmsg(jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
dcr->VolumeName, dev_name(dev));
goto read_volume; /* read label we just wrote */
}
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
- Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
+ Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
dcr->VolumeName, dev_name(dev));
mark_volume_in_error(dcr);
goto mount_next_vol;
default:
/* Send error message */
if (!dev->poll) {
- Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
} else {
- Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
+ Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
}
ask = true;
+ /* Needed, so the medium can be changed */
+ if (dev_cap(dev, CAP_REQMOUNT)) {
+ close_dev(dev);
+ }
goto mount_next_vol;
}
Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
dcr->VolumeName);
if (!eod_dev(dev)) {
- Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device \"%s\". ERR=%s\n"),
+ Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
mark_volume_in_error(dcr);
goto mount_next_vol;
* that the database says we should be.
*/
if (dev->VolCatInfo.VolCatFiles == dev_file(dev)) {
- Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
+ Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
dcr->VolumeName, dev_file(dev));
} else {
- Jmsg(jcr, M_ERROR, 0, _("I canot write on Volume \"%s\" because:\n"
+ Jmsg(jcr, M_ERROR, 0, _("I canot write on Volume \"%s\" because:\n"
"The number of files mismatch! Volume=%u Catalog=%u\n"),
dcr->VolumeName, dev_file(dev), dev->VolCatInfo.VolCatFiles);
mark_volume_in_error(dcr);
*/
if (!dev_cap(dev, CAP_STREAM)) {
if (!rewind_dev(dev)) {
- Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device \"%s\". ERR=%s\n"),
+ Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
}
if (recycle) {
if (!truncate_dev(dev)) {
- Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device \"%s\". ERR=%s\n"),
+ Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
}
}
/* Attempt write to check write permission */
Dmsg0(200, "Attempt to write to device.\n");
if (!write_block_to_dev(dcr)) {
- Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"),
+ Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
- Dmsg0(200, "===ERROR write block to dev\n");
+ Dmsg0(200, "===ERROR write block to dev\n");
return false;
}
}
close_dev(dev);
dev->state &= ~ST_READ;
if (!acquire_device_for_read(jcr)) {
- Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
+ Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
dcr->VolumeName);
return false;
}
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
/* From dev.c */
DEVICE *init_dev(DEVICE *dev, DEVRES *device);
int open_dev(DEVICE *dev, char *VolName, int mode);
+off_t lseek_dev(DEVICE *dev, off_t offset, int whence);
+int open_first_part(DEVICE *dev);
+int open_next_part(DEVICE *dev);
+int open_guess_name_dev(DEVICE *dev);
void close_dev(DEVICE *dev);
void force_close_dev(DEVICE *dev);
bool truncate_dev(DEVICE *dev);
void init_dev_wait_timers(DEVICE *dev);
bool double_dev_wait_time(DEVICE *dev);
-
/* Get info about device */
char * dev_name(DEVICE *dev);
char * dev_vol_name(DEVICE *dev);
/* From label.c */
int read_dev_volume_label(DCR *dcr);
+int read_dev_volume_label_guess(DCR *dcr, bool write);
void create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName);
*/
/*
-
Copyright (C) 2005 Kern Sibbald
This program is free software; you can redistribute it and/or
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
bnet_strerror(fd));
return false;
} else {
- Dmsg1(30, ">filed: Hdr=%s\n", fd->msg);
+ Dmsg1(31, ">filed: Hdr=%s\n", fd->msg);
}
save_msg = fd->msg; /* save fd message pointer */
fd->msg = rec->data; /* pass data directly to bnet_send */
fd->msglen = rec->data_len;
- Dmsg1(30, ">filed: send %d bytes data.\n", fd->msglen);
+ Dmsg1(31, ">filed: send %d bytes data.\n", fd->msglen);
if (!bnet_send(fd)) {
Pmsg1(000, "Error sending to FD. ERR=%s\n", bnet_strerror(fd));
Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
HOST_OS, DISTNAME, DISTVER);
bstrftime_nc(dt, sizeof(dt), daemon_start_time);
bnet_fsend(user, _("Daemon started %s, %d Job%s run since started.\n"), dt, num_jobs_run,
- num_jobs_run == 1 ? "" : "s");
+ num_jobs_run == 1 ? "" : "s");
if (debug_level > 0) {
char b1[35], b2[35], b3[35], b4[35];
bnet_fsend(user, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
for (dev=device->dev; dev; dev=dev->next) {
if (dev_state(dev, ST_OPENED)) {
if (dev_state(dev, ST_LABEL)) {
- bnet_fsend(user, _("Device \"%s\" is mounted with Volume \"%s\"\n"),
+ bnet_fsend(user, _("Device \"%s\" is mounted with Volume \"%s\"\n"),
dev_name(dev), dev->VolHdr.VolName);
} else {
- bnet_fsend(user, _("Device \"%s\" open but no Bacula volume is mounted.\n"), dev_name(dev));
+ bnet_fsend(user, _("Device \"%s\" open but no Bacula volume is mounted.\n"), dev_name(dev));
}
send_blocked_status(jcr, dev);
if (dev_state(dev, ST_APPEND)) {
bpb = 1;
}
bpb = dev->VolCatInfo.VolCatBytes / bpb;
- bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
+ bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
edit_uint64_with_commas(bpb, b3));
} else {
bpb = 0;
}
- bnet_fsend(user, _(" Total Bytes Read=%s Blocks Read=%s Bytes/block=%s\n"),
+ bnet_fsend(user, _(" Total Bytes Read=%s Blocks Read=%s Bytes/block=%s\n"),
edit_uint64_with_commas(dev->VolCatInfo.VolCatRBytes, b1),
edit_uint64_with_commas(dev->VolCatInfo.VolCatReads, b2),
edit_uint64_with_commas(bpb, b3));
}
- bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"),
+ bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"),
edit_uint64_with_commas(dev->file, b1),
edit_uint64_with_commas(dev->block_num, b2));
} else {
- bnet_fsend(user, _("Device \"%s\" is not open.\n"), dev_name(dev));
+ bnet_fsend(user, _("Device \"%s\" is not open.\n"), dev_name(dev));
send_blocked_status(jcr, dev);
}
}
break;
case BST_WAITING_FOR_SYSOP:
if (jcr->JobStatus == JS_WaitMount) {
- bnet_fsend(user, _(" Device is BLOCKED waiting for mount of volume \"%s\".\n"),
+ bnet_fsend(user, _(" Device is BLOCKED waiting for mount of volume \"%s\".\n"),
dcr->VolumeName);
} else {
- bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n"));
+ bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n"));
}
break;
case BST_DOING_ACQUIRE:
bnet_fsend(user, "%sEOF ", dev->state & ST_EOF ? "" : "!");
bnet_fsend(user, "%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");
bnet_fsend(user, "%sSHORT ", dev->state & ST_SHORT ? "" : "!");
+ bnet_fsend(user, "%sMOUNTED ", dev->state & ST_MOUNTED ? "" : "!");
bnet_fsend(user, "\n");
bnet_fsend(user, _("Device parameters:\n"));
lock_jcr_chain();
foreach_jcr(jcr) {
if (jcr->JobStatus == JS_WaitFD) {
- bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
+ bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
job_type_to_str(jcr->JobType), jcr->Job);
}
if (jcr->device) {
/* There are three periods after the Job name */
char *p;
for (int i=0; i<3; i++) {
- if ((p=strrchr(JobName, '.')) != NULL) {
+ if ((p=strrchr(JobName, '.')) != NULL) {
*p = 0;
}
}
- bnet_fsend(user, _("%s %s job %s JobId=%d Volume=\"%s\" device=\"%s\"\n"),
+ bnet_fsend(user, _("%s %s job %s JobId=%d Volume=\"%s\" device=\"%s\"\n"),
job_level_to_str(jcr->JobLevel),
job_type_to_str(jcr->JobType),
JobName,
jcr->JobId,
- jcr->dcr?jcr->dcr->VolumeName:"*none*",
- jcr->device?jcr->device->device_name:"none");
+ jcr->dcr?jcr->dcr->VolumeName:"*none*",
+ jcr->device?jcr->device->device_name:"none");
sec = time(NULL) - jcr->run_time;
if (sec <= 0) {
sec = 1;
}
bps = jcr->JobBytes / sec;
- bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
+ bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
edit_uint64_with_commas(jcr->JobFiles, b1),
edit_uint64_with_commas(jcr->JobBytes, b2),
edit_uint64_with_commas(bps, b3));
found = true;
#ifdef DEBUG
if (jcr->file_bsock) {
- bnet_fsend(user, " FDReadSeqNo=%s in_msg=%u out_msg=%d fd=%d\n",
+ bnet_fsend(user, " FDReadSeqNo=%s in_msg=%u out_msg=%d fd=%d\n",
edit_uint64_with_commas(jcr->file_bsock->read_seqno, b1),
jcr->file_bsock->in_msg_no, jcr->file_bsock->out_msg_no,
jcr->file_bsock->fd);
} else {
- bnet_fsend(user, " FDSocket closed\n");
+ bnet_fsend(user, " FDSocket closed\n");
}
#endif
}
switch (je->JobType) {
case JT_ADMIN:
case JT_RESTORE:
- bstrncpy(level, " ", sizeof(level));
+ bstrncpy(level, " ", sizeof(level));
break;
default:
bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
}
switch (je->JobStatus) {
case JS_Created:
- termstat = "Created";
+ termstat = "Created";
break;
case JS_FatalError:
case JS_ErrorTerminated:
- termstat = "Error";
+ termstat = "Error";
break;
case JS_Differences:
- termstat = "Diffs";
+ termstat = "Diffs";
break;
case JS_Canceled:
- termstat = "Cancel";
+ termstat = "Cancel";
break;
case JS_Terminated:
- termstat = "OK";
+ termstat = "OK";
break;
default:
- termstat = "Other";
+ termstat = "Other";
break;
}
bstrncpy(JobName, je->Job, sizeof(JobName));
/* There are three periods after the Job name */
char *p;
for (int i=0; i<3; i++) {
- if ((p=strrchr(JobName, '.')) != NULL) {
+ if ((p=strrchr(JobName, '.')) != NULL) {
*p = 0;
}
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
#include "jcr.h"
#include "protos.h"
#ifdef HAVE_LIBZ
-#include <zlib.h> /* compression headers */
+#include <zlib.h> /* compression headers */
#else
#define uLongf uint32_t
#endif
#else
#include "lib/fnmatch.h"
#endif
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(dirent) (strlen((dirent)->d_name))
+#endif
+#ifndef HAVE_READDIR_R
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+#endif
extern STORES *me; /* "Global" daemon resource */
-extern bool forge_on; /* proceed inspite of I/O errors */
+extern bool forge_on; /* proceed inspite of I/O errors */
#ifdef debug_tracing
extern int _rewind_dev(char *file, int line, DEVICE *dev);
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
{"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
{"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
{"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0},
+ {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
+ {"requiresmount", store_yesno, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
+ {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
+ {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
+ {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
+ {"writepartcommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
+ {"freespacecommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
{NULL, NULL, 0, 0, 0, 0}
};
get_first_port_host_order(res->res_store.sddaddrs),
edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
foreach_dlist(p, res->res_store.sdaddrs) {
- sendit(sock, " SDaddr=%s SDport=%d\n",
+ sendit(sock, " SDaddr=%s SDport=%d\n",
p->get_address(buf, sizeof(buf)), p->get_port_host_order());
}
foreach_dlist(p, res->res_store.sddaddrs) {
- sendit(sock, " SDDaddr=%s SDDport=%d\n",
+ sendit(sock, " SDDaddr=%s SDDport=%d\n",
p->get_address(buf, sizeof(buf)), p->get_port_host_order());
}
break;
res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
strcpy(buf, " ");
if (res->res_dev.cap_bits & CAP_EOF) {
- bstrncat(buf, "CAP_EOF ", sizeof(buf));
+ bstrncat(buf, "CAP_EOF ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_BSR) {
- bstrncat(buf, "CAP_BSR ", sizeof(buf));
+ bstrncat(buf, "CAP_BSR ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_BSF) {
- bstrncat(buf, "CAP_BSF ", sizeof(buf));
+ bstrncat(buf, "CAP_BSF ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_FSR) {
- bstrncat(buf, "CAP_FSR ", sizeof(buf));
+ bstrncat(buf, "CAP_FSR ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_FSF) {
- bstrncat(buf, "CAP_FSF ", sizeof(buf));
+ bstrncat(buf, "CAP_FSF ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_EOM) {
- bstrncat(buf, "CAP_EOM ", sizeof(buf));
+ bstrncat(buf, "CAP_EOM ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_REM) {
- bstrncat(buf, "CAP_REM ", sizeof(buf));
+ bstrncat(buf, "CAP_REM ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_RACCESS) {
- bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
+ bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
- bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
+ bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_LABEL) {
- bstrncat(buf, "CAP_LABEL ", sizeof(buf));
+ bstrncat(buf, "CAP_LABEL ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_ANONVOLS) {
- bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
+ bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
}
if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
- bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
+ bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
}
bstrncat(buf, "\n", sizeof(buf));
sendit(sock, buf);
case R_MSGS:
sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
if (res->res_msgs.mail_cmd)
- sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
+ sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
if (res->res_msgs.operator_cmd)
- sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
+ sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
break;
default:
sendit(sock, _("Warning: unknown resource type %d\n"), type);
if (res->res_dev.spool_directory) {
free(res->res_dev.spool_directory);
}
+ if (res->res_dev.mount_point) {
+ free(res->res_dev.mount_point);
+ }
+ if (res->res_dev.mount_command) {
+ free(res->res_dev.mount_command);
+ }
+ if (res->res_dev.unmount_command) {
+ free(res->res_dev.unmount_command);
+ }
+ if (res->res_dev.write_part_command) {
+ free(res->res_dev.write_part_command);
+ }
+ if (res->res_dev.free_space_command) {
+ free(res->res_dev.free_space_command);
+ }
break;
case R_MSGS:
if (res->res_msgs.mail_cmd) {
res = NULL;
break;
default:
- Dmsg1(0, "Unknown resource type %d\n", type);
+ Dmsg1(0, "Unknown resource type %d\n", type);
break;
}
/* Common stuff again -- free the resource, recurse to next one */
for (i=0; items[i].name; i++) {
if (items[i].flags & ITEM_REQUIRED) {
if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
- Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
+ Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
items[i].name, resources[rindex]);
}
}
/* If this triggers, take a look at lib/parse_conf.h */
if (i >= MAX_RES_ITEMS) {
- Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
+ Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
}
}
/* Resources containing a resource */
case R_STORAGE:
if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name);
+ Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name);
}
res->res_store.messages = res_all.res_store.messages;
break;
default:
- printf("Unknown resource type %d\n", type);
+ printf("Unknown resource type %d\n", type);
error = 1;
break;
}
size = sizeof(MSGS);
break;
default:
- printf("Unknown resource type %d\n", type);
+ printf("Unknown resource type %d\n", type);
error = 1;
size = 1;
break;
for (next=res_head[rindex]; next->next; next=next->next) {
if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
Emsg2(M_ERROR_TERM, 0,
- _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
+ _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
resources[rindex].name, res->res_dir.hdr.name);
}
}
next->next = (RES *)res;
- Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
+ Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
res->res_dir.hdr.name);
}
}
* Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 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
R_DEVICE,
R_MSGS,
R_FIRST = R_DIRECTOR,
- R_LAST = R_MSGS /* keep this updated */
+ R_LAST = R_MSGS /* keep this updated */
};
enum {
/* Definition of the contents of each Resource */
struct DIRRES {
- RES hdr;
+ RES hdr;
- char *password; /* Director password */
- char *address; /* Director IP address or zero */
- int enable_ssl; /* Use SSL with this Director */
- int monitor; /* Have only access to status and .status functions */
+ char *password; /* Director password */
+ char *address; /* Director IP address or zero */
+ int enable_ssl; /* Use SSL with this Director */
+ int monitor; /* Have only access to status and .status functions */
};
/* Storage daemon "global" definitions */
struct s_res_store {
- RES hdr;
+ RES hdr;
dlist *sdaddrs;
dlist *sddaddrs;
- char *working_directory; /* working directory for checkpoints */
+ char *working_directory; /* working directory for checkpoints */
char *pid_directory;
char *subsys_directory;
- int require_ssl; /* Require SSL on all connections */
+ int require_ssl; /* Require SSL on all connections */
uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */
- MSGS *messages; /* Daemon message handler */
- utime_t heartbeat_interval; /* Interval to send hb to FD */
+ MSGS *messages; /* Daemon message handler */
+ utime_t heartbeat_interval; /* Interval to send hb to FD */
};
typedef struct s_res_store STORES;
/* Device specific definitions */
struct DEVRES {
- RES hdr;
+ RES hdr;
- char *media_type; /* User assigned media type */
- char *device_name; /* Archive device name */
- char *changer_name; /* Changer device name */
- char *changer_command; /* Changer command -- external program */
- char *alert_command; /* Alert command -- external program */
- char *spool_directory; /* Spool file directory */
- uint32_t drive_index; /* Autochanger drive index */
- uint32_t cap_bits; /* Capabilities of this device */
- uint32_t max_changer_wait; /* Changer timeout */
- uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
- uint32_t max_open_wait; /* maximum secs to wait for open */
- uint32_t max_open_vols; /* maximum simultaneous open volumes */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ char *media_type; /* User assigned media type */
+ char *device_name; /* Archive device name */
+ char *changer_name; /* Changer device name */
+ char *changer_command; /* Changer command -- external program */
+ char *alert_command; /* Alert command -- external program */
+ char *spool_directory; /* Spool file directory */
+ uint32_t drive_index; /* Autochanger drive index */
+ uint32_t cap_bits; /* Capabilities of this device */
+ uint32_t max_changer_wait; /* Changer timeout */
+ uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
+ uint32_t max_open_wait; /* maximum secs to wait for open */
+ uint32_t max_open_vols; /* maximum simultaneous open volumes */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
uint32_t max_network_buffer_size; /* max network buf size */
- utime_t vol_poll_interval; /* interval between polling volume during mount */
- int64_t max_volume_files; /* max files to put on one volume */
- int64_t max_volume_size; /* max bytes to put on one volume */
- int64_t max_file_size; /* max file size in bytes */
- int64_t volume_capacity; /* advisory capacity */
- int64_t max_spool_size; /* Max spool size for all jobs */
- int64_t max_job_spool_size; /* Max spool size for any single job */
- DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
+ utime_t vol_poll_interval; /* interval between polling volume during mount */
+ int64_t max_volume_files; /* max files to put on one volume */
+ int64_t max_volume_size; /* max bytes to put on one volume */
+ int64_t max_file_size; /* max file size in bytes */
+ int64_t volume_capacity; /* advisory capacity */
+ int64_t max_spool_size; /* Max spool size for all jobs */
+ int64_t max_job_spool_size; /* Max spool size for any single job */
+
+ int64_t max_part_size; /* Max part size */
+ char *mount_point; /* Mount point for require mount devices */
+ char *mount_command; /* Mount command */
+ char *unmount_command; /* Unmount command */
+ char *write_part_command; /* Write part command */
+ char *free_space_command; /* Free space command */
+
+ DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
};
union URES {
STORES res_store;
DEVRES res_dev;
MSGS res_msgs;
- RES hdr;
+ RES hdr;
};
int
main (int argc, char *const *argv)
{
- POOLMEM *fs;
int verbose = 0;
int status = 0;
int ch, i;
+ char fs[1000];
while ((ch = getopt(argc, argv, "v?")) != -1) {
switch (ch) {
- case 'v':
+ case 'v':
verbose = 1;
break;
- case '?':
+ case '?':
default:
usage();
}
for (i = 0; i < argc; --argc, ++argv) {
- if ((fs = fstype(*argv)) != NULL) {
+ if (fstype(*argv, fs, sizeof(fs))) {
if (verbose) {
- printf("%s: %s\n", *argv, fs);
+ printf("%s: %s\n", *argv, fs);
} else {
puts(fs);
}
- free(fs);
} else {
- fprintf(stderr, "%s: unknown\n", *argv);
+ fprintf(stderr, "%s: unknown\n", *argv);
status = 1;
}
}
/* */
#undef VERSION
-#define VERSION "1.37.1"
-#define BDATE "07 January 2005"
-#define LSMDATE "07Jan05"
+#define VERSION "1.37.2"
+#define BDATE "08 January 2005"
+#define LSMDATE "08Jan05"
/* Debug flags */
#undef DEBUG