From eab20270e130f6628f6fe44f5c86c687e54461bd Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Fri, 23 May 2003 17:24:36 +0000 Subject: [PATCH] Sort bsr records, use C++ structs, add volatile, fix shell character expansion, make new status.c in SD git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@534 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 2 +- bacula/autoconf/configure.in | 1 + bacula/configure | 1 + bacula/kernstodo | 18 +++ bacula/src/cats/cats.h | 37 ++--- bacula/src/dird/ua_restore.c | 82 ++++++++--- bacula/src/filed/win32/winevents.h | 21 +-- bacula/src/filed/win32/winservice.cpp | 2 +- bacula/src/filed/win32/winservice.h | 2 +- bacula/src/filed/win32/winstat.cpp | 4 +- bacula/src/filed/win32/winstat.h | 21 +-- bacula/src/filed/win32/wintray.h | 2 +- bacula/src/jcr.h | 12 +- bacula/src/lib/bpipe.c | 2 +- bacula/src/lib/bsock.h | 20 +-- bacula/src/lib/util.c | 12 +- bacula/src/stored/Makefile.in | 4 +- bacula/src/stored/block.c | 2 +- bacula/src/stored/dev.c | 23 ++- bacula/src/stored/dev.h | 42 +----- bacula/src/stored/dircmd.c | 154 +------------------- bacula/src/stored/mount.c | 1 + bacula/src/stored/status.c | 201 ++++++++++++++++++++++++++ bacula/src/stored/stored_conf.h | 21 ++- bacula/src/version.h | 4 +- 25 files changed, 392 insertions(+), 299 deletions(-) create mode 100644 bacula/src/stored/status.c diff --git a/bacula/ChangeLog b/bacula/ChangeLog index cb7065b936..a34e1ce554 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,4 @@ -2003-05-20 Version 1.31 Beta 22May03 +2003-05-22 Version 1.31 Beta 22May03 - I discovered that C++ permits "prototyping" structures e.g. struct A; is a valid statement. This permitted me to eliminate all the void *jcr, in favor of JCR *jcr, which pointed out a number of bugs in block.c. diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index 0286d742eb..9bb85499aa 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -1164,6 +1164,7 @@ aix) PSCMD="ps -e -o pid,comm" PFILES="${PFILES} \ platforms/aix/Makefile" + TAPEDRIVE="/dev/rmt0.1" ;; alpha) DISTVER=`uname -r` diff --git a/bacula/configure b/bacula/configure index 52093d7ba0..e0b638c509 100755 --- a/bacula/configure +++ b/bacula/configure @@ -9466,6 +9466,7 @@ aix) PSCMD="ps -e -o pid,comm" PFILES="${PFILES} \ platforms/aix/Makefile" + TAPEDRIVE="/dev/rmt0.1" ;; alpha) DISTVER=`uname -r` diff --git a/bacula/kernstodo b/bacula/kernstodo index 299e2ca95d..8d9fc909a7 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -25,6 +25,24 @@ Testing to do: (painful) - Figure out how to use ssh or stunnel to protect Bacula communications. For 1.31 release: +- Add SDWriteSeqNo to SD, and probably Read on FD side. +- Make sure all restore counters are working correctly in the FD. +- When all cassettes in magazine are used, got: + 22-May-2003 18:24 undef-sd: 3304 Autochanger "load slot 1" status is OK. + 22-May-2003 18:24 undef-sd: NightlySave.2003-05-22_14.08.16 Warning: mount.c:245 Director wanted Volume "TestVolume0009". + Current Volume "TestVolume0005" not acceptable because: + 1998 Volume "TestVolume0005" not Append or Recycle. + 22-May-2003 18:24 undef-sd: NightlySave.2003-05-22_14.08.16 Error: Autochanger Volume "TestVolume0009" not found in slot 1. + Setting slot to zero in catalog. + 22-May-2003 18:24 undef-sd: Please mount Volume "TestVolume0009" on Storage Device "ARCHIVE 4586" for Job NightlySave.2003-05-22_14 + .08.16 + Use "mount" command to release Job. + 22-May-2003 19:24 undef-sd: Please mount Volume "TestVolume0009" on Storage Device "ARCHIVE 4586" for Job NightlySave.2003-05-22_14 + .08.16 + Use "mount" command to release Job. + +- SD Bytes Read is wrong. +- Configure mtx-changer to have correct path to mtx. - Look at ALL higher level routines that call block.c to be sure they don't expect something in errmsg. - Fix Verify VolumeToCatalog to use BSRs -- it is broken. diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 17aaec9146..6e5ab105ff 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -279,7 +279,7 @@ typedef uint32_t JobId_t; * it also contains fields found in the JobMedia record. */ /* Job record */ -typedef struct { +struct JOB_DBR { JobId_t JobId; char Job[MAX_NAME_LENGTH]; /* Job unique name */ char Name[MAX_NAME_LENGTH]; /* Job base name */ @@ -315,13 +315,13 @@ typedef struct { char cEndTime[MAX_TIME_LENGTH]; /* Extra stuff not in DB */ faddr_t rec_addr; -} JOB_DBR; +}; /* Job Media information used to create the media records * for each Volume used for the job. */ /* JobMedia record */ -typedef struct { +struct JOBMEDIA_DBR { uint32_t JobMediaId; /* record id */ JobId_t JobId; /* JobId */ uint32_t MediaId; /* MediaId */ @@ -331,10 +331,11 @@ typedef struct { uint32_t EndFile; /* End file on Volume */ uint32_t StartBlock; /* start block on tape */ uint32_t EndBlock; /* last block */ -} JOBMEDIA_DBR; +}; + /* Volume Parameter structure */ -typedef struct { +struct VOL_PARAMS { char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ uint32_t FirstIndex; /* First index this Volume */ uint32_t LastIndex; /* Last index this Volume */ @@ -342,14 +343,14 @@ typedef struct { uint32_t EndFile; /* End file on Volume */ uint32_t StartBlock; /* start block on tape */ uint32_t EndBlock; /* last block */ -} VOL_PARAMS; +}; /* Attributes record -- NOT same as in database because * in general, this "record" creates multiple database * records (e.g. pathname, filename, fileattributes). */ -typedef struct { +struct ATTR_DBR { char *fname; /* full path & filename */ char *link; /* link if any */ char *attr; /* attributes statp */ @@ -360,11 +361,11 @@ typedef struct { uint32_t PathId; uint32_t FilenameId; FileId_t FileId; -} ATTR_DBR; +}; /* File record -- same format as database */ -typedef struct { +struct FILE_DBR { FileId_t FileId; uint32_t FileIndex; JobId_t JobId; @@ -375,10 +376,10 @@ typedef struct { /* int Status; */ char SIG[50]; int SigType; /* NO_SIG/MD5_SIG/SHA1_SIG */ -} FILE_DBR; +}; /* Pool record -- same format as database */ -typedef struct { +struct POOL_DBR { uint32_t PoolId; char Name[MAX_NAME_LENGTH]; /* Pool name */ uint32_t NumVols; /* total number of volumes */ @@ -397,10 +398,10 @@ typedef struct { char LabelFormat[MAX_NAME_LENGTH]; /* Extra stuff not in DB */ faddr_t rec_addr; -} POOL_DBR; +}; /* Media record -- same as the database */ -typedef struct { +struct MEDIA_DBR { uint32_t MediaId; /* Unique volume id */ char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ char MediaType[MAX_NAME_LENGTH]; /* Media type */ @@ -433,24 +434,24 @@ typedef struct { char cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */ char cLastWritten[MAX_TIME_LENGTH]; /* LastWritten returned from DB */ char cLabelData[MAX_TIME_LENGTH]; /* LabelData returned from DB */ -} MEDIA_DBR; +}; /* Client record -- same as the database */ -typedef struct { +struct CLIENT_DBR { uint32_t ClientId; /* Unique Client id */ int AutoPrune; utime_t FileRetention; utime_t JobRetention; char Name[MAX_NAME_LENGTH]; /* Client name */ char Uname[256]; /* Uname for client */ -} CLIENT_DBR; +}; /* FileSet record -- same as the database */ -typedef struct { +struct FILESET_DBR { uint32_t FileSetId; /* Unique FileSet id */ char FileSet[MAX_NAME_LENGTH]; /* FileSet name */ char MD5[50]; /* MD5 signature of include/exclude */ -} FILESET_DBR; +}; #include "protos.h" diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index c687b1b4e2..c8d60d57e1 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -47,49 +47,56 @@ extern char *uar_sel_all_temp1, *uar_sel_fileset, *uar_mediatype; /* Context for insert_tree_handler() */ -typedef struct s_tree_ctx { +struct TREE_CTX { TREE_ROOT *root; /* root */ TREE_NODE *node; /* current node */ TREE_NODE *avail_node; /* unused node last insert */ int cnt; /* count for user feedback */ UAContext *ua; -} TREE_CTX; +}; /* Main structure for obtaining JobIds */ -typedef struct s_jobids { +struct JobIds { utime_t JobTDate; uint32_t TotalFiles; char ClientName[MAX_NAME_LENGTH]; char JobIds[200]; STORE *store; -} JobIds; +}; -/* FileIndex entry in bootstrap record */ -typedef struct s_rbsr_findex { - struct s_rbsr_findex *next; +/* FileIndex entry in restore bootstrap record */ +struct RBSR_FINDEX { + RBSR_FINDEX *next; int32_t findex; int32_t findex2; -} RBSR_FINDEX; - -/* Restore bootstrap record -- not the real one, but useful here */ -typedef struct s_rbsr { - struct s_rbsr *next; /* next JobId */ +}; + +/* + * Restore bootstrap record -- not the real one, but useful here + * The restore bsr is a chain of BSR records (linked by next). + * Each BSR represents a single JobId, and within it, it + * contains a linked list of file indexes for that JobId. + * The complete_bsr() routine, will then add all the volumes + * on which the Job is stored to the BSR. + */ +struct RBSR { + RBSR *next; /* next JobId */ uint32_t JobId; /* JobId this bsr */ uint32_t VolSessionId; uint32_t VolSessionTime; int VolCount; /* Volume parameter count */ VOL_PARAMS *VolParams; /* Volume, start/end file/blocks */ RBSR_FINDEX *fi; /* File indexes this JobId */ -} RBSR; +}; -typedef struct s_name_ctx { +struct NAME_LIST { char **name; /* list of names */ int num_ids; /* ids stored */ int max_ids; /* size of array */ int num_del; /* number deleted */ int tot_ids; /* total to process */ -} NAME_LIST; +}; #define MAX_ID_LIST_LEN 1000000 @@ -113,6 +120,7 @@ static void print_name_list(UAContext *ua, NAME_LIST *name_list); static int unique_name_list_handler(void *ctx, int num_fields, char **row); static void free_name_list(NAME_LIST *name_list); static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JobIds *ji); +static RBSR *sort_bsr(RBSR *bsr); /* @@ -274,7 +282,7 @@ int restorecmd(UAContext *ua, char *cmd) if (where) { Mmsg(&ua->cmd, "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"" - "where=\"%s\"", + " where=\"%s\"", job->hdr.name, ji.ClientName, ji.store?ji.store->hdr.name:"", working_directory, where); } else { @@ -719,7 +727,6 @@ static int write_bsr_file(UAContext *ua, RBSR *bsr) FILE *fd; POOLMEM *fname = get_pool_memory(PM_MESSAGE); int stat; - RBSR *nbsr; Mmsg(&fname, "%s/restore.bsr", working_directory); fd = fopen(fname, "w+"); @@ -729,14 +736,19 @@ static int write_bsr_file(UAContext *ua, RBSR *bsr) free_pool_memory(fname); return 0; } + /* Sort the bsr chain */ + bsr = sort_bsr(bsr); + /* Write them to file */ write_bsr(ua, bsr, fd); stat = !ferror(fd); fclose(fd); bsendmsg(ua, _("Bootstrap records written to %s\n"), fname); + + /* Tell the user what he will need to mount */ bsendmsg(ua, _("\nThe restore job will require the following Volumes:\n")); /* Create Unique list of Volumes using prompt list */ start_prompt(ua, ""); - for (nbsr=bsr; nbsr; nbsr=nbsr->next) { + for (RBSR *nbsr=bsr; nbsr; nbsr=nbsr->next) { for (int i=0; i < nbsr->VolCount; i++) { add_prompt(ua, nbsr->VolParams[i].VolumeName); } @@ -751,6 +763,40 @@ static int write_bsr_file(UAContext *ua, RBSR *bsr) return stat; } +int comp_vol_params(const void *v1, const void *v2) +{ + VOL_PARAMS *vol1 = (VOL_PARAMS *)v1; + VOL_PARAMS *vol2 = (VOL_PARAMS *)v2; + + if (vol1->FirstIndex < vol2->FirstIndex) { + return -1; + } else if (vol1->FirstIndex > vol2->FirstIndex) { + return 1; + } else { + return 0; + } +} + +/* + * First sort the bsr chain, then sort the VolParams + */ +static RBSR *sort_bsr(RBSR *bsr) +{ + if (!bsr) { + return bsr; + } + /* ****FIXME**** sort the bsr chain */ + /* Sort the VolParams for each bsr */ + for (RBSR *nbsr=bsr; nbsr; nbsr=nbsr->next) { + if (nbsr->VolCount > 1) { + Dmsg1(100, "VolCount=%d\n", nbsr->VolCount); + qsort((void *)nbsr->VolParams, nbsr->VolCount, sizeof(VOL_PARAMS), + comp_vol_params); + } + } + return bsr; +} + static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) { if (bsr) { diff --git a/bacula/src/filed/win32/winevents.h b/bacula/src/filed/win32/winevents.h index 466760b3c7..a28d66e124 100755 --- a/bacula/src/filed/win32/winevents.h +++ b/bacula/src/filed/win32/winevents.h @@ -1,21 +1,22 @@ /* Object implementing the Events dialog for Bacula */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2003 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ diff --git a/bacula/src/filed/win32/winservice.cpp b/bacula/src/filed/win32/winservice.cpp index aa6bcafffc..98cb4140dd 100755 --- a/bacula/src/filed/win32/winservice.cpp +++ b/bacula/src/filed/win32/winservice.cpp @@ -1,6 +1,6 @@ // Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. // -// This file is part of the VNC system. +// This file was part of the VNC system. // // The VNC system is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/bacula/src/filed/win32/winservice.h b/bacula/src/filed/win32/winservice.h index 2747995056..589f94a54c 100755 --- a/bacula/src/filed/win32/winservice.h +++ b/bacula/src/filed/win32/winservice.h @@ -1,6 +1,6 @@ // Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. // -// This file is part of the ups system. +// This file was part of the ups system. // // The ups system is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/bacula/src/filed/win32/winstat.cpp b/bacula/src/filed/win32/winstat.cpp index f9415dfa04..79da6dcc7e 100755 --- a/bacula/src/filed/win32/winstat.cpp +++ b/bacula/src/filed/win32/winstat.cpp @@ -44,8 +44,8 @@ void bacStatus::Show(BOOL show) { if (show && !visible) { - DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_STATUS), NULL, - (DLGPROC)DialogProc, (LONG)this); + DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_STATUS), NULL, + (DLGPROC)DialogProc, (LONG)this); } } diff --git a/bacula/src/filed/win32/winstat.h b/bacula/src/filed/win32/winstat.h index 008ad56e44..e5c29a859b 100755 --- a/bacula/src/filed/win32/winstat.h +++ b/bacula/src/filed/win32/winstat.h @@ -3,22 +3,23 @@ * */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2003 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ diff --git a/bacula/src/filed/win32/wintray.h b/bacula/src/filed/win32/wintray.h index 34b422a518..0b210282af 100755 --- a/bacula/src/filed/win32/wintray.h +++ b/bacula/src/filed/win32/wintray.h @@ -1,6 +1,6 @@ // Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. // -// This file is part of the VNC system. +// This file was part of the VNC system. // // The VNC system is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 4a2d72b174..02bc36c4f9 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -92,7 +92,7 @@ struct JCR { BSOCK *store_bsock; /* Storage connection socket */ BSOCK *file_bsock; /* File daemon connection socket */ JCR_free_HANDLER *daemon_free_jcr; /* Local free routine */ - int use_count; /* use count */ + volatile int use_count; /* use count */ POOLMEM *errmsg; /* edited error message */ char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */ uint32_t JobId; /* Director's JobId */ @@ -103,7 +103,7 @@ struct JCR { uint64_t JobBytes; /* Number of bytes processed this job */ uint64_t ReadBytes; /* Bytes read -- before compression */ uint32_t Errors; /* Number of non-fatal errors */ - int JobStatus; /* ready, running, blocked, terminated */ + volatile int JobStatus; /* ready, running, blocked, terminated */ int JobType; /* backup, restore, verify ... */ int JobLevel; /* Job level */ int authenticated; /* set when client authenticated */ @@ -126,7 +126,7 @@ struct JCR { pthread_t SD_msg_chan; /* Message channel thread id */ pthread_cond_t term_wait; /* Wait for job termination */ workq_ele_t *work_item; /* Work queue item if scheduled */ - int msg_thread_done; /* Set when Storage message thread terms */ + volatile int msg_thread_done; /* Set when Storage message thread terms */ BSOCK *ua; /* User agent */ JOB *job; /* Job resource */ STORE *store; /* Storage resource */ @@ -135,8 +135,8 @@ struct JCR { FILESET *fileset; /* FileSet resource */ CAT *catalog; /* Catalog resource */ MSGS *messages; /* Default message handler */ - int SDJobStatus; /* Storage Job Status */ - int FDJobStatus; /* File daemon Job Status */ + volatile int SDJobStatus; /* Storage Job Status */ + volatile int FDJobStatus; /* File daemon Job Status */ int mode; /* manual/auto run */ B_DB *db; /* database pointer */ uint32_t MediaId; /* DB record IDs associated with this job */ @@ -180,7 +180,7 @@ struct JCR { uint32_t StartBlock; uint32_t EndBlock; pthread_t heartbeat_id; /* id of heartbeat thread */ - BSOCK *hb_bsock; /* duped SD socket */ + volatile BSOCK *hb_bsock; /* duped SD socket */ #endif /* FILE_DAEMON */ diff --git a/bacula/src/lib/bpipe.c b/bacula/src/lib/bpipe.c index 975c5f6896..577fc4d188 100644 --- a/bacula/src/lib/bpipe.c +++ b/bacula/src/lib/bpipe.c @@ -78,7 +78,7 @@ BPIPE *open_bpipe(char *prog, int wait, char *mode) } /* Start worker process */ switch (bpipe->worker_pid = fork()) { - case -1: + case -1: /* error */ free(bpipe); return NULL; diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index 5ca7d1ad7e..92aa2596c5 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -31,31 +31,31 @@ */ -typedef struct s_bsock { +struct BSOCK { uint64_t read_seqno; /* read sequence number */ - uint32_t in_msg_no; /* intput message number */ + uint32_t in_msg_no; /* input message number */ uint32_t out_msg_no; /* output message number */ int fd; /* socket file descriptor */ int32_t msglen; /* message length */ int port; /* desired port */ - int errors; /* set if errors on socket */ - int suppress_error_msgs; /* set to suppress error messages */ + volatile int errors; /* set if errors on socket */ + volatile int suppress_error_msgs; /* set to suppress error messages */ int b_errno; /* bsock errno */ - time_t timer_start; /* time started read/write */ - int timed_out; /* timed out in read/write */ - int timeout; /* time out after this value */ - int terminated; /* set when BNET_TERMINATE arrives */ + volatile time_t timer_start; /* time started read/write */ + volatile int timed_out; /* timed out in read/write */ + volatile int timeout; /* time out after this value */ + volatile int terminated; /* set when BNET_TERMINATE arrives */ int duped; /* set if duped BSOCK */ POOLMEM *msg; /* message pool buffer */ char *who; /* Name of daemon to which we are talking */ char *host; /* Host name/IP */ POOLMEM *errmsg; /* edited error message (to be implemented) */ RES *res; /* Resource to which we are connected */ - struct s_bsock *next; /* next BSOCK if duped */ + BSOCK *next; /* next BSOCK if duped */ int spool; /* set for spooling */ FILE *spool_fd; /* spooling file */ JCR *jcr; /* jcr or NULL for error msgs */ -} BSOCK; +}; /* Signal definitions for use in bnet_sig() */ #define BNET_EOD -1 /* End of data stream, new data may follow */ diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 1d1b525817..4433febb4f 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -440,10 +440,15 @@ int do_shell_expansion(char *name, int name_len) if ((shellcmd = getenv("SHELL")) == NULL) { shellcmd = "/bin/sh"; } - close(1); dup(pfd[1]); /* attach pipes to stdin and stdout */ +#ifdef xxx + close(1); dup(pfd[1]); /* attach pipes to stdout and stderr */ close(2); dup(pfd[1]); for (i = 3; i < 32; i++) /* close everything else */ close(i); +#endif + close(pfd[0]); /* close stdin */ + dup2(pfd[1], 1); /* attach to stdout */ + dup2(pfd[1], 2); /* and stderr */ strcpy(echout, "echo "); /* form echo command */ bstrncat(echout, name, sizeof(echout)); execl(shellcmd, shellcmd, "-c", echout, NULL); /* give to shell */ @@ -452,7 +457,10 @@ int do_shell_expansion(char *name, int name_len) default: /* parent */ /* read output from child */ echout[0] = 0; - i = read(pfd[0], echout, sizeof echout); + do { + i = read(pfd[0], echout, sizeof echout); + } while (i == -1 && errno == EINTR); + if (i > 0) { echout[--i] = 0; /* set end of string */ /* look for first line. */ diff --git a/bacula/src/stored/Makefile.in b/bacula/src/stored/Makefile.in index 753f91b162..df205d0487 100644 --- a/bacula/src/stored/Makefile.in +++ b/bacula/src/stored/Makefile.in @@ -23,13 +23,13 @@ SVRSRCS = stored.c autochanger.c acquire.c append.c \ block.c dev.c \ device.c dircmd.c fd_cmds.c job.c \ label.c match_bsr.c parse_bsr.c \ - read.c record.c stored_conf.c mount.c + read.c record.c status.c stored_conf.c mount.c SVROBJS = stored.o autochanger.o acquire.o append.o \ askdir.o authenticate.o \ block.o dev.o \ device.o dircmd.o fd_cmds.o job.o \ label.o match_bsr.o mount.o parse_bsr.o \ - read.o record.o stored_conf.o + read.o record.o status.o stored_conf.o # btape TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \ diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index c95096aa0f..6ca1575d83 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -395,7 +395,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) wlen, stat, dev->dev_errno, strerror(dev->dev_errno)); if (stat == -1) { - Jmsg2(jcr, M_ERROR, 0, _("Write error on device %s. ERR=%s.\n"), + Jmsg(jcr, M_ERROR, 0, _("Write error on device %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); } else { Jmsg3(jcr, M_INFO, 0, _("End of media on device %s. Write of %u bytes got %d.\n"), diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 98eada35dc..d7f5e56a9d 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -521,7 +521,7 @@ status_dev(DEVICE *dev, uint32_t *status) if (dev->state & (ST_EOT | ST_WEOT)) { stat |= BMT_EOD; - Dmsg0(-20, " EOD"); + Dmsg0(-20, " EOD-"); } if (dev->state & ST_EOF) { stat |= BMT_EOF; @@ -558,7 +558,7 @@ status_dev(DEVICE *dev, uint32_t *status) } 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; @@ -1191,25 +1191,22 @@ term_dev(DEVICE *dev) } -/* To make following two functions more readable */ - -#define attached_jcrs ((JCR *)(dev->attached_jcrs)) void attach_jcr_to_device(DEVICE *dev, JCR *jcr) { - jcr->prev_dev = NULL; - jcr->next_dev = attached_jcrs; - if (attached_jcrs) { - attached_jcrs->prev_dev = jcr; + jcr->prev_dev = (JCR *)NULL; + jcr->next_dev = dev->attached_jcrs; + if (dev->attached_jcrs) { + dev->attached_jcrs->prev_dev = jcr; } - attached_jcrs = jcr; + dev->attached_jcrs = jcr; Dmsg1(100, "Attached Job %s\n", jcr->Job); } void detach_jcr_from_device(DEVICE *dev, JCR *jcr) { if (!jcr->prev_dev) { - attached_jcrs = jcr->next_dev; + dev->attached_jcrs = jcr->next_dev; } else { jcr->prev_dev->next_dev = jcr->next_dev; } @@ -1222,8 +1219,8 @@ void detach_jcr_from_device(DEVICE *dev, JCR *jcr) JCR *next_attached_jcr(DEVICE *dev, JCR *jcr) { - if (jcr == NULL) { - return attached_jcrs; + if (jcr == (JCR *)NULL) { + return dev->attached_jcrs; } return jcr->next_dev; } diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 515ef7df09..449fd78994 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -139,12 +139,13 @@ typedef struct s_steal_lock { int dev_blocked; /* state */ } bsteal_lock_t; +struct DEVRES; /* Device resource defined in stored_conf.h */ /* Device structure definition */ -typedef struct s_device { - struct s_device *next; /* pointer to next open device */ - struct s_device *prev; /* pointer to prev open device */ - void *attached_jcrs; /* attached JCR list */ +struct DEVICE { + DEVICE *next; /* pointer to next open device */ + DEVICE *prev; /* pointer to prev open device */ + JCR *attached_jcrs; /* attached JCR list */ pthread_mutex_t mutex; /* access control */ pthread_cond_t wait; /* thread wait variable */ pthread_cond_t wait_next_vol; /* wait for tape to be mounted */ @@ -173,44 +174,15 @@ typedef struct s_device { 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 */ - void *device; /* pointer to Device Resource */ + DEVRES *device; /* pointer to Device Resource */ btimer_id tid; /* timer id */ VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */ VOLUME_LABEL VolHdr; /* Actual volume label */ -} DEVICE; +}; - - -#ifdef SunOS -#define DEFAULT_TAPE_DRIVE "/dev/rmt/0cbn" -#endif -#ifdef AIX -#define DEFAULT_TAPE_DRIVE "/dev/rmt0.1" -#endif -#ifdef SGI -#define DEFAULT_TAPE_DRIVE "/dev/tps0d4nr" -#endif -#ifdef Linux -#define DEFAULT_TAPE_DRIVE "/dev/nst0" -#endif -#ifdef OSF -#define DEFAULT_TAPE_DRIVE "/dev/nrmt0" -#endif -#ifdef HPUX -#define DEFAULT_TAPE_DRIVE "/dev/rmt/0hnb" -#endif -#ifdef FreeBSD -#define DEFAULT_TAPE_DRIVE "/dev/nrst0" -#endif - -/* Default default */ -#ifndef DEFAULT_TAPE_DRIVE -#define DEFAULT_TAPE_DRIVE "/dev/nst0" -#endif - /* Get some definition of function to position * to the end of the medium in MTEOM. System * dependent. Arrgggg! diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index a62a315736..433940f7a2 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -59,6 +59,7 @@ static char OKsetdebug[] = "3000 OK setdebug=%d\n"; /* Imported functions */ extern void terminate_child(); extern int job_cmd(JCR *jcr); +extern int status_cmd(JCR *sjcr); /* Forward referenced functions */ static int label_cmd(JCR *jcr); @@ -67,13 +68,11 @@ static int setdebug_cmd(JCR *jcr); static int cancel_cmd(JCR *cjcr); static int mount_cmd(JCR *jcr); static int unmount_cmd(JCR *jcr); -static int status_cmd(JCR *sjcr); static int autochanger_cmd(JCR *sjcr); static int do_label(JCR *jcr, int relabel); static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, char *newname, char *poolname, int Slot, int relabel); -static void send_blocked_status(JCR *jcr, DEVICE *dev); struct s_cmds { char *cmd; @@ -666,157 +665,6 @@ static int unmount_cmd(JCR *jcr) return 1; } -/* - * Status command from Director - */ -static int status_cmd(JCR *jcr) -{ - DEVRES *device; - DEVICE *dev; - int found, bps, sec, bpb; - BSOCK *user = jcr->dir_bsock; - char dt[MAX_TIME_LENGTH]; - char b1[30], b2[30], b3[30]; - - bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ")\n", my_name); - bstrftime(dt, sizeof(dt), daemon_start_time); - bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs, - last_job.NumJobs == 1 ? "" : "s"); - if (last_job.NumJobs > 0) { - char termstat[30]; - - bstrftime(dt, sizeof(dt), last_job.end_time); - bnet_fsend(user, _("Last Job %s finished at %s\n"), last_job.Job, dt); - - jobstatus_to_ascii(last_job.JobStatus, termstat, sizeof(termstat)); - bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"), - edit_uint64_with_commas(last_job.JobFiles, b1), - edit_uint64_with_commas(last_job.JobBytes, b2), - termstat); - } - - LockRes(); - for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { - for (dev=device->dev; dev; dev=dev->next) { - if (dev->state & ST_OPENED) { - if (dev->state & ST_LABEL) { - 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)); - } - send_blocked_status(jcr, dev); - if (dev->state & ST_APPEND) { - bpb = dev->VolCatInfo.VolCatBlocks; - if (bpb <= 0) { - bpb = 1; - } - bpb = dev->VolCatInfo.VolCatBytes / bpb; - 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 { /* reading */ - bpb = dev->VolCatInfo.VolCatReads; - if (bpb <= 0) { - bpb = 1; - } - bpb = dev->VolCatInfo.VolCatRBytes / bpb; - 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"), - 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)); - send_blocked_status(jcr, dev); - } - } - } - UnlockRes(); - - found = 0; - lock_jcr_chain(); - /* NOTE, we reuse a calling argument jcr. Be warned! */ - for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { - if (jcr->JobStatus == JS_WaitFD) { - bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"), - job_type_to_str(jcr->JobType), jcr->Job); - } - if (jcr->device) { - bnet_fsend(user, _("%s %s job %s is using device %s volume %s\n"), - job_level_to_str(jcr->JobLevel), - job_type_to_str(jcr->JobType), - jcr->Job, jcr->device->device_name, - jcr->VolumeName); - 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"), - edit_uint64_with_commas(jcr->JobFiles, b1), - edit_uint64_with_commas(jcr->JobBytes, b2), - edit_uint64_with_commas(bps, b3)); - found = 1; -#ifdef DEBUG - if (jcr->file_bsock) { - bnet_fsend(user, " FDReadSeqNo=%" lld " fd=%d\n", - jcr->file_bsock->read_seqno, jcr->file_bsock->fd); - } else { - bnet_fsend(user, " FDSocket closed\n"); - } -#endif - } - free_locked_jcr(jcr); - } - unlock_jcr_chain(); - if (!found) { - bnet_fsend(user, _("No jobs running.\n")); - } - -#ifdef full_status - bnet_fsend(user, "\n\n"); - dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user); -#endif - bnet_fsend(user, "====\n"); - - bnet_sig(user, BNET_EOD); - return 1; -} - -static void send_blocked_status(JCR *jcr, DEVICE *dev) -{ - BSOCK *user = jcr->dir_bsock; - - switch (dev->dev_blocked) { - case BST_UNMOUNTED: - bnet_fsend(user, _(" Device is BLOCKED. User unmounted.\n")); - break; - case BST_UNMOUNTED_WAITING_FOR_SYSOP: - bnet_fsend(user, _(" Device is BLOCKED. User unmounted during wait for media/mount.\n")); - break; - case BST_WAITING_FOR_SYSOP: - if (jcr->JobStatus == JS_WaitMount) { - bnet_fsend(user, _(" Device is BLOCKED waiting for mount.\n")); - } else { - bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n")); - } - break; - case BST_DOING_ACQUIRE: - bnet_fsend(user, _(" Device is being initialized.\n")); - break; - case BST_WRITING_LABEL: - bnet_fsend(user, _(" Device is blocked labeling a Volume.\n")); - break; - default: - break; - } -} /* * Autochanger command from Director diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index eb37ee80fb..e02f791944 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -306,6 +306,7 @@ mount_error: dev->VolCatInfo.VolCatFiles = 0; dev->VolCatInfo.VolCatErrors = 0; dev->VolCatInfo.VolCatBlocks = 0; + dev->VolCatInfo.VolCatRBytes = 0; if (recycle) { dev->VolCatInfo.VolCatMounts++; dev->VolCatInfo.VolCatRecycles++; diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c new file mode 100644 index 0000000000..53401ed411 --- /dev/null +++ b/bacula/src/stored/status.c @@ -0,0 +1,201 @@ +/* + * This file handles the status command + * + * Kern Sibbald, May MMIII + * + * Version $Id$ + * + */ +/* + Copyright (C) 2000-2003 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "stored.h" + +/* Exported variables */ + +/* Imported variables */ +extern BSOCK *filed_chan; +extern int r_first, r_last; +extern struct s_res resources[]; +extern char my_name[]; +extern time_t daemon_start_time; +extern struct s_last_job last_job; + +/* Static variables */ + + +/* Forward referenced functions */ +static void send_blocked_status(JCR *jcr, DEVICE *dev); + + +/* + * Status command from Director + */ +int status_cmd(JCR *jcr) +{ + DEVRES *device; + DEVICE *dev; + int found, bps, sec, bpb; + BSOCK *user = jcr->dir_bsock; + char dt[MAX_TIME_LENGTH]; + char b1[30], b2[30], b3[30]; + + bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ")\n", my_name); + bstrftime(dt, sizeof(dt), daemon_start_time); + bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs, + last_job.NumJobs == 1 ? "" : "s"); + if (last_job.NumJobs > 0) { + char termstat[30]; + + bstrftime(dt, sizeof(dt), last_job.end_time); + bnet_fsend(user, _("Last Job %s finished at %s\n"), last_job.Job, dt); + + jobstatus_to_ascii(last_job.JobStatus, termstat, sizeof(termstat)); + bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"), + edit_uint64_with_commas(last_job.JobFiles, b1), + edit_uint64_with_commas(last_job.JobBytes, b2), + termstat); + } + + LockRes(); + for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { + for (dev=device->dev; dev; dev=dev->next) { + if (dev->state & ST_OPENED) { + if (dev->state & ST_LABEL) { + 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)); + } + send_blocked_status(jcr, dev); + if (dev->state & ST_APPEND) { + bpb = dev->VolCatInfo.VolCatBlocks; + if (bpb <= 0) { + bpb = 1; + } + bpb = dev->VolCatInfo.VolCatBytes / bpb; + 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 { /* reading */ + bpb = dev->VolCatInfo.VolCatReads; + if (bpb <= 0) { + bpb = 1; + } + bpb = dev->VolCatInfo.VolCatRBytes / bpb; + 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"), + 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)); + send_blocked_status(jcr, dev); + } + } + } + UnlockRes(); + + found = 0; + lock_jcr_chain(); + /* NOTE, we reuse a calling argument jcr. Be warned! */ + for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + if (jcr->JobStatus == JS_WaitFD) { + bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"), + job_type_to_str(jcr->JobType), jcr->Job); + } + if (jcr->device) { + bnet_fsend(user, _("%s %s job %s is using device %s volume %s\n"), + job_level_to_str(jcr->JobLevel), + job_type_to_str(jcr->JobType), + jcr->Job, jcr->device->device_name, + jcr->VolumeName); + 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"), + edit_uint64_with_commas(jcr->JobFiles, b1), + edit_uint64_with_commas(jcr->JobBytes, b2), + edit_uint64_with_commas(bps, b3)); + found = 1; +#ifdef DEBUG + if (jcr->file_bsock) { + 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"); + } +#endif + } + free_locked_jcr(jcr); + } + unlock_jcr_chain(); + if (!found) { + bnet_fsend(user, _("No jobs running.\n")); + } + +#ifdef full_status + bnet_fsend(user, "\n\n"); + dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user); +#endif + bnet_fsend(user, "====\n"); + + bnet_sig(user, BNET_EOD); + return 1; +} + +static void send_blocked_status(JCR *jcr, DEVICE *dev) +{ + BSOCK *user = jcr->dir_bsock; + + switch (dev->dev_blocked) { + case BST_UNMOUNTED: + bnet_fsend(user, _(" Device is BLOCKED. User unmounted.\n")); + break; + case BST_UNMOUNTED_WAITING_FOR_SYSOP: + bnet_fsend(user, _(" Device is BLOCKED. User unmounted during wait for media/mount.\n")); + break; + case BST_WAITING_FOR_SYSOP: + if (jcr->JobStatus == JS_WaitMount) { + bnet_fsend(user, _(" Device is BLOCKED waiting for mount.\n")); + } else { + bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n")); + } + break; + case BST_DOING_ACQUIRE: + bnet_fsend(user, _(" Device is being initialized.\n")); + break; + case BST_WRITING_LABEL: + bnet_fsend(user, _(" Device is blocked labeling a Volume.\n")); + break; + default: + break; +} +} diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 91d2560896..9dcd977b1e 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -40,14 +40,13 @@ #define R_BACKUP 3024 /* Definition of the contents of each Resource */ -struct s_res_dir { +struct DIRRES { RES hdr; char *password; /* Director password */ char *address; /* Director IP address or zero */ int enable_ssl; /* Use SSL with this Director */ }; -typedef struct s_res_dir DIRRES; /* Storage daemon "global" definitions */ @@ -69,7 +68,7 @@ struct s_res_store { typedef struct s_res_store STORES; /* Device specific definitions */ -struct s_res_dev { +struct DEVRES { RES hdr; char *media_type; /* User assigned media type */ @@ -90,13 +89,11 @@ struct s_res_dev { int64_t volume_capacity; /* advisory capacity */ DEVICE *dev; /* Pointer to phyical dev -- set at runtime */ }; -typedef struct s_res_dev DEVRES; - -union u_res { - struct s_res_dir res_dir; - struct s_res_store res_store; - struct s_res_dev res_dev; - struct s_res_msgs res_msgs; - RES hdr; + +union URES { + DIRRES res_dir; + STORES res_store; + DEVRES res_dev; + MSGS res_msgs; + RES hdr; }; -typedef union u_res URES; diff --git a/bacula/src/version.h b/bacula/src/version.h index 87157f7780..6e82990dd3 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.31" #define VSTRING "1" -#define BDATE "22 May 2003" -#define LSMDATE "22May03" +#define BDATE "23 May 2003" +#define LSMDATE "23May03" /* Debug flags */ #define DEBUG 1 -- 2.39.5