Kern's ToDo List
- 13 May 2003
+ 14 May 2003
Documentation to do: (any release a little bit at a time)
- Document running a test version.
- Document static linking
- Document problems with Verify and pruning.
- Document how to use multiple databases.
-- Add a section to the doc on Manual cycling of Volumes.
- For FreeBSD typical /dev/nrsa0 and for mtx /dev/pass1
- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.31 release:
-- Check if Job/File retentions apply to multivolume jobs.
+14-May-2003 14:41 undef-sd: RestoreFiles.2003-05-14_14.41.00 Warning: acquire.c:106 Volume name mismatch. Wanted TestVolume0005 got TestVolume0010
+14-May-2003 14:41 undef-sd: 3301 Issuing autochanger "loaded" command.
+14-May-2003 14:41 undef-sd: 3302 Issuing autochanger "unload" command.
+14-May-2003 14:42 undef-sd: 3303 Issuing autochanger "load slot 1" command.
+14-May-2003 14:42 undef-sd: 3304 Autochanger "load slot 1" status is OK.
+14-May-2003 14:42 undef-sd: RestoreFiles.2003-05-14_14.41.00 Warning: acquire.c:106 Volume name mismatch. Wanted TestVolume0005 got TestVolume0009
+14-May-2003 14:42 undef-sd: 3301 Issuing autochanger "loaded" command.
+14-May-2003 14:42 undef-sd: RestoreFiles.2003-05-14_14.41.00 Warning: acquire.c:106 Volume name mismatch. Wanted TestVolume0005 got TestVolume0009
+14-May-2003 14:42 undef-sd: 3301 Issuing autochanger "loaded" command.
+14-May-2003 14:42 undef-sd: RestoreFiles.2003-05-14_14.41.00 Warning: acquire.c:106 Volume name mismatch. Wanted TestVolume0005 got TestVolume0009
+14-May-2003 14:42 undef-sd: 3301 Issuing autochanger "loaded" command.
+14-May-2003 14:42 undef-sd: RestoreFiles.2003-05-14_14.41.00 Warning: acquire.c:106 Volume name mismatch. Wanted TestVolume0005 got TestVolume0009
+14-May-2003 14:42 undef-sd: 3301 Issuing autochanger "loaded" command.
+14-May-2003 14:42 undef-sd: RestoreFiles.2003-05-14_14.41.00 Fatal error: acquire.c:129 Too many errors trying to mount device "/dev/nrsa0".
+14-May-2003 14:42 undef-dir: Bacula 1.31 (12May03): 14-May-2003 14:42
+
+- Implement MTIOCERRSTAT on FreeBSD to clear tape error conditions.
+
+- BSD (probably) does not have strtoll()
+- BSD does not have ioctl() MTEOM
+- BSD defines a number of MT_xxx variables which conflict
+ with those defined by Bacula.
+
+- The following Re-read last block at EOT failed. ERR=block.c:523 Read zero bytes on device /dev/nrsa0.
+ undef-sd: block.c:523 Read zero bytes on device /dev/nrsa0.
+ apparently masks the standard EOM message.
- Add Progress command that periodically reports the progress of
a job or all jobs.
- Implement "Reschedule OnError=yes interval=nnn times=xxx"
xeon-fd: Could not stat c:/Documents and Settings/All
Users/Application Data/Humc:\Documents and Settings\All User98_AIX.kbf:
ERR=No such file or directory
-- Implement argv/argk in place of sscanf in the daemon protocol.
- Examine Bare Metal restore problem (a FD crash exists somewhere ...).
- Test multiple simultaneous Volumes
- Document FInclude ...
The number of files mismatch! Volume=1 Catalog=0
rufus-sd: Matou.2003-05-10_10.39.18 Error: askdir.c:155 NULL Volume name. This shouldn't happen!!!
- Shell character expansion is failing occassionally.
+- Add a section to the doc on Manual cycling of Volumes.
+- Check if Job/File retentions apply to multivolume jobs.
/* Forward referenced functions */
+/*
+ * The pruning code was written to be referenced by the
+ * User Agent (i.e. the console), so to properly access it and
+ * to ensure that the Job gets the proper output, we create
+ * a User Agent context. This is a sort of mini-kludge.
+ */
void create_ua_context(JCR *jcr, UAContext *ua)
{
memset(ua, 0, sizeof(UAContext));
}
/*
- * Auto Prune Jobs and Files
- * Volumes are done separately
+ * Auto Prune Jobs and Files. This is called at the end of every
+ * Job. We do not prune volumes here.
*/
int do_autoprune(JCR *jcr)
{
}
/*
- * Prune all volumes in current Pool.
+ * Prune all volumes in current Pool. This is called from
+ * catreq.c when the Storage daemon is asking for another
+ * volume and no appendable volumes are available.
*
* Return 0: on error
* number of Volumes Purged
db_lock(jcr->db);
+ /* Get the Pool Record and a list of Media Id's in the Pool */
pr.PoolId = jcr->PoolId;
if (!db_get_pool_record(jcr, jcr->db, &pr) || !db_get_media_ids(jcr, jcr->db, &num_ids, &ids)) {
Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
goto bail_out;
}
-
+ /* Visit each Volume and Prune it */
for (i=0; i<num_ids; i++) {
mr.MediaId = ids[i];
if (!db_get_media_record(jcr, jcr->db, &mr)) {
* Send Level command to File daemon
*/
switch (jcr->JobLevel) {
+ case L_BASE:
+ bnet_fsend(fd, levelcmd, "base", " ");
+ break;
case L_FULL:
bnet_fsend(fd, levelcmd, "full", " ");
break;
bpipe = open_bpipe(fname, 0, "w");
fd = bpipe ? bpipe->wfd : NULL;
} else {
+ /* ***FIXME*** handle BASE */
fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+");
}
if (fd) {
*/
struct s_jl joblevels[] = {
{"Full", L_FULL, JT_BACKUP},
+ {"Base", L_BASE, JT_BACKUP},
{"Incremental", L_INCREMENTAL, JT_BACKUP},
{"Differential", L_DIFFERENTIAL, JT_BACKUP},
{"Since", L_SINCE, JT_BACKUP},
db_lock(ua->db);
memset(&jr, 0, sizeof(jr));
memset(&del, 0, sizeof(del));
+
+ /*
+ * Find out how many Jobs remain on this Volume by
+ * counting the JobMedia records.
+ */
cnt.count = 0;
Mmsg(&query, cnt_JobMedia, mr->MediaId);
if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) {
del.max_ids = MAX_DEL_LIST_LEN;
}
+ /*
+ * Now get a list of JobIds for Jobs written to this Volume
+ * Could optimize here by adding JobTDate > (now - period).
+ */
del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
-
- /* ***FIXME*** could make this do JobTDate check too */
Mmsg(&query, sel_JobMedia, mr->MediaId);
if (!db_sql_query(ua->db, query, file_delete_handler, (void *)&del)) {
if (ua->verbose) {
goto bail_out;
}
- /* Use Volume Retention to prune Jobs and Files */
+ /* Use Volume Retention to prune Jobs and their Files */
period = mr->VolRetention;
now = (utime_t)time(NULL);
Dmsg3(200, "Now=%d period=%d now-period=%d\n", (int)now, (int)period,
(int)(now-period));
+
for (i=0; i < del.num_ids; i++) {
jr.JobId = del.JobId[i];
if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
/* Level */
if (jcr->JobType == JT_BACKUP) {
start_prompt(ua, _("Levels:\n"));
+ add_prompt(ua, _("Base"));
add_prompt(ua, _("Full"));
add_prompt(ua, _("Incremental"));
add_prompt(ua, _("Differential"));
add_prompt(ua, _("Since"));
switch (do_prompt(ua, _("Select level"), NULL, 0)) {
case 0:
- jcr->JobLevel = L_FULL;
+ jcr->JobLevel = L_BASE;
break;
case 1:
- jcr->JobLevel = L_INCREMENTAL;
+ jcr->JobLevel = L_FULL;
break;
case 2:
- jcr->JobLevel = L_DIFFERENTIAL;
+ jcr->JobLevel = L_INCREMENTAL;
break;
case 3:
+ jcr->JobLevel = L_DIFFERENTIAL;
+ break;
+ case 4:
jcr->JobLevel = L_SINCE;
break;
default:
free_memory(level);
return 0;
}
- /*
- * Full backup requested
- */
- if (strcmp(level, "full") == 0) {
+ /* Base backup requested? */
+ if (strcmp(level, "base") == 0) {
+ jcr->save_level = L_BASE;
+ /* Full backup requested? */
+ } else if (strcmp(level, "full") == 0) {
jcr->save_level = L_FULL;
/*
* Backup requested since <date> <time>
tm.tm_isdst = -1;
mtime = mktime(&tm);
Dmsg1(100, "Got since time: %s", ctime(&mtime));
- jcr->incremental = 1;
- jcr->mtime = mtime;
+ jcr->incremental = 1; /* set incremental or decremental backup */
+ jcr->mtime = mtime; /* set since time */
} else {
Jmsg1(jcr, M_FATAL, 0, "Unknown backup level: %s\n", level);
free_memory(level);
int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
{
POOLMEM *win32_fname;
+
if (!bfd->use_win_api) {
bfd->fid = open(fname, flags, mode);
if (bfd->fid >= 0) {
if (flags & O_WRONLY) { /* creating */
bfd->fh = CreateFile(win32_fname,
- WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY, /* access */
- FILE_SHARE_READ | FILE_SHARE_WRITE, /* shared mode */
+ FILE_ALL_ACCESS|WRITE_DAC|ACCESS_SYSTEM_SECURITY, /* access */
+ 0,
NULL, /* SecurityAttributes */
CREATE_ALWAYS, /* CreationDisposition */
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, /* Flags and attributes */
}
} else {
bfd->fh = CreateFile(win32_fname,
- READ_CONTROL|ACCESS_SYSTEM_SECURITY, /* access */
- FILE_SHARE_READ | FILE_SHARE_WRITE, /* shared mode */
+ GENERIC_READ|ACCESS_SYSTEM_SECURITY, /* access */
+ FILE_SHARE_READ, /* shared mode */
NULL, /* SecurityAttributes */
OPEN_EXISTING, /* CreationDisposition */
- FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, /* Flags and attributes */
+ FILE_FLAG_BACKUP_SEMANTICS, /* Flags and attributes */
NULL); /* TemplateFile */
if (bfd->fh == INVALID_HANDLE_VALUE) {
}
bfd->rw_bytes = 0;
- BackupRead(bfd->fh,
- (BYTE *)buf,
- count,
- &bfd->rw_bytes,
- 0, /* no Abort */
- 1, /* Process Security */
- &bfd->lpContext); /* Context */
- if (bfd->rw_bytes > 0) {
- return (ssize_t)bfd->rw_bytes;
+ if (!BackupRead(bfd->fh,
+ (BYTE *)buf,
+ count,
+ &bfd->rw_bytes,
+ 0, /* no Abort */
+ 1, /* Process Security */
+ &bfd->lpContext)) { /* Context */
+ bfd->lerror = GetLastError();
+ return -1;
}
- bfd->lerror = GetLastError();
- return bfd->lerror == 0 ? 0 : -1;
+ return (ssize_t)bfd->rw_bytes;
}
ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
{
- DWORD bytes_written = 0;
if (!bfd->use_win_api) {
return write(bfd->fid, buf, count);
}
- BackupWrite(bfd->fh,
- (BYTE *)buf,
- count,
- &bytes_written,
- 0, /* No abort */
- 1, /* Process Security */
- &bfd->lpContext); /* Context */
-
- if ((size_t)bfd->rw_bytes == count) {
- return (ssize_t)bfd->rw_bytes;
+
+ bfd->rw_bytes = 0;
+ if (!BackupWrite(bfd->fh,
+ (BYTE *)buf,
+ count,
+ &bfd->rw_bytes,
+ 0, /* No abort */
+ 1, /* Process Security */
+ &bfd->lpContext)) { /* Context */
+ bfd->lerror = GetLastError();
+ return -1;
}
- bfd->lerror = GetLastError();
- return bfd->lerror == 0 ? (ssize_t)bfd->rw_bytes : -1;
+ return (ssize_t)bfd->rw_bytes;
}
int is_bopen(BFILE *bfd)
#define __JCR_H_ 1
/* Backup/Verify level code. These are stored in the DB */
-#define L_FULL 'F'
+#define L_FULL 'F' /* Full backup */
#define L_INCREMENTAL 'I' /* since last backup */
#define L_DIFFERENTIAL 'D' /* since last full backup */
#define L_SINCE 'S'
#define L_VERIFY_INIT 'V' /* verify save (init DB) */
#define L_VERIFY_VOLUME_TO_CATALOG 'O' /* verify Volume to catalog entries */
#define L_VERIFY_DATA 'A' /* verify data on volume */
+#define L_BASE 'B' /* Base level job */
/* Job Types. These are stored in the DB */
} else {
return 0;
}
+ tm.tm_wday = tm.tm_yday = 0;
+ tm.tm_isdst = -1;
ttime = mktime(&tm);
if (ttime == -1) {
ttime = 0;
char *str;
switch (level) {
+ case L_BASE:
+ str = _("Base");
case L_FULL:
str = _("Full");
break;
int stat = 0;
int tape_previously_mounted;
VOL_LIST *vol;
+ int autochanger = 0;
lock_device(dev);
block_device(dev, BST_DOING_ACQUIRE);
dev->state &= ~ST_LABEL; /* force reread of label */
Dmsg0(200, "calling read-vol-label\n");
switch (read_dev_volume_label(jcr, dev, block)) {
- case VOL_OK:
- stat = 1;
- break; /* got it */
- case VOL_IO_ERROR:
- /*
- * Send error message generated by read_dev_volume_label()
- * only we really had a tape mounted. This supresses superfluous
- * error messages when nothing is mounted.
- */
- if (tape_previously_mounted) {
- Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
- }
- goto default_path;
- default:
- Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ case VOL_OK:
+ stat = 1;
+ break; /* got it */
+ case VOL_IO_ERROR:
+ /*
+ * Send error message generated by read_dev_volume_label()
+ * only we really had a tape mounted. This supresses superfluous
+ * error messages when nothing is mounted.
+ */
+ if (tape_previously_mounted) {
+ Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ }
+ goto default_path;
+ default:
+ Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
default_path:
- tape_previously_mounted = 0;
- Dmsg0(200, "dir_get_volume_info\n");
- if (!dir_get_volume_info(jcr, 0)) {
- Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
- }
+ tape_previously_mounted = 1;
+ if (autochanger) {
+ invalidate_slot_in_catalog(jcr);
+ }
+ Dmsg0(200, "dir_get_volume_info\n");
+ if (!dir_get_volume_info(jcr, 0)) {
+ Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
+ }
+ /* Call autochanger only once unless ask_sysop called */
+ if (!autochanger) {
Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
jcr->VolumeName, jcr->VolCatInfo.Slot);
- if (autoload_device(jcr, dev, 0, NULL)) {
+ if ((autochanger=autoload_device(jcr, dev, 0, NULL))) {
continue;
}
- /* Mount a specific volume and no other */
- Dmsg0(200, "calling dir_ask_sysop\n");
- if (!dir_ask_sysop_to_mount_volume(jcr, dev)) {
- goto get_out; /* error return */
- }
- continue; /* try reading again */
- }
+ }
+ /* Mount a specific volume and no other */
+ Dmsg0(200, "calling dir_ask_sysop\n");
+ if (!dir_ask_sysop_to_mount_volume(jcr, dev)) {
+ goto get_out; /* error return */
+ }
+ autochanger = 0; /* permit using autochanger again */
+ continue; /* try reading again */
+ } /* end switch */
break;
- }
+ } /* end for loop */
if (stat == 0) {
Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device \"%s\".\n"),
dev_name(dev));
return rtn_stat;
}
+void invalidate_slot_in_catalog(JCR *jcr)
+{
+ Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n"
+" Setting slot to zero in catalog.\n"),
+ jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
+ jcr->VolCatInfo.Slot = 0; /* invalidate slot */
+ Dmsg0(200, "update vol info in mount\n");
+ dir_update_volume_info(jcr, &jcr->VolCatInfo, 1); /* set slot */
+}
+
/*
* List the Volumes that are in the autoloader possibly
* with their barcodes.
/* Send error message */
Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
if (autochanger) {
- Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n\
- Setting slot to zero in catalog.\n"),
- jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
- jcr->VolCatInfo.Slot = 0; /* invalidate slot */
- Dmsg0(200, "update vol info in mount\n");
- dir_update_volume_info(jcr, &jcr->VolCatInfo, 1); /* set slot */
+ invalidate_slot_in_catalog(jcr);
}
Dmsg0(100, "Default\n");
goto mount_next_vol;
uint32_t new_VolSessionId();
/* From acquire.c */
-DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int release_device(JCR *jcr, DEVICE *dev);
+DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int release_device(JCR *jcr, DEVICE *dev);
/* From askdir.c */
-int dir_get_volume_info(JCR *jcr, int writing);
-int dir_find_next_appendable_volume(JCR *jcr);
-int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel);
-int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
-int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
-int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
-int dir_send_job_status(JCR *jcr);
-int dir_create_jobmedia_record(JCR *jcr);
+int dir_get_volume_info(JCR *jcr, int writing);
+int dir_find_next_appendable_volume(JCR *jcr);
+int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel);
+int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
+int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
+int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
+int dir_send_job_status(JCR *jcr);
+int dir_create_jobmedia_record(JCR *jcr);
/* authenticate.c */
-int authenticate_director(JCR *jcr);
-int authenticate_filed(JCR *jcr);
+int authenticate_director(JCR *jcr);
+int authenticate_filed(JCR *jcr);
/* From block.c */
-void dump_block(DEV_BLOCK *b, char *msg);
+void dump_block(DEV_BLOCK *b, char *msg);
DEV_BLOCK *new_block(DEVICE *dev);
-void init_block_write(DEV_BLOCK *block);
-void empty_block(DEV_BLOCK *block);
-void free_block(DEV_BLOCK *block);
-int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
-int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
+void init_block_write(DEV_BLOCK *block);
+void empty_block(DEV_BLOCK *block);
+void free_block(DEV_BLOCK *block);
+int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
+int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
/* From butil.c -- utilities for SD tool programs */
-void print_ls_output(char *fname, char *link, int type, struct stat *statp);
+void print_ls_output(char *fname, char *link, int type, struct stat *statp);
JCR *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName);
DEVICE *setup_to_access_device(JCR *jcr, int read_access);
-void display_error_status(DEVICE *dev);
+void display_error_status(DEVICE *dev);
DEVRES *find_device_res(char *device_name, int read_access);
/* From dev.c */
-DEVICE *init_dev(DEVICE *dev, DEVRES *device);
-int open_dev(DEVICE *dev, char *VolName, int mode);
-void close_dev(DEVICE *dev);
-void force_close_dev(DEVICE *dev);
-int truncate_dev(DEVICE *dev);
-void term_dev(DEVICE *dev);
-char * strerror_dev(DEVICE *dev);
-void clrerror_dev(DEVICE *dev, int func);
-int update_pos_dev(DEVICE *dev);
-int rewind_dev(DEVICE *dev);
-int load_dev(DEVICE *dev);
-int offline_dev(DEVICE *dev);
-int flush_dev(DEVICE *dev);
-int weof_dev(DEVICE *dev, int num);
-int write_block(DEVICE *dev);
-int write_dev(DEVICE *dev, char *buf, size_t len);
-int read_dev(DEVICE *dev, char *buf, size_t len);
-int status_dev(DEVICE *dev, uint32_t *status);
-int eod_dev(DEVICE *dev);
-int fsf_dev(DEVICE *dev, int num);
-int fsr_dev(DEVICE *dev, int num);
-int bsf_dev(DEVICE *dev, int num);
-int bsr_dev(DEVICE *dev, int num);
-void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
-void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
-JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
+DEVICE *init_dev(DEVICE *dev, DEVRES *device);
+int open_dev(DEVICE *dev, char *VolName, int mode);
+void close_dev(DEVICE *dev);
+void force_close_dev(DEVICE *dev);
+int truncate_dev(DEVICE *dev);
+void term_dev(DEVICE *dev);
+char * strerror_dev(DEVICE *dev);
+void clrerror_dev(DEVICE *dev, int func);
+int update_pos_dev(DEVICE *dev);
+int rewind_dev(DEVICE *dev);
+int load_dev(DEVICE *dev);
+int offline_dev(DEVICE *dev);
+int flush_dev(DEVICE *dev);
+int weof_dev(DEVICE *dev, int num);
+int write_block(DEVICE *dev);
+int write_dev(DEVICE *dev, char *buf, size_t len);
+int read_dev(DEVICE *dev, char *buf, size_t len);
+int status_dev(DEVICE *dev, uint32_t *status);
+int eod_dev(DEVICE *dev);
+int fsf_dev(DEVICE *dev, int num);
+int fsr_dev(DEVICE *dev, int num);
+int bsf_dev(DEVICE *dev, int num);
+int bsr_dev(DEVICE *dev, int num);
+void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
+void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
+JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
/* Get info about device */
-char * dev_name(DEVICE *dev);
-char * dev_vol_name(DEVICE *dev);
+char * dev_name(DEVICE *dev);
+char * dev_vol_name(DEVICE *dev);
uint32_t dev_block(DEVICE *dev);
uint32_t dev_file(DEVICE *dev);
-int dev_is_tape(DEVICE *dev);
+int dev_is_tape(DEVICE *dev);
/* From device.c */
-int open_device(DEVICE *dev);
-int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int open_device(DEVICE *dev);
+int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
void _lock_device(char *file, int line, DEVICE *dev);
void _unlock_device(char *file, int line, DEVICE *dev);
void _block_device(char *file, int line, DEVICE *dev, int state);
void new_return_device_lock(DEVICE *dev, brwsteal_t *hold);
/* From dircmd.c */
-void *connection_request(void *arg);
+void *connection_request(void *arg);
/* From fd_cmds.c */
-void run_job(JCR *jcr);
+void run_job(JCR *jcr);
/* From job.c */
-void stored_free_jcr(JCR *jcr);
-void connection_from_filed(void *arg);
-void handle_filed_connection(BSOCK *fd, char *job_name);
+void stored_free_jcr(JCR *jcr);
+void connection_from_filed(void *arg);
+void handle_filed_connection(BSOCK *fd, char *job_name);
/* From label.c */
-int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
-void create_volume_label(DEVICE *dev, char *VolName);
-int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
-int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void dump_volume_label(DEVICE *dev);
-void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-int unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
+void create_volume_label(DEVICE *dev, char *VolName);
+int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
+int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
+int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void dump_volume_label(DEVICE *dev);
+void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+int unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
/* From match_bsr.c */
int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
- SESSION_LABEL *sesrec);
+ SESSION_LABEL *sesrec);
/* From mount.c */
-int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
-int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
+int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
/* From autochanger.c */
-int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
-int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
+int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
+int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
+void invalidate_slot_in_catalog(JCR *jcr);
/* From parse_bsr.c */
/* From record.c */
char *FI_to_ascii(int fi);
char *stream_to_ascii(int stream, int fi);
-int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
-void free_record(DEV_RECORD *rec);
+void free_record(DEV_RECORD *rec);
/* From read_record.c */
int read_records(JCR *jcr, DEVICE *dev,
/* */
#define VERSION "1.31"
#define VSTRING "1"
-#define BDATE "12 May 2003"
-#define LSMDATE "12May03"
+#define BDATE "15 May 2003"
+#define LSMDATE "15May03"
/* Debug flags */
#define DEBUG 1