len = sizeof(mr);
while (fread(&mr, len, 1, mdb->mediafd) > 0) {
Mmsg(&mdb->cmd, " %-10s %17s %-15s %s\n",
- mr.VolStatus, edit_uint_with_commas(mr.VolBytes, ewc),
+ mr.VolStatus, edit_uint64_with_commas(mr.VolBytes, ewc),
mr.MediaType, mr.VolumeName);
sendit(ctx, mdb->cmd);
}
strftime(dt, sizeof(dt), "%m-%d %H:%M", &tm);
Mmsg(&mdb->cmd, " %7d %-10s %c %c %14s %10s %c %s\n",
ojr.JobId, dt, (char)ojr.Type, (char)ojr.Level,
- edit_uint_with_commas(ojr.JobBytes, ewc1),
- edit_uint_with_commas(ojr.JobFiles, ewc2),
+ edit_uint64_with_commas(ojr.JobBytes, ewc1),
+ edit_uint64_with_commas(ojr.JobFiles, ewc2),
(char)ojr.JobStatus, ojr.Name);
sendit(ctx, mdb->cmd);
}
total_jobs++;
}
Mmsg(&mdb->cmd, " %7s %10s %15s\n",
- edit_uint_with_commas(total_jobs, ewc1),
- edit_uint_with_commas(total_files, ewc2),
- edit_uint_with_commas(total_bytes, ewc3));
+ edit_uint64_with_commas(total_jobs, ewc1),
+ edit_uint64_with_commas(total_files, ewc2),
+ edit_uint64_with_commas(total_bytes, ewc3));
sendit(ctx, mdb->cmd);
sendit(ctx, "=======================================\n");
V(mdb->mutex);
SchedTime DATETIME NOT NULL,
StartTime DATETIME NOT NULL,
EndTime DATETIME NOT NULL,
- StartDay INTEGER UNSIGNED NOT NULL,
+ StartDay BIGINT UNSIGNED NOT NULL,
VolSessionId INTEGER UNSIGNED NOT NULL,
VolSessionTime INTEGER UNSIGNED NOT NULL,
JobFiles INTEGER UNSIGNED NOT NULL,
mdb->num_rows = 1;
}
if (mdb->num_rows != 1) {
- m_msg(file, line, &mdb->errmsg, _("Insertion problem: affect_rows=%" lld "\n"), mdb->num_rows);
+ char ed1[30];
+ m_msg(file, line, &mdb->errmsg, _("Insertion problem: affect_rows=%s\n"),
+ edit_uint64(mdb->num_rows, ed1));
e_msg(file, line, M_FATAL, 0, mdb->errmsg); /* ***FIXME*** remove me */
return 0;
}
}
mdb->num_rows = sql_affected_rows(mdb);
if (mdb->num_rows != 1) {
- m_msg(file, line, &mdb->errmsg, _("Update problem: affect_rows=%" lld "\n"), mdb->num_rows);
+ char ed1[30];
+ m_msg(file, line, &mdb->errmsg, _("Update problem: affect_rows=%s\n"),
+ edit_uint64(mdb->num_rows, ed1));
e_msg(file, line, M_ERROR, 0, mdb->errmsg);
e_msg(file, line, M_ERROR, 0, "%s\n", cmd);
return 0;
struct tm tm;
int stat;
char *JobId;
- int32_t StartDay;
+ btime_t StartDay;
+ char ed1[30];
stime = jr->SchedTime;
localtime_r(&stime, &tm);
strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
- StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+ StartDay = (btime_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
date_encode(2000, 1, 1));
P(mdb->mutex);
/* Must create it */
Mmsg(&mdb->cmd,
"INSERT INTO Job (JobId, Job, Name, Type, Level, SchedTime, StartDay) VALUES \
-(%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %d)",
+(%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %s)",
JobId, jr->Job, jr->Name, (char)(jr->Type), (char)(jr->Level), dt,
- StartDay);
+ edit_uint64(StartDay, ed1));
if (!INSERT_DB(mdb, mdb->cmd)) {
Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"),
db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
{
int stat;
+ char ed1[30], ed2[30];
P(mdb->mutex);
Mmsg(&mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName=\"%s\"",
/* Must create it */
Mmsg(&mdb->cmd,
"INSERT INTO Media (VolumeName, MediaType, PoolId, VolMaxBytes, VolCapacityBytes, \
-VolStatus, Recycle) VALUES (\"%s\", \"%s\", %d, %" lld ", %" lld ", \"%s\", \"%s\")",
+VolStatus, Recycle) VALUES (\"%s\", \"%s\", %d, %s, %s, \"%s\", \"%s\")",
mr->VolumeName,
mr->MediaType, mr->PoolId,
- mr->VolMaxBytes, mr->VolCapacityBytes,
+ edit_uint64(mr->VolMaxBytes,ed1),
+ edit_uint64(mr->VolCapacityBytes, ed2),
mr->VolStatus, mr->Recycle);
if (!INSERT_DB(mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
- Mmsg2(&mdb->errmsg, _("More than one Path!: %" lld " for Path=%s\n"),
- mdb->num_rows, path);
+ char ed1[30];
+ Mmsg2(&mdb->errmsg, _("More than one Path!: %s for Path=%s\n"),
+ edit_uint64(mdb->num_rows, ed1), path);
Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
Emsg1(M_ERROR, 0, "%s\n", mdb->cmd);
}
Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path=\"%s\"", path);
if (QUERY_DB(mdb, mdb->cmd)) {
-
+ char ed1[30];
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
- Mmsg1(&mdb->errmsg, _("More than one Path!: %" lld "\n"), mdb->num_rows);
+ Mmsg1(&mdb->errmsg, _("More than one Path!: %s\n"),
+ edit_uint64(mdb->num_rows, ed1));
Emsg0(M_FATAL, 0, mdb->errmsg);
} else if (mdb->num_rows == 1) {
if ((row = sql_fetch_row(mdb)) == NULL) {
if (QUERY_DB(mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
- Mmsg1(&mdb->errmsg, _("More than one Pool!: %" lld "\n"), mdb->num_rows);
+ char ed1[30];
+ Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"),
+ edit_uint64(mdb->num_rows, ed1));
Emsg0(M_ERROR, 0, mdb->errmsg);
} else if (mdb->num_rows == 1) {
if ((row = sql_fetch_row(mdb)) == NULL) {
if (QUERY_DB(mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
- Mmsg1(&mdb->errmsg, _("More than one Volume!: %" lld "\n"), mdb->num_rows);
+ char ed1[30];
+ Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"),
+ edit_uint64(mdb->num_rows, ed1));
Emsg0(M_ERROR, 0, mdb->errmsg);
} else if (mdb->num_rows == 1) {
if ((row = sql_fetch_row(mdb)) == NULL) {
mr->PoolId = atoi(row[13]);
stat = mr->MediaId;
}
+ } else {
+ Mmsg0(&mdb->errmsg, _("Media record not found.\n"));
}
sql_free_result(mdb);
}
char dt[MAX_TIME_LENGTH];
time_t stime;
struct tm tm;
- int32_t StartDay;
+ btime_t StartDay;
int stat;
+ char ed1[30];
stime = jr->StartTime;
localtime_r(&stime, &tm);
strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
- StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+ StartDay = (btime_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
date_encode(2000, 1, 1));
P(mdb->mutex);
Mmsg(&mdb->cmd, "UPDATE Job SET Level='%c', StartTime=\"%s\", \
-ClientId=%d, StartDay=%d WHERE JobId=%d",
- (char)(jr->Level), dt, jr->ClientId, StartDay, jr->JobId);
+ClientId=%d, StartDay=%s WHERE JobId=%d",
+ (char)(jr->Level), dt, jr->ClientId, edit_uint64(StartDay, ed1), jr->JobId);
stat = UPDATE_DB(mdb, mdb->cmd);
V(mdb->mutex);
return stat;
time_t ttime;
struct tm tm;
int stat;
+ char ed1[30], ed2[30];
+ btime_t StartDay;
ttime = jr->EndTime;
localtime_r(&ttime, &tm);
strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
+ StartDay = (btime_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+ date_encode(2000, 1, 1));
P(mdb->mutex);
Mmsg(&mdb->cmd,
"UPDATE Job SET JobStatus='%c', EndTime='%s', \
-ClientId=%d, JobBytes=%" lld ", JobFiles=%d, JobErrors=%d, VolSessionId=%d, \
-VolSessionTime=%d, PoolId=%d, FileSetId=%d WHERE JobId=%d",
- (char)(jr->JobStatus), dt, jr->ClientId, jr->JobBytes, jr->JobFiles,
- jr->JobErrors, jr->VolSessionId, jr->VolSessionTime,
- jr->PoolId, jr->FileSetId, jr->JobId);
+ClientId=%d, JobBytes=%s, JobFiles=%d, JobErrors=%d, VolSessionId=%d, \
+VolSessionTime=%d, PoolId=%d, FileSetId=%d, StartDay=%s WHERE JobId=%d",
+ (char)(jr->JobStatus), dt, jr->ClientId, edit_uint64(jr->JobBytes, ed1),
+ jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime,
+ jr->PoolId, jr->FileSetId, edit_uint64(StartDay, ed2), jr->JobId);
stat = UPDATE_DB(mdb, mdb->cmd);
V(mdb->mutex);
time_t ttime;
struct tm tm;
int stat;
+ char ed1[30], ed2[30];
ttime = mr->LastWritten;
localtime_r(&ttime, &tm);
}
Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%d,\
- VolFiles=%d, VolBlocks=%d, VolBytes=%" lld ", VolMounts=%d, VolErrors=%d,\
- VolWrites=%d, VolMaxBytes=%" lld ", LastWritten=\"%s\", VolStatus=\"%s\" \
+ VolFiles=%d, VolBlocks=%d, VolBytes=%s, VolMounts=%d, VolErrors=%d,\
+ VolWrites=%d, VolMaxBytes=%s, LastWritten=\"%s\", VolStatus=\"%s\" \
WHERE VolumeName=\"%s\"",
- mr->VolJobs, mr->VolFiles, mr->VolBlocks, mr->VolBytes, mr->VolMounts,
- mr->VolErrors, mr->VolWrites, mr->VolMaxBytes, dt, mr->VolStatus,
- mr->VolumeName);
+ mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
+ mr->VolMounts, mr->VolErrors, mr->VolWrites,
+ edit_uint64(mr->VolMaxBytes, ed2), dt,
+ mr->VolStatus, mr->VolumeName);
stat = UPDATE_DB(mdb, mdb->cmd);
V(mdb->mutex);
<output_build_files>False</output_build_files>
</project>
-<widget>
- <class>GnomeAbout</class>
- <name>about</name>
- <visible>False</visible>
- <modal>True</modal>
- <copyright>Copyright (c) 1999 - 2002, Kern Sibbald and John Walker</copyright>
- <authors>Kern Sibbald and John Walker
-</authors>
- <comments>It comes by night and sucks the essence from your computers.</comments>
-</widget>
-
<widget>
<class>GnomeMessageBox</class>
<name>messagebox1</name>
</widget>
</widget>
+<widget>
+ <class>GtkDialog</class>
+ <name>about1</name>
+ <width>382</width>
+ <height>242</height>
+ <title>About Bacula Console</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_CENTER</position>
+ <modal>True</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox5</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area5</name>
+ <border_width>10</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox20</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label44</name>
+ <label></label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>about_button</name>
+ <border_width>1</border_width>
+ <width>80</width>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_about_button_clicked</handler>
+ <last_modification_time>Sun, 28 Apr 2002 15:55:15 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox8</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox9</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>about_head</name>
+ <height>102</height>
+ <label>Bacula Console 1.19 (28 April 2002)
+</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHSeparator</class>
+ <name>hseparator1</name>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>copyright</name>
+ <label>Copyright (c) 1999 - 2002, Kern Sibbald and John Walker</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0.1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>authors</name>
+ <label>Authors: Kern Sibbald and John Walker</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0.0400001</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>theme</name>
+ <label>It comes by night and sucks the essence from your computers</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0.15</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
</GTK-Interface>
dummy:
#
-SVRSRCS = dird.c authenticate.c backup.c catreq.c dird_conf.c \
+SVRSRCS = dird.c authenticate.c backup.c \
+ catreq.c dird_conf.c \
fd_cmds.c getmsg.c job.c \
- mountreq.c msgchan.c newvol.c run_conf.c restore.c \
+ mountreq.c msgchan.c newvol.c \
+ run_conf.c restore.c \
scheduler.c ua_cmds.c \
ua_dotcmds.c \
ua_db_query.c ua_retention.c \
- ua_input.c ua_output.c ua_prune.c ua_run.c \
+ ua_input.c ua_output.c ua_prune.c \
+ ua_purge.c ua_run.c \
ua_select.c ua_server.c \
ua_status.c verify.c
-SVROBJS = dird.o authenticate.o backup.o catreq.o dird_conf.o \
+SVROBJS = dird.o authenticate.o backup.o \
+ catreq.o dird_conf.o \
fd_cmds.o getmsg.o job.o \
- mountreq.o msgchan.o newvol.o run_conf.o restore.o \
+ mountreq.o msgchan.o newvol.o \
+ run_conf.o restore.o \
scheduler.o ua_cmds.o \
ua_dotcmds.o \
ua_db_query.o ua_retention.o \
- ua_input.o ua_output.o ua_prune.o ua_run.o \
+ ua_input.o ua_output.o ua_prune.o \
+ ua_purge.o ua_run.o \
ua_select.o ua_server.o \
ua_status.o verify.o
jcr->client->hdr.name,
sdt,
edt,
- edit_uint_with_commas(jcr->jr.JobBytes, ec1),
- edit_uint_with_commas(jcr->jr.JobFiles, ec2),
+ edit_uint64_with_commas(jcr->jr.JobBytes, ec1),
+ edit_uint64_with_commas(jcr->jr.JobFiles, ec2),
jcr->VolumeName,
jcr->VolSessionId,
jcr->VolSessionTime,
- edit_uint_with_commas(mr.VolBytes, ec3),
+ edit_uint64_with_commas(mr.VolBytes, ec3),
term_msg);
Dmsg0(100, "Leave backup_cleanup()\n");
}
switch (type) {
case R_DIRECTOR:
- sendit(sock, "Director: name=%s maxjobs=%d FDtimeout=%" lld " SDtimeout=%" lld "\n",
+ char ed1[30], ed2[30];
+ sendit(sock, "Director: name=%s maxjobs=%d FDtimeout=%s SDtimeout=%s\n",
reshdr->name, res->res_dir.MaxConcurrentJobs,
- res->res_dir.FDConnectTimeout,
- res->res_dir.SDConnectTimeout);
+ 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);
}
JCR *jcr;
B_DB *db;
CAT *catalog;
- char *cmd; /* return command/name buffer */
- char *args; /* command line arguments */
- char *argk[MAX_ARGS]; /* argument keywords */
- char *argv[MAX_ARGS]; /* argument values */
- int argc; /* number of arguments */
- char **prompt; /* list of prompts */
- int max_prompts; /* max size of list */
- int num_prompts; /* current number in list */
- int auto_display_messages; /* if set, display messages */
+ char *cmd; /* return command/name buffer */
+ char *args; /* command line arguments */
+ char *argk[MAX_ARGS]; /* argument keywords */
+ char *argv[MAX_ARGS]; /* argument values */
+ int argc; /* number of arguments */
+ char **prompt; /* list of prompts */
+ int max_prompts; /* max size of list */
+ int num_prompts; /* current number in list */
+ int auto_display_messages; /* if set, display messages */
int user_notified_msg_pending; /* set when user notified */
- int automount; /* if set, mount after label */
+ int automount; /* if set, mount after label */
} UAContext;
/* ua_cmds.c */
int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fs_resource(UAContext *ua);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
void start_prompt(UAContext *ua, char *msg);
void add_prompt(UAContext *ua, char *prompt);
int do_prompt(UAContext *ua, char *msg, char *prompt);
-CAT *get_catalog_resource(UAContext *ua);
+CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, char *cmd);
int get_media_type(UAContext *ua, char *MediaType);
int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
POOL *get_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, char **list);
int do_keyword_prompt(UAContext *ua, char *msg, char **list);
extern int runcmd(UAContext *ua, char *cmd);
extern int retentioncmd(UAContext *ua, char *cmd);
extern int prunecmd(UAContext *ua, char *cmd);
+extern int purgecmd(UAContext *ua, char *cmd);
/* Forward referenced functions */
static int addcmd(UAContext *ua, char *cmd), createcmd(UAContext *ua, char *cmd), cancelcmd(UAContext *ua, char *cmd);
{ N_("messages"), messagescmd, _("messages")},
{ N_("mount"), mountcmd, _("mount <storage-name>")},
{ N_("prune"), prunecmd, _("prune expired records from catalog")},
+ { N_("purge"), purgecmd, _("purge records from catalog")},
{ N_("run"), runcmd, _("run <job-name>")},
{ N_("setdebug"), setdebugcmd, _("sets debug level")},
{ N_("show"), showcmd, _("show (resource records) [jobs | pools | ... | all]")},
{
POOL_DBR pr;
MEDIA_DBR mr;
- int found = FALSE;
- int i;
- memset(&pr, 0, sizeof(pr));
- memset(&mr, 0, sizeof(mr));
-
- /* Get the pool, possibly from pool=<pool-name> */
- if (!get_pool_dbr(ua, &pr)) {
+ if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
return 1;
}
- mr.PoolId = pr.PoolId;
-
- /* See if a volume name is specified as an argument */
- for (i=1; i<ua->argc; i++) {
- if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) {
- found = TRUE;
- break;
- }
- }
- if (found) {
- strcpy(mr.VolumeName, ua->argv[i]);
- } else {
- db_list_media_records(ua->db, &mr, prtit, ua);
- if (!get_cmd(ua, _("Enter the Volume name to delete: "))) {
- return 1;
- }
- }
- mr.MediaId = 0;
- strcpy(mr.VolumeName, ua->cmd);
bsendmsg(ua, _("\nThis command will delete volume %s\n"
- "and all Jobs saved on that volume from the Catalog\n"));
+ "and all Jobs saved on that volume from the Catalog\n"),
+ mr.VolumeName);
if (!get_cmd(ua, _("If you want to continue enter pretty please: "))) {
return 1;
--- /dev/null
+/*
+ *
+ * Bacula Director -- User Agent Database prune Command
+ * Applies retention periods
+ *
+ * Kern Sibbald, February MMII
+ */
+
+/*
+ Copyright (C) 2002 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 "dird.h"
+#include "ua.h"
+
+/* Forward referenced functions */
+int prune_files(UAContext *ua, CLIENT *client);
+int prune_jobs(UAContext *ua, CLIENT *client);
+int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+
+
+#define MAX_DEL_LIST_LEN 1000000
+
+/*
+ * Select JobIds for File deletion.
+ */
+static char *select_job =
+ "SELECT JobId from Job "
+ "WHERE StartDay < %s "
+ "AND ClientId=%d "
+ "AND PurgedFiles=0";
+
+/*
+ * List of SQL commands terminated by NULL for deleting
+ * temporary tables and indicies
+ */
+static char *drop_deltabs[] = {
+ "DROP TABLE DelCandidates",
+ "DROP INDEX DelInx1",
+ NULL};
+
+/*
+ * List of SQL commands to create temp table and indicies
+ */
+static char *create_deltabs[] = {
+ "CREATE TABLE DelCandidates ("
+ "JobId INTEGER UNSIGNED NOT NULL, "
+ "PurgedFiles TINYINT, "
+ "FileSetId INTEGER UNSIGNED)",
+ "CREATE INDEX DelInx1 ON DelCandidates (JobId)",
+ NULL};
+
+
+/*
+ * Fill candidates table with all Files subject to being deleted
+ */
+static char *insert_delcand =
+ "INSERT INTO DelCandidates "
+ "SELECT JobId, PurgedFiles, FileSetId FROM Job "
+ "WHERE StartDay < %s "
+ "AND ClientId=%d";
+
+/*
+ * Select files from the DelCandidates table that have a
+ * more recent backup -- i.e. are not the only backup.
+ * This is the list of files to delete.
+ */
+static char *select_del =
+ "SELECT DelCandidates.JobId "
+ "FROM Job,DelCandidates "
+ "WHERE Job.StartDay >= %s "
+ "AND Job.ClientId=%d "
+ "AND Job.Level='F' "
+ "AND Job.JobStatus='T' "
+ "AND Job.FileSetId=DelCandidates.FileSetId";
+
+/* In memory list of JobIds */
+struct s_file_del_ctx {
+ JobId_t *JobId;
+ int num_ids; /* ids stored */
+ int max_ids; /* size of array */
+ int num_del; /* number deleted */
+ int tot_ids; /* total to process */
+};
+
+struct s_job_del_ctx {
+ JobId_t *JobId; /* array of JobIds */
+ char *PurgedFiles; /* Array of PurgedFile flags */
+ int num_ids; /* ids stored */
+ int max_ids; /* size of array */
+ int num_del; /* number deleted */
+ int tot_ids; /* total to process */
+};
+
+struct s_count_ctx {
+ int count;
+};
+
+
+/*
+ * Called here to count entries to be deleted
+ */
+static int count_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_count_ctx *cnt = (struct s_count_ctx *)ctx;
+
+ if (row[0]) {
+ cnt->count = atoi(row[0]);
+ } else {
+ cnt->count = 0;
+ }
+ return 0;
+}
+
+
+/*
+ * Called here to count entries to be deleted
+ */
+static int file_count_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+ del->tot_ids++;
+ return 0;
+}
+
+
+/*
+ * Called here to make in memory list of JobIds to be
+ * deleted and the associated PurgedFiles flag.
+ * The in memory list will then be transversed
+ * to issue the SQL DELETE commands. Note, the list
+ * is allowed to get to MAX_DEL_LIST_LEN to limit the
+ * maximum malloc'ed memory.
+ */
+static int job_delete_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx;
+
+ if (del->num_ids == MAX_DEL_LIST_LEN) {
+ return 1;
+ }
+ if (del->num_ids == del->max_ids) {
+ del->max_ids = (del->max_ids * 3) / 2;
+ del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids);
+ del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids);
+ }
+ del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL);
+ del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]);
+ return 0;
+}
+
+static int file_delete_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+
+ if (del->num_ids == MAX_DEL_LIST_LEN) {
+ return 1;
+ }
+ if (del->num_ids == del->max_ids) {
+ del->max_ids = (del->max_ids * 3) / 2;
+ del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
+ del->max_ids);
+ }
+ del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+ return 0;
+}
+
+/*
+ * Prune records from database
+ */
+int prunecmd(UAContext *ua, char *cmd)
+{
+ CLIENT *client;
+ POOL_DBR pr;
+ MEDIA_DBR mr;
+
+ static char *keywords[] = {
+ N_("files"),
+ N_("jobs"),
+ N_("volume"),
+ NULL};
+ if (!open_db(ua)) {
+ return 1;
+ }
+ switch (find_arg_keyword(ua, keywords)) {
+ case 0:
+ client = select_client_resource(ua);
+ prune_files(ua, client);
+ return 1;
+ case 1:
+ client = select_client_resource(ua);
+ prune_jobs(ua, client);
+ return 1;
+ case 2:
+ if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
+ return 1;
+ }
+ prune_volume(ua, &pr, &mr);
+ return 1;
+ default:
+ break;
+ }
+ switch (do_keyword_prompt(ua, _("Choose item to prune"), keywords)) {
+ case 0:
+ client = select_client_resource(ua);
+ if (!client) {
+ return 1;
+ }
+ prune_files(ua, client);
+ break;
+ case 1:
+ client = select_client_resource(ua);
+ if (!client) {
+ return 1;
+ }
+ prune_jobs(ua, client);
+ break;
+ case 2:
+ if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
+ return 1;
+ }
+ prune_volume(ua, &pr, &mr);
+ return 1;
+ }
+ return 1;
+}
+
+/*
+ * Prune File records from the database. For any Job which
+ * is older than the retention period, we unconditionally delete
+ * all File records for that Job. This is simple enough that no
+ * temporary tables are needed. We simply make an in memory list of
+ * the JobIds meeting the prune conditions, then delete all File records
+ * pointing to each of those JobIds.
+ */
+int prune_files(UAContext *ua, CLIENT *client)
+{
+ struct s_file_del_ctx del;
+ char *query = (char *)get_pool_memory(PM_MESSAGE);
+ int i;
+ struct tm tm;
+ uint64_t today, period;
+ time_t now;
+ CLIENT_DBR cr;
+ char ed1[50];
+
+ memset(&cr, 0, sizeof(cr));
+ strcpy(cr.Name, client->hdr.name);
+ if (!db_create_client_record(ua->db, &cr)) {
+ return 0;
+ }
+
+ period = client->FileRetention;
+ now = time(NULL);
+ localtime_r(&now, &tm);
+ today = (uint64_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+ date_encode(2000, 1, 1));
+
+ del.JobId = NULL;
+ del.num_ids = 0;
+ del.tot_ids = 0;
+ del.num_del = 0;
+ del.max_ids = 0;
+
+ Dmsg3(100, "Today=%d period=%d period=%d\n", (uint32_t)today, (uint32_t)period,
+ (uint32_t)(period/(3600*24)));
+
+ Mmsg(&query, select_job,
+ edit_uint64(today - period/(3600*24), ed1), cr.ClientId);
+
+ Dmsg1(050, "select sql=%s\n", query);
+
+ if (!db_sql_query(ua->db, query, file_count_handler, (void *)&del)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "Count failed\n");
+ goto bail_out;
+ }
+
+ if (del.tot_ids == 0) {
+ bsendmsg(ua, _("No Files found for client %s to prune from %s catalog.\n"),
+ client->hdr.name, client->catalog->hdr.name);
+ goto bail_out;
+ }
+
+ if (del.tot_ids < MAX_DEL_LIST_LEN) {
+ del.max_ids = del.tot_ids + 1;
+ } else {
+ del.max_ids = MAX_DEL_LIST_LEN;
+ }
+ del.tot_ids = 0;
+
+ del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+
+ db_sql_query(ua->db, query, file_delete_handler, (void *)&del);
+
+ for (i=0; i < del.num_ids; i++) {
+ Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+ Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ /*
+ * Now mark Job as having files purged. This is necessary to
+ * avoid having too many Jobs to process in future prunings. If
+ * we don't do this, the number of JobId's in our in memory list
+ * will grow very large.
+ */
+ Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+ }
+ bsendmsg(ua, _("%d Files for client %s pruned from %s catalog.\n"), del.num_ids,
+ client->hdr.name, client->catalog->hdr.name);
+
+bail_out:
+ if (del.JobId) {
+ free(del.JobId);
+ }
+ free_pool_memory(query);
+ return 1;
+}
+
+
+static void drop_temp_tables(UAContext *ua)
+{
+ int i;
+ for (i=0; drop_deltabs[i]; i++) {
+ db_sql_query(ua->db, drop_deltabs[i], NULL, (void *)NULL);
+ }
+}
+
+static int create_temp_tables(UAContext *ua)
+{
+ int i;
+ /* Create temp tables and indicies */
+ for (i=0; create_deltabs[i]; i++) {
+ if (!db_sql_query(ua->db, create_deltabs[i], NULL, (void *)NULL)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "create DelTables table failed\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+/*
+ * Purging Jobs is a bit more complicated than purging Files
+ * because we delete Job records only if there is a more current
+ * backup of the FileSet. Otherwise, we keep the Job record.
+ * In other words, we never delete the only Job record that
+ * contains a current backup of a FileSet. This prevents the
+ * Volume from being recycled and destroying a current backup.
+ */
+int prune_jobs(UAContext *ua, CLIENT *client)
+{
+ struct s_job_del_ctx del;
+ struct s_count_ctx cnt;
+ char *query = (char *)get_pool_memory(PM_MESSAGE);
+ int i;
+ struct tm tm;
+ uint64_t today, period;
+ time_t now;
+ CLIENT_DBR cr;
+ char ed1[50];
+
+ memset(&cr, 0, sizeof(cr));
+ strcpy(cr.Name, client->hdr.name);
+ if (!db_create_client_record(ua->db, &cr)) {
+ return 0;
+ }
+
+ period = client->JobRetention;
+ now = time(NULL);
+ localtime_r(&now, &tm);
+ today = (uint64_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+ date_encode(2000, 1, 1));
+
+
+ del.JobId = NULL;
+ del.num_ids = 0;
+ del.tot_ids = 0;
+ del.num_del = 0;
+ del.max_ids = 0;
+
+ Dmsg3(050, "Today=%d period=%d period=%d\n", (uint32_t)today, (uint32_t)period,
+ (uint32_t)(period/(3600*24)));
+
+ /* Drop any previous temporary tables still there */
+ drop_temp_tables(ua);
+
+ /* Create temp tables and indicies */
+ if (!create_temp_tables(ua)) {
+ goto bail_out;
+ }
+
+ /*
+ * Select all files that are older than the JobRetention period
+ * and stuff them into the "DeletionCandidates" table.
+ */
+ edit_uint64(today - period/(3600*24), ed1);
+ Mmsg(&query, insert_delcand, ed1, cr.ClientId);
+
+ if (!db_sql_query(ua->db, query, NULL, (void *)NULL)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "insert delcand failed\n");
+ goto bail_out;
+ }
+
+ strcpy(query, "SELECT count(*) FROM DelCandidates");
+
+ Dmsg1(100, "select sql=%s\n", query);
+
+ if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "Count failed\n");
+ goto bail_out;
+ }
+
+ if (cnt.count == 0) {
+ bsendmsg(ua, _("No Jobs for client %s found to prune from %s catalog.\n"),
+ client->hdr.name, client->catalog->hdr.name);
+ goto bail_out;
+ }
+
+ if (cnt.count < MAX_DEL_LIST_LEN) {
+ del.max_ids = cnt.count + 1;
+ } else {
+ del.max_ids = MAX_DEL_LIST_LEN;
+ }
+ del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+ del.PurgedFiles = (char *)malloc(del.max_ids);
+
+ Mmsg(&query, select_del, ed1, cr.ClientId);
+ db_sql_query(ua->db, query, job_delete_handler, (void *)&del);
+
+ /*
+ * OK, now we have the list of JobId's to be pruned, first check
+ * if the Files have been purged, if not, purge (delete) them.
+ * Then delete the Job entry, and finally and JobMedia records.
+ */
+ for (i=0; i < del.num_ids; i++) {
+ Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+ if (!del.PurgedFiles[i]) {
+ Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+ }
+
+ Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+
+ Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+ }
+ bsendmsg(ua, _("%d Jobs for client %s pruned from %s catalog.\n"), del.num_ids,
+ client->hdr.name, client->catalog->hdr.name);
+
+bail_out:
+ drop_temp_tables(ua);
+ if (del.JobId) {
+ free(del.JobId);
+ }
+ if (del.PurgedFiles) {
+ free(del.PurgedFiles);
+ }
+ free_pool_memory(query);
+ return 1;
+}
+
+/*
+ * Prune volumes
+ */
+int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
+{
+ char *query = (char *)get_pool_memory(PM_MESSAGE);
+ struct s_count_ctx cnt;
+
+ Mmsg(&query, "SELECT count(*) FROM JobMedia WHERE MediaId=%d", mr->MediaId);
+ if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "Count failed\n");
+ goto bail_out;
+ }
+
+ if (cnt.count == 0) {
+ bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n",
+ mr->VolumeName);
+ } else {
+ bsendmsg(ua, "There are still %d Jobs on Volume %s. It is not purged.\n",
+ cnt.count, mr->VolumeName);
+ }
+bail_out:
+ free_pool_memory(query);
+ return 1;
+}
--- /dev/null
+/*
+ *
+ * Bacula Director -- User Agent Database Purge Command
+ *
+ * Purges Files from specific JobIds
+ * or
+ * Purges Jobs from Volumes
+ *
+ * Kern Sibbald, February MMII
+ */
+
+/*
+ Copyright (C) 2002 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 "dird.h"
+#include "ua.h"
+
+/* Forward referenced functions */
+int purge_files_from_client(UAContext *ua, CLIENT *client);
+int purge_jobs_from_client(UAContext *ua, CLIENT *client);
+void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr );
+void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+void purge_files_from_job(UAContext *ua, JOB_DBR *jr);
+
+
+#define MAX_DEL_LIST_LEN 1000000
+
+
+static char *select_jobsfiles_from_client =
+ "SELECT JobId FROM Job "
+ "WHERE ClientId=%d "
+ "AND PurgedFiles=0";
+
+static char *select_jobs_from_client =
+ "SELECT JobId, PurgedFiles FROM Job "
+ "WHERE ClientId=%d";
+
+
+/* In memory list of JobIds */
+struct s_file_del_ctx {
+ JobId_t *JobId;
+ int num_ids; /* ids stored */
+ int max_ids; /* size of array */
+ int num_del; /* number deleted */
+ int tot_ids; /* total to process */
+};
+
+struct s_job_del_ctx {
+ JobId_t *JobId; /* array of JobIds */
+ char *PurgedFiles; /* Array of PurgedFile flags */
+ int num_ids; /* ids stored */
+ int max_ids; /* size of array */
+ int num_del; /* number deleted */
+ int tot_ids; /* total to process */
+};
+
+struct s_count_ctx {
+ int count;
+};
+
+
+/*
+ * Called here to count entries to be deleted
+ */
+static int file_count_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+ del->tot_ids++;
+ return 0;
+}
+
+
+static int job_count_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx;
+ del->tot_ids++;
+ return 0;
+}
+
+
+/*
+ * Called here to make in memory list of JobIds to be
+ * deleted and the associated PurgedFiles flag.
+ * The in memory list will then be transversed
+ * to issue the SQL DELETE commands. Note, the list
+ * is allowed to get to MAX_DEL_LIST_LEN to limit the
+ * maximum malloc'ed memory.
+ */
+static int job_delete_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx;
+
+ if (del->num_ids == MAX_DEL_LIST_LEN) {
+ return 1;
+ }
+ if (del->num_ids == del->max_ids) {
+ del->max_ids = (del->max_ids * 3) / 2;
+ del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids);
+ del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids);
+ }
+ del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL);
+ del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]);
+ return 0;
+}
+
+static int file_delete_handler(void *ctx, int num_fields, char **row)
+{
+ struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+
+ if (del->num_ids == MAX_DEL_LIST_LEN) {
+ return 1;
+ }
+ if (del->num_ids == del->max_ids) {
+ del->max_ids = (del->max_ids * 3) / 2;
+ del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
+ del->max_ids);
+ }
+ del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+ return 0;
+}
+
+void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr ) {} /* ***FIXME*** implement */
+void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) {} /* ***FIXME*** implement */
+
+
+
+/*
+ * Purge records from database
+ *
+ * Purge Files from [Job|JobId|Client|Volume]
+ * Purge Jobs from [Client|Volume]
+ *
+ * N.B. Not all above is implemented yet.
+ */
+int purgecmd(UAContext *ua, char *cmd)
+{
+ CLIENT *client;
+ MEDIA_DBR mr;
+ POOL_DBR pr;
+ JOB_DBR jr;
+ static char *keywords[] = {
+ N_("files"),
+ N_("jobs"),
+ NULL};
+
+ static char *files_keywords[] = {
+ N_("Job"),
+ N_("JobId"),
+ N_("Client"),
+ N_("Volume"),
+ NULL};
+
+ static char *jobs_keywords[] = {
+ N_("Client"),
+ N_("Volume"),
+ NULL};
+
+ bsendmsg(ua, _(
+ "This command is DANGEROUUS!\n"
+ "It purges (deletes) all Files from a Job,\n"
+ "JobId, Client or Volume; or it purges (deletes)\n"
+ "all Jobs from a Client or Volume. Normally you\n"
+ "should use the PRUNE command instead.\n"));
+
+ if (!open_db(ua)) {
+ return 1;
+ }
+ switch (find_arg_keyword(ua, keywords)) {
+ /* Files */
+ case 0:
+ switch(find_arg_keyword(ua, files_keywords)) {
+ case 0: /* Job */
+ case 1:
+ if (get_job_dbr(ua, &jr)) {
+ purge_files_from_job(ua, &jr);
+ }
+ return 1;
+ case 2: /* client */
+ client = select_client_resource(ua);
+ purge_files_from_client(ua, client);
+ return 1;
+ case 3:
+ if (select_pool_and_media_dbr(ua, &pr, &mr)) {
+ purge_files_from_volume(ua, &pr, &mr);
+ }
+ return 1;
+ }
+ /* Jobs */
+ case 1:
+ switch(find_arg_keyword(ua, jobs_keywords)) {
+ case 0: /* client */
+ client = select_client_resource(ua);
+ purge_jobs_from_client(ua, client);
+ return 1;
+ case 1:
+ if (select_pool_and_media_dbr(ua, &pr, &mr)) {
+ purge_jobs_from_volume(ua, &pr, &mr);
+ }
+ return 1;
+ }
+ default:
+ break;
+ }
+ switch (do_keyword_prompt(ua, _("Choose item to purge"), keywords)) {
+ case 0:
+ client = select_client_resource(ua);
+ if (!client) {
+ return 1;
+ }
+ purge_files_from_client(ua, client);
+ break;
+ case 1:
+ client = select_client_resource(ua);
+ if (!client) {
+ return 1;
+ }
+ purge_jobs_from_client(ua, client);
+ break;
+ }
+ return 1;
+}
+
+/*
+ * Prune File records from the database. For any Job which
+ * is older than the retention period, we unconditionally delete
+ * all File records for that Job. This is simple enough that no
+ * temporary tables are needed. We simply make an in memory list of
+ * the JobIds meeting the prune conditions, then delete all File records
+ * pointing to each of those JobIds.
+ */
+int purge_files_from_client(UAContext *ua, CLIENT *client)
+{
+ struct s_file_del_ctx del;
+ char *query = (char *)get_pool_memory(PM_MESSAGE);
+ int i;
+ CLIENT_DBR cr;
+
+ memset(&cr, 0, sizeof(cr));
+ strcpy(cr.Name, client->hdr.name);
+ if (!db_create_client_record(ua->db, &cr)) {
+ return 0;
+ }
+
+ del.JobId = NULL;
+ del.num_ids = 0;
+ del.tot_ids = 0;
+ del.num_del = 0;
+ del.max_ids = 0;
+
+ Mmsg(&query, select_jobsfiles_from_client, cr.ClientId);
+
+ Dmsg1(050, "select sql=%s\n", query);
+
+ if (!db_sql_query(ua->db, query, file_count_handler, (void *)&del)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "Count failed\n");
+ goto bail_out;
+ }
+
+ if (del.tot_ids == 0) {
+ bsendmsg(ua, _("No Files found for client %s to purge from %s catalog.\n"),
+ client->hdr.name, client->catalog->hdr.name);
+ goto bail_out;
+ }
+
+ if (del.tot_ids < MAX_DEL_LIST_LEN) {
+ del.max_ids = del.tot_ids + 1;
+ } else {
+ del.max_ids = MAX_DEL_LIST_LEN;
+ }
+ del.tot_ids = 0;
+
+ del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+
+ db_sql_query(ua->db, query, file_delete_handler, (void *)&del);
+
+ for (i=0; i < del.num_ids; i++) {
+ Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+ Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ /*
+ * Now mark Job as having files purged. This is necessary to
+ * avoid having too many Jobs to process in future prunings. If
+ * we don't do this, the number of JobId's in our in memory list
+ * will grow very large.
+ */
+ Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+ }
+ bsendmsg(ua, _("%d Files for client %s purged from %s catalog.\n"), del.num_ids,
+ client->hdr.name, client->catalog->hdr.name);
+
+bail_out:
+ if (del.JobId) {
+ free(del.JobId);
+ }
+ free_pool_memory(query);
+ return 1;
+}
+
+
+
+/*
+ * Purging Jobs is a bit more complicated than purging Files
+ * because we delete Job records only if there is a more current
+ * backup of the FileSet. Otherwise, we keep the Job record.
+ * In other words, we never delete the only Job record that
+ * contains a current backup of a FileSet. This prevents the
+ * Volume from being recycled and destroying a current backup.
+ */
+int purge_jobs_from_client(UAContext *ua, CLIENT *client)
+{
+ struct s_job_del_ctx del;
+ char *query = (char *)get_pool_memory(PM_MESSAGE);
+ int i;
+ CLIENT_DBR cr;
+
+ memset(&cr, 0, sizeof(cr));
+ strcpy(cr.Name, client->hdr.name);
+ if (!db_create_client_record(ua->db, &cr)) {
+ return 0;
+ }
+
+ del.JobId = NULL;
+ del.num_ids = 0;
+ del.tot_ids = 0;
+ del.num_del = 0;
+ del.max_ids = 0;
+
+ Mmsg(&query, select_jobs_from_client, cr.ClientId);
+
+ Dmsg1(050, "select sql=%s\n", query);
+
+ if (!db_sql_query(ua->db, query, job_count_handler, (void *)&del)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ Dmsg0(050, "Count failed\n");
+ goto bail_out;
+ }
+ if (del.tot_ids == 0) {
+ bsendmsg(ua, _("No Jobs found for client %s to purge from %s catalog.\n"),
+ client->hdr.name, client->catalog->hdr.name);
+ goto bail_out;
+ }
+
+ if (del.tot_ids < MAX_DEL_LIST_LEN) {
+ del.max_ids = del.tot_ids + 1;
+ } else {
+ del.max_ids = MAX_DEL_LIST_LEN;
+ }
+
+ del.tot_ids = 0;
+
+
+
+ del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+ del.PurgedFiles = (char *)malloc(del.max_ids);
+
+ db_sql_query(ua->db, query, job_delete_handler, (void *)&del);
+
+ /*
+ * OK, now we have the list of JobId's to be purged, first check
+ * if the Files have been purged, if not, purge (delete) them.
+ * Then delete the Job entry, and finally and JobMedia records.
+ */
+ for (i=0; i < del.num_ids; i++) {
+ Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+ if (!del.PurgedFiles[i]) {
+ Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+ }
+
+ Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+
+ Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+ Dmsg1(050, "Del sql=%s\n", query);
+ }
+ bsendmsg(ua, _("%d Jobs for client %s purged from %s catalog.\n"), del.num_ids,
+ client->hdr.name, client->catalog->hdr.name);
+
+bail_out:
+ if (del.JobId) {
+ free(del.JobId);
+ }
+ if (del.PurgedFiles) {
+ free(del.PurgedFiles);
+ }
+ free_pool_memory(query);
+ return 1;
+}
+
+void purge_files_from_job(UAContext *ua, JOB_DBR *jr)
+{
+ char *query = (char *)get_pool_memory(PM_MESSAGE);
+
+ Mmsg(&query, "DELETE FROM File WHERE JobId=%d", jr->JobId);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+
+ Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", jr->JobId);
+ db_sql_query(ua->db, query, NULL, (void *)NULL);
+
+ free_pool_memory(query);
+}
return select_client_resource(ua);
}
-
-
-
/* Scan what the user has entered looking for:
*
* pool=<pool-name>
return opr.PoolId;
}
+/*
+ * Select a Pool and a Media (Volume) record from the database
+ */
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
+{
+ int found = FALSE;
+ int i;
+
+ memset(pr, 0, sizeof(POOL_DBR));
+ memset(mr, 0, sizeof(MEDIA_DBR));
+
+ /* Get the pool, possibly from pool=<pool-name> */
+ if (!get_pool_dbr(ua, pr)) {
+ return 0;
+ }
+ mr->PoolId = pr->PoolId;
+
+ /* See if a volume name is specified as an argument */
+ for (i=1; i<ua->argc; i++) {
+ if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found) {
+ strcpy(mr->VolumeName, ua->argv[i]);
+ } else {
+ db_list_media_records(ua->db, mr, prtit, ua);
+ if (!get_cmd(ua, _("Enter the Volume name to delete: "))) {
+ return 01;
+ }
+ strcpy(mr->VolumeName, ua->cmd);
+ }
+ mr->MediaId = 0;
+ if (!db_get_media_record(ua->db, mr)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ return 0;
+ }
+ return 1;
+}
+
/*
* This routine is ONLY used in the create command.
return pool;
}
+/*
+ * List all jobs and ask user to select one
+ */
+int select_job_dbr(UAContext *ua, JOB_DBR *jr)
+{
+ db_list_job_records(ua->db, jr, prtit, ua);
+ if (!get_cmd(ua, _("Enter the JobId to select: "))) {
+ return 0;
+ }
+ jr->JobId = atoi(ua->cmd);
+ if (!db_get_job_record(ua->db, jr)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ return 0;
+ }
+ return jr->JobId;
+
+}
+
+
+/* Scan what the user has entered looking for:
+ *
+ * jobid=nn
+ *
+ * if error or not found, put up a list of Jobs
+ * to choose from.
+ *
+ * returns: 0 on error
+ * JobId on success and fills in JOB_DBR
+ */
+int get_job_dbr(UAContext *ua, JOB_DBR *jr)
+{
+ int i;
+
+ for (i=1; i<ua->argc; i++) {
+ if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) {
+ jr->JobId = 0;
+ strcpy(jr->Job, ua->argv[i]);
+ } else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) {
+ jr->JobId = atoi(ua->argv[i]);
+ } else {
+ continue;
+ }
+ if (!db_get_job_record(ua->db, jr)) {
+ bsendmsg(ua, _("Could not find Job %s: ERR=%s"), ua->argv[i],
+ db_strerror(ua->db));
+ jr->JobId = 0;
+ break;
+ }
+ return jr->JobId;
+ }
+
+ if (!select_job_dbr(ua, jr)) { /* try once more */
+ return 0;
+ }
+ return jr->JobId;
+}
+
}
bsendmsg(ua, _(" Files=%s Bytes=%s Termination Status=%s\n"),
- edit_uint_with_commas(last_job.JobFiles, b1),
- edit_uint_with_commas(last_job.JobBytes, b2),
+ edit_uint64_with_commas(last_job.JobFiles, b1),
+ edit_uint64_with_commas(last_job.JobBytes, b2),
termstat);
}
lock_jcr_chain();
jcr->client->hdr.name,
sdt,
edt,
- edit_uint_with_commas(jcr->jr.JobFiles, ec1),
+ edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
term_msg);
Dmsg0(100, "Leave verify_cleanup()\n");
}
len = Mmsg(&msg, _(" Files=%s Bytes=%s Termination Status=%s\n"),
- edit_uint_with_commas(last_job.JobFiles, b1),
- edit_uint_with_commas(last_job.JobBytes, b2),
+ edit_uint64_with_commas(last_job.JobFiles, b1),
+ edit_uint64_with_commas(last_job.JobBytes, b2),
termstat);
sendit(msg, len, arg);
}
}
bps = njcr->JobBytes / sec;
len = Mmsg(&msg, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
- edit_uint_with_commas(njcr->JobFiles, b1),
- edit_uint_with_commas(njcr->JobBytes, b2),
- edit_uint_with_commas(bps, b3));
+ edit_uint64_with_commas(njcr->JobFiles, b1),
+ edit_uint64_with_commas(njcr->JobBytes, b2),
+ edit_uint64_with_commas(bps, b3));
sendit(msg, len, arg);
len = Mmsg(&msg, _(" Files Examined=%s\n"),
- edit_uint_with_commas(njcr->num_files_examined, b1));
+ edit_uint64_with_commas(njcr->num_files_examined, b1));
sendit(msg, len, arg);
if (njcr->JobFiles > 0) {
len = Mmsg(&msg, _(" Processing file: %s\n"), njcr->last_fname);
*/
/* base64.c */
-void base64_init __PROTO((void));
-int to_base64 __PROTO((intmax_t value, char *where));
-int from_base64 __PROTO((intmax_t *value, char *where));
-void encode_stat __PROTO((char *buf, struct stat *statp));
-void decode_stat __PROTO((char *buf, struct stat *statp));
-int bin_to_base64 __PROTO((char *buf, char *bin, int len));
+void base64_init __PROTO((void));
+int to_base64 __PROTO((intmax_t value, char *where));
+int from_base64 __PROTO((intmax_t *value, char *where));
+void encode_stat __PROTO((char *buf, struct stat *statp));
+void decode_stat __PROTO((char *buf, struct stat *statp));
+int bin_to_base64 __PROTO((char *buf, char *bin, int len));
/* bmisc.c */
-void *b_malloc (char *file, int line, size_t size);
+void *b_malloc (char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, char *fmt, ...);
-int create_pid_file (char *dir, char *progname, int port, char *errmsg);
-int delete_pid_file (char *dir, char *progname, int port);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, char *fmt, ...);
+int create_pid_file (char *dir, char *progname, int port, char *errmsg);
+int delete_pid_file (char *dir, char *progname, int port);
/* bnet.c */
-int32_t bnet_recv __PROTO((BSOCK *bsock));
-int bnet_send __PROTO((BSOCK *bsock));
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-BSOCK * bnet_connect (void *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-int bnet_wait_data (BSOCK *bsock, int sec);
-void bnet_close __PROTO((BSOCK *bsock));
-BSOCK * init_bsock __PROTO((int sockfd, char *who, char *ip, int port));
-BSOCK * dup_bsock __PROTO((BSOCK *bsock));
-void term_bsock __PROTO((BSOCK *bsock));
-char * bnet_strerror __PROTO((BSOCK *bsock));
-char * bnet_sig_to_ascii __PROTO((BSOCK *bsock));
-int bnet_wait_data __PROTO((BSOCK *bsock, int sec));
+int32_t bnet_recv __PROTO((BSOCK *bsock));
+int bnet_send __PROTO((BSOCK *bsock));
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+BSOCK * bnet_connect (void *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+int bnet_wait_data (BSOCK *bsock, int sec);
+void bnet_close __PROTO((BSOCK *bsock));
+BSOCK * init_bsock __PROTO((int sockfd, char *who, char *ip, int port));
+BSOCK * dup_bsock __PROTO((BSOCK *bsock));
+void term_bsock __PROTO((BSOCK *bsock));
+char * bnet_strerror __PROTO((BSOCK *bsock));
+char * bnet_sig_to_ascii __PROTO((BSOCK *bsock));
+int bnet_wait_data __PROTO((BSOCK *bsock, int sec));
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password);
int cram_md5_auth(BSOCK *bs, char *password);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* create_file.c */
int create_file(void *jcr, char *fname, char *ofile, char *lname,
- int type, struct stat *statp, int *ofd);
+ int type, struct stat *statp, int *ofd);
int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type,
- struct stat *statp);
+ struct stat *statp);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start __PROTO(());
+void daemon_start __PROTO(());
/* lex.c */
-LEX * lex_close_file __PROTO((LEX *lf));
-LEX * lex_open_file __PROTO((LEX *lf, char *fname));
-int lex_get_char __PROTO((LEX *lf));
-void lex_unget_char __PROTO((LEX *lf));
-char * lex_tok_to_str __PROTO((int token));
-int lex_get_token __PROTO((LEX *lf));
+LEX * lex_close_file __PROTO((LEX *lf));
+LEX * lex_open_file __PROTO((LEX *lf, char *fname));
+int lex_get_char __PROTO((LEX *lf));
+void lex_unget_char __PROTO((LEX *lf));
+char * lex_tok_to_str __PROTO((int token));
+int lex_get_token __PROTO((LEX *lf));
/* makepath.c */
int make_path(
- void *jcr,
- const char *argpath,
- int mode,
- int parent_mode,
- uid_t owner,
- gid_t group,
- int preserve_existing,
- char *verbose_fmt_string);
+ void *jcr,
+ const char *argpath,
+ int mode,
+ int parent_mode,
+ uid_t owner,
+ gid_t group,
+ int preserve_existing,
+ char *verbose_fmt_string);
/* message.c */
-void my_name_is __PROTO((int argc, char *argv[], char *name));
-void init_msg __PROTO((void *jcr));
-void term_msg __PROTO((void));
-void close_msg __PROTO((void *jcr));
-void add_msg_dest __PROTO((int dest, int type, char *where, char *dest_code));
-void rem_msg_dest __PROTO((int dest, int type, char *where));
-void Jmsg (void *jcr, int type, int level, char *fmt, ...);
-void dispatch_message __PROTO((void *jcr, int type, int level, char *buf));
-void init_console_msg __PROTO((char *wd));
+void my_name_is __PROTO((int argc, char *argv[], char *name));
+void init_msg __PROTO((void *jcr));
+void term_msg __PROTO((void));
+void close_msg __PROTO((void *jcr));
+void add_msg_dest __PROTO((int dest, int type, char *where, char *dest_code));
+void rem_msg_dest __PROTO((int dest, int type, char *where));
+void Jmsg (void *jcr, int type, int level, char *fmt, ...);
+void dispatch_message __PROTO((void *jcr, int type, int level, char *buf));
+void init_console_msg __PROTO((char *wd));
/* bnet_server.c */
-void bnet_thread_server(int port, int max_clients, workq_t *client_wq,
- void handle_client_request(void *bsock));
-void bnet_server __PROTO((int port, void handle_client_request(BSOCK *bsock)));
-int net_connect __PROTO((int port));
-BSOCK * bnet_bind __PROTO((int port));
-BSOCK * bnet_accept __PROTO((BSOCK *bsock, char *who));
+void bnet_thread_server(int port, int max_clients, workq_t *client_wq,
+ void handle_client_request(void *bsock));
+void bnet_server __PROTO((int port, void handle_client_request(BSOCK *bsock)));
+int net_connect __PROTO((int port));
+BSOCK * bnet_bind __PROTO((int port));
+BSOCK * bnet_accept __PROTO((BSOCK *bsock, char *who));
/* signal.c */
-void init_signals __PROTO((void terminate(int sig)));
-void init_stack_dump (void);
+void init_signals __PROTO((void terminate(int sig)));
+void init_stack_dump (void);
/* util.c */
-void lcase __PROTO((char *str));
-void bash_spaces __PROTO((char *str));
-void unbash_spaces __PROTO((char *str));
-void strip_trailing_junk __PROTO((char *str));
-void strip_trailing_slashes __PROTO((char *dir));
-int skip_spaces __PROTO((char **msg));
-int skip_nonspaces __PROTO((char **msg));
-int fstrsch __PROTO((char *a, char *b));
-char * encode_time __PROTO((time_t time, char *buf));
-char * encode_mode __PROTO((mode_t mode, char *buf));
-char * edit_uint_with_commas __PROTO((uint64_t val, char *buf));
-char * add_commas __PROTO((char *val, char *buf));
-char * edit_uint (uint64_t val, char *buf);
-int do_shell_expansion (char *name);
-int is_a_number (const char *num);
+void lcase __PROTO((char *str));
+void bash_spaces __PROTO((char *str));
+void unbash_spaces __PROTO((char *str));
+void strip_trailing_junk __PROTO((char *str));
+void strip_trailing_slashes __PROTO((char *dir));
+int skip_spaces __PROTO((char **msg));
+int skip_nonspaces __PROTO((char **msg));
+int fstrsch __PROTO((char *a, char *b));
+char * encode_time __PROTO((time_t time, char *buf));
+char * encode_mode __PROTO((mode_t mode, char *buf));
+char * edit_uint64_with_commas __PROTO((uint64_t val, char *buf));
+char * add_commas __PROTO((char *val, char *buf));
+char * edit_uint64 (uint64_t val, char *buf);
+int do_shell_expansion (char *name);
+int is_a_number (const char *num);
/*
- *void print_ls_output __PROTO((char *fname, char *lname, int type, struct stat *statp));
+ *void print_ls_output __PROTO((char *fname, char *lname, int type, struct stat *statp));
*/
/* watchdog.c */
* must be at least 27 bytes long. The incoming number
* is always widened to 64 bits.
*/
-char *edit_uint_with_commas(uint64_t val, char *buf)
+char *edit_uint64_with_commas(uint64_t val, char *buf)
{
sprintf(buf, "%" lld, val);
return add_commas(buf, buf);
* must be at least 27 bytes long. The incoming number
* is always widened to 64 bits.
*/
-char *edit_uint(uint64_t val, char *buf)
+char *edit_uint64(uint64_t val, char *buf)
{
sprintf(buf, "%" lld, val);
return buf;
/* Inform User about end of media */
Jmsg(jcr, M_INFO, 0, _("End of media on Volume %s Bytes=%s Blocks=%s.\n"),
- PrevVolName, edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1),
- edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2));
+ PrevVolName, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2));
if (!dev_is_tape(dev)) { /* If file, */
close_dev(dev); /* yes, close it */
}
bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"),
- edit_uint_with_commas(last_job.JobFiles, b1),
- edit_uint_with_commas(last_job.JobBytes, b2),
+ edit_uint64_with_commas(last_job.JobFiles, b1),
+ edit_uint64_with_commas(last_job.JobBytes, b2),
termstat);
}
}
bpb = dev->VolCatInfo.VolCatBytes / bpb;
bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
- edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1),
- edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
- edit_uint_with_commas(bpb, b3));
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
+ edit_uint64_with_commas(bpb, b3));
bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"),
- edit_uint_with_commas(dev->file, b1),
- edit_uint_with_commas(dev->block_num, b2));
+ 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));
}
bps = jcr->JobBytes / sec;
bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
- edit_uint_with_commas(jcr->JobFiles, b1),
- edit_uint_with_commas(jcr->JobBytes, b2),
- edit_uint_with_commas(bps, b3));
+ 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) {
EndFile : %s\n\
JobErrors : %s\n\
",
- edit_uint_with_commas(label.JobFiles, ec1),
- edit_uint_with_commas(label.JobBytes, ec2),
- edit_uint_with_commas(label.start_block, ec3),
- edit_uint_with_commas(label.end_block, ec4),
- edit_uint_with_commas(label.start_file, ec5),
- edit_uint_with_commas(label.end_file, ec6),
- edit_uint_with_commas(label.JobErrors, ec7));
+ edit_uint64_with_commas(label.JobFiles, ec1),
+ edit_uint64_with_commas(label.JobBytes, ec2),
+ edit_uint64_with_commas(label.start_block, ec3),
+ edit_uint64_with_commas(label.end_block, ec4),
+ edit_uint64_with_commas(label.start_file, ec5),
+ edit_uint64_with_commas(label.end_file, ec6),
+ edit_uint64_with_commas(label.JobErrors, ec7));
}
dt.julian_day_number = label.write_date;
dt.julian_day_fraction = label.write_time;