/* Maximum Name length including EOS */
#define MAX_NAME_LENGTH 128
+/* Maximume number of user entered command args */
+#define MAX_CMD_ARGS 30
+
/* All tape operations MUST be a multiple of this */
#define TAPE_BSIZE 1024
#if !defined(DEV_BSIZE) && defined(BSIZE)
/* Forward referenced functions */
static void terminate_console(int sig);
int get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec);
+static int do_outputcmd(FILE *input, BSOCK *UA_sock);
+static void sendit(char *fmt, ...);
/* Static variables */
static char *configfile = NULL;
static BSOCK *UA_sock = NULL;
static DIRRES *dir;
static FILE *output = stdout;
+int tee = 0; /* output to output and stdout */
static int stop = FALSE;
+static int argc;
+static POOLMEM *args;
+static char *argk[MAX_CMD_ARGS];
+static char *argv[MAX_CMD_ARGS];
+
+/* Command prototypes */
+static int versioncmd(FILE *input, BSOCK *UA_sock);
+static int inputcmd(FILE *input, BSOCK *UA_sock);
+static int outputcmd(FILE *input, BSOCK *UA_sock);
+static int teecmd(FILE *input, BSOCK *UA_sock);
+static int quitcmd(FILE *input, BSOCK *UA_sock);
+static int timecmd(FILE *input, BSOCK *UA_sock);
+static int sleepcmd(FILE *input, BSOCK *UA_sock);
#define CONFIG_FILE "./console.conf" /* default configuration file */
// printf("Got tin\n");
}
+struct cmdstruct { char *key; int (*func)(FILE *input, BSOCK *UA_sock); char *help; };
+static struct cmdstruct commands[] = {
+ { N_("input"), inputcmd, _("input from file")},
+ { N_("output"), outputcmd, _("output to file")},
+ { N_("quit"), quitcmd, _("quit")},
+ { N_("tee"), teecmd, _("output to file and terminal")},
+ { N_("sleep"), sleepcmd, _("sleep specified time")},
+ { N_("time"), timecmd, _("print current time")},
+ { N_("version"), versioncmd, _("print Console's version")},
+ { N_("exit"), quitcmd, _("exit = quit")},
+ };
+#define comsize (sizeof(commands)/sizeof(struct cmdstruct))
+
+static int do_a_command(FILE *input, BSOCK *UA_sock)
+{
+ unsigned int i;
+ int stat;
+ int found;
+ int len;
+ char *cmd;
+
+ found = 0;
+ stat = 1;
+
+ Dmsg1(120, "Command: %s\n", UA_sock->msg);
+ if (argc == 0) {
+ return 1;
+ }
+
+ cmd = argk[0]+1;
+ if (*cmd == '#') { /* comment */
+ return 1;
+ }
+ len = strlen(cmd);
+ for (i=0; i<comsize; i++) { /* search for command */
+ if (strncasecmp(cmd, _(commands[i].key), len) == 0) {
+ stat = (*commands[i].func)(input, UA_sock); /* go execute command */
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ pm_strcat(&UA_sock->msg, _(": is an illegal command\n"));
+ UA_sock->msglen = strlen(UA_sock->msg);
+ fputs(UA_sock->msg, output);
+ fflush(output);
+ }
+ return stat;
+}
+
static void read_and_process_input(FILE *input, BSOCK *UA_sock)
{
bnet_fsend(UA_sock, ".messages");
} else {
at_prompt = FALSE;
+ /* @ => internal command for us */
+ if (UA_sock->msg[0] == '@') {
+ parse_command_args(UA_sock->msg, args, &argc, argk, argv);
+ if (!do_a_command(input, UA_sock)) {
+ break;
+ }
+ continue;
+ }
if (!bnet_send(UA_sock)) { /* send command */
break; /* error */
}
while ((stat = bnet_recv(UA_sock)) >= 0) {
if (at_prompt) {
if (!stop) {
- putc('\n', output);
+ sendit("\n");
}
at_prompt = FALSE;
}
if (!stop) {
- fputs(UA_sock->msg, output);
+ sendit("%s", UA_sock->msg);
}
}
if (!stop) {
- fflush(output);
+ fflush(stdout);
}
if (is_bnet_stop(UA_sock)) {
break; /* error or term */
my_name_is(argc, argv, "console");
init_msg(NULL, NULL);
working_directory = "/tmp";
+ args = get_pool_memory(PM_FNAME);
while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) {
switch (ch) {
if (ndir > 1) {
UA_sock = init_bsock(NULL, 0, "", "", 0);
try_again:
- fprintf(output, "Available Directors:\n");
+ sendit("Available Directors:\n");
LockRes();
ndir = 0;
for (dir = NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
}
item = atoi(UA_sock->msg);
if (item < 0 || item > ndir) {
- fprintf(output, "You must enter a number between 1 and %d\n", ndir);
+ sendit("You must enter a number between 1 and %d\n", ndir);
goto try_again;
}
LockRes();
}
- Dmsg2(-1, "Connecting to Director %s:%d\n", dir->address,dir->DIRport);
+ sendit("Connecting to Director %s:%d\n", dir->address,dir->DIRport);
UA_sock = bnet_connect(NULL, 5, 15, "Director daemon", dir->address,
NULL, dir->DIRport, 0);
if (UA_sock == NULL) {
exit(1);
}
already_here = TRUE;
+ free_pool_memory(args);
exit(0);
}
{
int len;
if (!stop) {
- fputs(prompt, output);
- fflush(output);
+ if (output == stdout || tee) {
+ fputs(prompt, stdout);
+ fflush(stdout);
+ }
}
again:
switch (wait_for_data(fileno(input), sec)) {
}
#endif
+
+static int versioncmd(FILE *input, BSOCK *UA_sock)
+{
+ sendit("Version: " VERSION " (" BDATE ")\n");
+ return 1;
+}
+
+static int inputcmd(FILE *input, BSOCK *UA_sock)
+{
+ FILE *fd;
+
+ if (argc > 2) {
+ sendit("Too many arguments.\n");
+ return 0;
+ }
+ if (argc == 1) {
+ sendit("First argument must be a filename.\n");
+ return 0;
+ }
+ fd = fopen(argk[1], "r");
+ if (!fd) {
+ sendit("Cannot open file. ERR=%s\n", strerror(errno));
+ return 0;
+ }
+ read_and_process_input(fd, UA_sock);
+ fclose(fd);
+ return 1;
+}
+
+static int teecmd(FILE *input, BSOCK *UA_sock)
+{
+ tee = 1;
+ return do_outputcmd(input, UA_sock);
+}
+
+static int outputcmd(FILE *input, BSOCK *UA_sock)
+{
+ tee = 0;
+ return do_outputcmd(input, UA_sock);
+}
+
+
+static int do_outputcmd(FILE *input, BSOCK *UA_sock)
+{
+ FILE *fd;
+ char *mode = "a+";
+
+ if (argc > 3) {
+ sendit("Too many arguments.\n");
+ return 1;
+ }
+ if (argc == 1) {
+ if (output != stdout) {
+ fclose(output);
+ output = stdout;
+ tee = 0;
+ }
+ return 1;
+ }
+ if (argc == 3) {
+ mode = argk[2];
+ }
+ fd = fopen(argk[1], mode);
+ if (!fd) {
+ sendit("Cannot open file. ERR=%s\n", strerror(errno));
+ return 1;
+ }
+ output = fd;
+ return 1;
+}
+
+static int quitcmd(FILE *input, BSOCK *UA_sock)
+{
+ return 0;
+}
+
+static int sleepcmd(FILE *input, BSOCK *UA_sock)
+{
+ if (argc > 1) {
+ sleep(atoi(argk[1]));
+ }
+ return 1;
+}
+
+
+static int timecmd(FILE *input, BSOCK *UA_sock)
+{
+ char sdt[50];
+ time_t ttime = time(NULL);
+ struct tm tm;
+ localtime_r(&ttime, &tm);
+ strftime(sdt, sizeof(sdt), "%d-%b-%Y %H:%M:%S", &tm);
+ sendit(sdt);
+ sendit("\n");
+ return 1;
+}
+
+static void sendit(char *fmt,...)
+{
+ char buf[3000];
+ va_list arg_ptr;
+
+ va_start(arg_ptr, fmt);
+ bvsnprintf(buf, sizeof(buf), (char *)fmt, arg_ptr);
+ va_end(arg_ptr);
+ fputs(buf, output);
+ if (tee) {
+ fputs(buf, stdout);
+ }
+ fflush(stdout);
+}
Messages = Standard
}
+#
# Define the main nightly save backup job
+# By default, this job will back up to disk in /tmp
Job {
Name = "NightlySave"
Type = Backup
Client=@hostname@-fd
FileSet="Full Set"
Schedule = "WeeklyCycle"
- Storage = DLTDrive
+ Storage = File
Messages = Standard
Pool = Default
Write Bootstrap = "@working_dir@/NightlySave.bsr"
Client=@hostname@-fd
FileSet="Catalog"
Schedule = "WeeklyCycleAfterBackup"
- Storage = DLTDrive
+ Storage = File
Messages = Standard
Pool = Default
# This creates an ASCII copy of the catalog
Type = Restore
Client=@hostname@-fd
FileSet="Full Set"
- Storage = DLTDrive
+ Storage = File
Messages = Standard
Pool = Default
Where = /tmp/bacula-restores
# Put your list of files here, one per line or include an
# external list with:
#
-# @file-name
+# <file-name
#
# Note: / backs up everything on the root partition.
# if you have other partitons such as /usr or /home
# you will probably want to add them too.
#
-
- /
-
+# By default this is defined to point to the Bacula build
+# directory to give a reasonable FileSet to backup to
+# disk storage during initial testing.
+#
+ @BUILD_DIR@
}
+
+#
+# If you backup the root directory, the following two excluded
+# files can be useful
+#
Exclude = { /proc; /tmp }
}
AutoPrune = yes # Prune expired volumes
Volume Retention = 365d # one year
Accept Any Volume = yes # write on any volume in the pool
+}
}
break;
case '<':
+ p++; /* skip over < */
if ((ffd = fopen(p, "r")) == NULL) {
Jmsg(jcr, M_FATAL, 0, _("Cannot open %s file: %s. ERR=%s\n"),
list==INC_LIST?"included":"excluded", p, strerror(errno));
void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr);
/* ua_input.c */
-char *next_arg(char **s);
int get_cmd(UAContext *ua, char *prompt);
-void parse_command_args(UAContext *ua);
+void parse_ua_args(UAContext *ua);
/* ua_output.c */
void prtit(void *ctx, char *msg);
* Version $Id$
*/
/*
- 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
#ifndef __UA_H_
#define __UA_H_ 1
-#define MAX_ARGS 30
typedef struct s_ua_context {
BSOCK *UA_sock;
CAT *catalog;
POOLMEM *cmd; /* return command/name buffer */
POOLMEM *args; /* command line arguments */
- char *argk[MAX_ARGS]; /* argument keywords */
- char *argv[MAX_ARGS]; /* argument values */
+ char *argk[MAX_CMD_ARGS]; /* argument keywords */
+ char *argv[MAX_CMD_ARGS]; /* argument values */
int argc; /* number of arguments */
char **prompt; /* list of prompts */
int max_prompts; /* max size of list */
static int delete_pool(UAContext *ua);
static int mountcmd(UAContext *ua, char *cmd);
static int updatecmd(UAContext *ua, char *cmd);
+static int waitcmd(UAContext *ua, char *cmd);
int quitcmd(UAContext *ua, char *cmd);
{ N_("query"), querycmd, _("query catalog")},
{ N_("time"), timecmd, _("print current time")},
{ N_("exit"), quitcmd, _("exit = quit")},
+ { N_("wait"), waitcmd, _("wait until no jobs are running")},
};
#define comsize (sizeof(commands)/sizeof(struct cmdstruct))
}
len = strlen(ua->argk[0]);
- for (i=0; i<comsize; i++) /* search for command */
+ for (i=0; i<comsize; i++) { /* search for command */
if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
stat = (*commands[i].func)(ua, cmd); /* go execute command */
found = 1;
break;
}
+ }
if (!found) {
- strcat(ua->UA_sock->msg, _(": is an illegal command\n"));
+ pm_strcat(&ua->UA_sock->msg, _(": is an illegal command\n"));
ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
bnet_send(ua->UA_sock);
}
return 1;
}
+/*
+ * Wait until no job is running
+ */
+int waitcmd(UAContext *ua, char *cmd)
+{
+ usleep(300000);
+ for (int running=1; running; ) {
+ running = 0;
+ lock_jcr_chain();
+ for (JCR *jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
+ if (jcr->JobId != 0 && jcr->JobStatus != JS_Created) {
+ running = 1;
+ free_locked_jcr(jcr);
+ break;
+ }
+ free_locked_jcr(jcr);
+ }
+ unlock_jcr_chain();
+ if (running) {
+ sleep(1);
+ }
+ }
+ return 1;
+}
+
+
static int helpcmd(UAContext *ua, char *cmd)
{
unsigned int i;
return 1;
}
-/*
- * Return next argument from command line. Note, this
- * routine is destructive.
- */
-char *next_arg(char **s)
+void parse_ua_args(UAContext *ua)
{
- char *p, *q, *n;
- int in_quote = 0;
-
- /* skip past spaces to next arg */
- for (p=*s; *p && *p == ' '; ) {
- p++;
- }
- Dmsg1(400, "Next arg=%s\n", p);
- for (n = q = p; *p ; ) {
- if (*p == '\\') {
- p++;
- if (*p) {
- *q++ = *p++;
- } else {
- *q++ = *p;
- }
- continue;
- }
- if (*p == '"') { /* start or end of quote */
- if (in_quote) {
- p++; /* skip quote */
- in_quote = 0;
- continue;
- }
- in_quote = 1;
- p++;
- continue;
- }
- if (!in_quote && *p == ' ') { /* end of field */
- p++;
- break;
- }
- *q++ = *p++;
- }
- *q = 0;
- *s = p;
- Dmsg2(400, "End arg=%s next=%s\n", n, p);
- return n;
-}
-
-/*
- * This routine parses the input command line.
- * It makes a copy in args, then builds an
- * argc, argv like list where
- *
- * argc = count of arguments
- * argk[i] = argument keyword (part preceding =)
- * argv[i] = argument value (part after =)
- *
- * example: arg1 arg2=abc arg3=
- *
- * argc = c
- * argk[0] = arg1
- * argv[0] = NULL
- * argk[1] = arg2
- * argv[1] = abc
- * argk[2] = arg3
- * argv[2] =
- */
-
-void parse_command_args(UAContext *ua)
-{
- char *p, *q, *n;
- int i, len;
-
- len = strlen(ua->cmd) + 1;
- ua->args = check_pool_memory_size(ua->args, len);
- bstrncpy(ua->args, ua->cmd, len);
- strip_trailing_junk(ua->args);
- ua->argc = 0;
- p = ua->args;
- /* Pick up all arguments */
- while (ua->argc < MAX_ARGS) {
- n = next_arg(&p);
- if (*n) {
- ua->argk[ua->argc++] = n;
- } else {
- break;
- }
- }
- /* Separate keyword and value */
- for (i=0; i<ua->argc; i++) {
- p = strchr(ua->argk[i], '=');
- if (p) {
- *p++ = 0; /* terminate keyword and point to value */
- /* Unquote quoted values */
- if (*p == '"') {
- for (n = q = ++p; *p && *p != '"'; ) {
- if (*p == '\\') {
- p++;
- }
- *q++ = *p++;
- }
- *q = 0; /* terminate string */
- p = n; /* point to string */
- }
- if (strlen(p) > MAX_NAME_LENGTH-1) {
- p[MAX_NAME_LENGTH-1] = 0; /* truncate to max len */
- }
- }
- ua->argv[i] = p; /* save ptr to value or NULL */
- }
-#ifdef xxxx
- for (i=0; i<ua->argc; i++) {
- Dmsg3(000, "Arg %d: kw=%s val=%s\n", i,
- ua->argk[i], ua->argv[i]?ua->argv[i]:"NULL");
- }
-#endif
+ return parse_command_args(ua->cmd, ua->args, &ua->argc, ua->argk, ua->argv);
}
Dmsg1(400, "Submitting: %s\n", ua->cmd);
- parse_command_args(ua);
+ parse_ua_args(ua);
runcmd(ua, ua->cmd);
bsendmsg(ua, _("Restore command done.\n"));
if (!get_cmd(tree->ua, "$ ")) {
break;
}
- parse_command_args(tree->ua);
+ parse_ua_args(tree->ua);
if (tree->ua->argc == 0) {
return;
}
if (stat >= 0) {
ua.cmd = check_pool_memory_size(ua.cmd, ua.UA_sock->msglen+1);
bstrncpy(ua.cmd, ua.UA_sock->msg, ua.UA_sock->msglen+1);
- parse_command_args(&ua);
+ parse_ua_args(&ua);
if (ua.argc > 0 && ua.argk[0][0] == '.') {
do_a_dot_command(&ua, ua.cmd);
} else {
} else {
tid = NULL;
}
- if ((ff_pkt->fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) {
+ if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
ff_pkt->ff_errno = errno;
Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
stop_thread_timer(tid);
}
stop_thread_timer(tid);
} else {
- ff_pkt->fid = -1;
+ binit(&ff_pkt->bfd);
}
Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);
*/
#ifndef NO_FD_SEND_TEST
if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
- if (ff_pkt->fid >= 0) {
- close(ff_pkt->fid);
+ if (is_bopen(&ff_pkt->bfd)) {
+ bclose(&ff_pkt->bfd);
}
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
Dmsg2(100, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
if (!stat) {
- if (ff_pkt->fid >= 0) {
- close(ff_pkt->fid);
+ if (is_bopen(&ff_pkt->bfd)) {
+ bclose(&ff_pkt->bfd);
}
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
* If the file has data, read it and send to the Storage daemon
*
*/
- if (ff_pkt->fid >= 0) {
+ if (is_bopen(&ff_pkt->bfd)) {
uint64_t fileAddr = 0; /* file address */
char *rbuf, *wbuf;
int rsize = jcr->buf_size; /* read buffer size */
* <file-index> <stream> <info>
*/
if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
- close(ff_pkt->fid);
+ bclose(&ff_pkt->bfd);
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
}
/*
* Read the file data
*/
- while ((sd->msglen=read(ff_pkt->fid, rbuf, rsize)) > 0) {
+ while ((sd->msglen=bread(&ff_pkt->bfd, rbuf, rsize)) > 0) {
int sparseBlock = 0;
/* Check for sparse blocks */
Jmsg(jcr, M_FATAL, 0, _("Compression error: %d\n"), zstat);
sd->msg = msgsave;
sd->msglen = 0;
- close(ff_pkt->fid);
+ bclose(&ff_pkt->bfd);
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
}
if (!bnet_send(sd)) {
sd->msg = msgsave; /* restore read buffer */
sd->msglen = 0;
- close(ff_pkt->fid);
+ bclose(&ff_pkt->bfd);
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
}
ff_pkt->fname, strerror(errno));
}
- close(ff_pkt->fid); /* close file */
+ bclose(&ff_pkt->bfd); /* close file */
#ifndef NO_FD_SEND_TEST
if (!bnet_sig(sd, BNET_EOD)) { /* indicate end of file data */
set_jcr_job_status(jcr, JS_ErrorTerminated);
jcr->last_fname = get_pool_memory(PM_FNAME);
jcr->last_fname[0] = 0;
jcr->client_name = get_memory(strlen(my_name) + 1);
- jcr->prefix_links = 1; /* default to prefix links */
pm_strcpy(&jcr->client_name, my_name);
dir->jcr = (void *)jcr;
uint32_t record_file_index;
struct stat statp;
int extract = FALSE;
- int ofd = -1;
+ BFILE bfd;
int type, stat;
uint32_t total = 0; /* Job total but only 32 bits for debug */
char *wbuf; /* write buffer */
wherelen = strlen(jcr->where);
+ binit(&bfd);
sd = jcr->store_bsock;
set_jcr_job_status(jcr, JS_Running);
* close the output file.
*/
if (extract) {
- if (ofd < 0) {
+ if (!is_bopen(&bfd)) {
Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n"));
}
set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &ofd);
+ &statp, attribsEx, &bfd);
extract = FALSE;
Dmsg0(30, "Stop extracting.\n");
}
}
strcat(ofile, fn); /* copy rest of name */
/*
- * Fixup link name -- add where only if requested
- * and if it is an absolute path
+ * Fixup link name -- if it is an absolute path
*/
if (type == FT_LNKSAVED || type == FT_LNK) {
int add_link;
- if (jcr->prefix_links && lp[0] == '/') { /* if absolute path */
+ /* Always add prefix to hard links (FT_LNKSAVED) and
+ * on user request to soft links
+ */
+ if (lp[0] == '/' &&
+ (type == FT_LNKSAVED || jcr->prefix_links)) {
strcpy(lname, jcr->where);
add_link = 1;
} else {
extract = FALSE;
stat = create_file(jcr, fname, ofile, lname, type,
- stream, &statp, attribsEx, &ofd, jcr->replace);
+ stream, &statp, attribsEx, &bfd, jcr->replace);
switch (stat) {
case CF_ERROR:
case CF_SKIP:
P(jcr->mutex);
pm_strcpy(&jcr->last_fname, ofile);
V(jcr->mutex);
- /* Fall-through wanted */
+ jcr->JobFiles++;
+ fileAddr = 0;
+ print_ls_output(jcr, ofile, lname, type, &statp);
+ /* Set attributes after file extracted */
+ break;
case CF_CREATED:
jcr->JobFiles++;
fileAddr = 0;
print_ls_output(jcr, ofile, lname, type, &statp);
+ /* set attributes now because file will not be extracted */
+ set_attributes(jcr, fname, ofile, lname, type, stream,
+ &statp, attribsEx, &bfd);
break;
}
unser_uint64(faddr);
if (fileAddr != faddr) {
fileAddr = faddr;
- if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) {
+ if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
edit_uint64(fileAddr, ec1), ofile, strerror(errno));
goto bail_out;
wsize = sd->msglen;
}
Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total);
- if ((uint32_t)write(ofd, wbuf, wsize) != wsize) {
+ if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
Dmsg0(0, "===Write error===\n");
Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
goto bail_out;
unser_uint64(faddr);
if (fileAddr != faddr) {
fileAddr = faddr;
- if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) {
+ if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
edit_uint64(fileAddr, ec1), ofile, strerror(errno));
goto bail_out;
}
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
- if ((uLong)write(ofd, jcr->compress_buf, compress_len) != compress_len) {
+ if ((uLong)bwrite(&bfd, jcr->compress_buf, compress_len) != compress_len) {
Dmsg0(0, "===Write error===\n");
Jmsg2(jcr, M_ERROR, 0, "Write error on %s: %s\n", ofile, strerror(errno));
goto bail_out;
/* If extracting, wierd stream (not 1 or 2), close output file anyway */
} else if (extract) {
Dmsg1(30, "Found wierd stream %d\n", stream);
- if (ofd < 0) {
- Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n"));
+ if (!is_bopen(&bfd)) {
+ Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
}
set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &ofd);
+ &statp, attribsEx, &bfd);
extract = FALSE;
} else if (!(stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE)) {
Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
/* If output file is still open, it was the last one in the
* archive since we just hit an end of file, so close the file.
*/
- if (ofd >= 0) {
+ if (is_bopen(&bfd)) {
set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &ofd);
+ &statp, attribsEx, &bfd);
}
set_jcr_job_status(jcr, JS_Terminated);
goto ok_out;
{
char attribs[MAXSTRING];
int32_t n;
- int fid, stat;
+ int stat;
+ BFILE bfd;
struct MD5Context md5c;
struct SHA1Context sha1c;
unsigned char signature[25]; /* large enough for either */
if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
ff_pkt->statp.st_size > 0) ||
ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO) {
- if ((fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) {
+ if ((bopen(&bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0)) < 0) {
ff_pkt->ff_errno = errno;
Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
return 1;
}
} else {
- fid = -1;
+ binit(&bfd);
}
encode_stat(attribs, &ff_pkt->statp, ff_pkt->LinkFI);
Dmsg2(20, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
if (!stat) {
Jmsg(jcr, M_ERROR, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
- if (fid >= 0) {
- close(fid);
+ if (is_bopen(&bfd)) {
+ bclose(&bfd);
}
return 0;
}
/* If file opened, compute MD5 */
- if (fid >= 0 && ff_pkt->flags & FO_MD5) {
+ if (is_bopen(&bfd) && ff_pkt->flags & FO_MD5) {
char MD5buf[40]; /* 24 should do */
MD5Init(&md5c);
- while ((n=read(fid, jcr->big_buf, jcr->buf_size)) > 0) {
+ while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) {
MD5Update(&md5c, ((unsigned char *) jcr->big_buf), n);
jcr->JobBytes += n;
}
bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_SIGNATURE, MD5buf,
jcr->JobFiles);
Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
- } else if (fid >= 0 && ff_pkt->flags & FO_SHA1) {
+ } else if (is_bopen(&bfd) && ff_pkt->flags & FO_SHA1) {
char SHA1buf[40]; /* 24 should do */
SHA1Init(&sha1c);
- while ((n=read(fid, jcr->big_buf, jcr->buf_size)) > 0) {
+ while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) {
SHA1Update(&sha1c, ((unsigned char *) jcr->big_buf), n);
jcr->JobBytes += n;
}
SHA1buf, jcr->JobFiles);
Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
}
- if (fid >= 0) {
- close(fid);
+ if (is_bopen(&bfd)) {
+ bclose(&bfd);
}
return 1;
}
#
LIBSRCS = find.c match.c find_one.c attibs.c create_file.c \
- makepath.c save-cwd.c
+ bfile.c makepath.c save-cwd.c
LIBOBJS = find.o match.o find_one.o attribs.o create_file.o \
- makepath.o save-cwd.o
+ bfile.o makepath.o save-cwd.o
.SUFFIXES: .c .o
.PHONY:
static
int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd);
+ char *attribsEx, BFILE *ofd);
void unix_name_to_win32(POOLMEM **win32_name, char *name);
extern "C" HANDLE get_osfhandle(int fd);
void win_error(void *jcr, char *prefix, POOLMEM *ofile);
*/
int set_attributes(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd)
+ char *attribsEx, BFILE *ofd)
{
struct utimbuf ut;
mode_t old_mask;
#endif
old_mask = umask(0);
- if (*ofd != -1) {
- close(*ofd); /* first close file */
- *ofd = -1;
+ if (is_bopen(ofd)) {
+ bclose(ofd); /* first close file */
}
ut.actime = statp->st_atime;
ut.modtime = statp->st_mtime;
/* ***FIXME**** optimize -- don't do if already correct */
+ /*
+ * For link, change owner of link using lchown, but don't
+ * try to do a chmod as that will update the file behind it.
+ */
if (type == FT_LNK) {
+ /* Change owner of link, not of real file */
if (lchown(ofile, statp->st_uid, statp->st_gid) < 0) {
Jmsg2(jcr, M_WARNING, 0, "Unable to set file owner %s: ERR=%s\n",
ofile, strerror(errno));
ofile, strerror(errno));
stat = 0;
}
- }
- if (chmod(ofile, statp->st_mode) < 0) {
- Jmsg2(jcr, M_WARNING, 0, "Unable to set file modes %s: ERR=%s\n",
- ofile, strerror(errno));
- stat = 0;
- }
+ if (chmod(ofile, statp->st_mode) < 0) {
+ Jmsg2(jcr, M_WARNING, 0, "Unable to set file modes %s: ERR=%s\n",
+ ofile, strerror(errno));
+ stat = 0;
+ }
- /* FreeBSD user flags */
+ /* FreeBSD user flags */
#ifdef HAVE_CHFLAGS
- if (chflags(ofile, statp->st_flags) < 0) {
- Jmsg2(jcr, M_WARNING, 0, "Unable to set file flags %s: ERR=%s\n",
- ofile, strerror(errno));
- stat = 0;
- }
+ if (chflags(ofile, statp->st_flags) < 0) {
+ Jmsg2(jcr, M_WARNING, 0, "Unable to set file flags %s: ERR=%s\n",
+ ofile, strerror(errno));
+ stat = 0;
+ }
#endif
- /*
- * Reset file times.
- */
- if (utime(ofile, &ut) < 0) {
- Jmsg2(jcr, M_ERROR, 0, "Unable to set file times %s: ERR=%s\n",
- ofile, strerror(errno));
- stat = 0;
+ /*
+ * Reset file times.
+ */
+ if (utime(ofile, &ut) < 0) {
+ Jmsg2(jcr, M_ERROR, 0, "Unable to set file times %s: ERR=%s\n",
+ ofile, strerror(errno));
+ stat = 0;
+ }
}
umask(old_mask);
return stat;
static
int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd)
+ char *attribsEx, BFILE *ofd)
{
char *p = attribsEx;
int64_t val;
WIN32_FILE_ATTRIBUTE_DATA atts;
ULARGE_INTEGER li;
- int fid, stat;
+ int stat;
POOLMEM *win32_ofile;
if (!p || !*p) { /* we should have attributes */
- Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, *ofd);
- if (*ofd != -1) {
- close(*ofd);
- *ofd = -1;
+ Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, ofd->fid);
+ if (is_bopen(ofd)) {
+ bclose(ofd);
}
return 0;
} else {
win32_ofile = get_pool_memory(PM_FNAME);
unix_name_to_win32(&win32_ofile, ofile);
- if (*ofd == -1) {
+ if (!is_bopen(ofd)) {
Dmsg1(100, "File not open: %s\n", ofile);
- fid = open(ofile, O_RDWR|O_BINARY); /* attempt to open the file */
- if (fid >= 0) {
- *ofd = fid;
- }
+ bopen(ofd, ofile, O_RDWR|O_BINARY, 0); /* attempt to open the file */
}
- if (*ofd != -1) {
+ if (is_open(ofd)) {
Dmsg1(100, "SetFileTime %s\n", ofile);
- stat = SetFileTime(get_osfhandle(*ofd),
+ stat = SetFileTime(get_osfhandle(ofd->fid),
&atts.ftCreationTime,
&atts.ftLastAccessTime,
&atts.ftLastWriteTime);
if (stat != 1) {
win_error(jcr, "SetFileTime:", win32_ofile);
}
- close(*ofd);
- *ofd = -1;
+ bclose(ofd);
}
Dmsg1(100, "SetFileAtts %s\n", ofile);
--- /dev/null
+/*
+ * Bacula low level File I/O routines. This routine simulates
+ * open(), read(), write(), and close(), but using native routines.
+ * I.e. on Windows, we use Windows APIs.
+ *
+ * Kern Sibbald, April 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 "find.h"
+
+
+void binit(BFILE *bfd)
+{
+ bfd->fid = -1;
+}
+
+int bopen(BFILE *bfd, const char *pathname, int flags, mode_t mode)
+{
+ return bfd->fid = open(pathname, flags, mode);
+}
+
+int bclose(BFILE *bfd)
+{
+ int stat = close(bfd->fid);
+ bfd->fid = -1;
+ return stat;
+}
+
+ssize_t bread(BFILE *bfd, void *buf, size_t count)
+{
+ return read(bfd->fid, buf, count);
+}
+
+ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
+{
+ return write(bfd->fid, buf, count);
+}
+
+int is_bopen(BFILE *bfd)
+{
+ return bfd->fid >= 0;
+}
+
+off_t blseek(BFILE *bfd, off_t offset, int whence)
+{
+ return lseek(bfd->fid, offset, whence);
+}
*/
int create_file(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd, int replace)
+ char *attribsEx, BFILE *ofd, int replace)
{
int new_mode, parent_mode, mode;
uid_t uid;
int fnl, pnl;
char *f, *p, savechr;
- *ofd = -1;
+ binit(ofd);
new_mode = statp->st_mode;
Dmsg2(300, "newmode=%x file=%s\n", new_mode, ofile);
parent_mode = S_IWUSR | S_IXUSR | new_mode;
ofile, lname, strerror(errno));
return CF_ERROR;
}
- break;
+ return CF_CREATED;
case FT_REGE: /* empty file */
case FT_REG: /* regular file */
/* Separate pathname and filename */
mode |= O_CTG; /* set contiguous bit if needed */
}
Dmsg1(50, "Create file: %s\n", ofile);
- if ((*ofd = open(ofile, mode, S_IRUSR | S_IWUSR)) < 0) {
+ if ((bopen(ofd, ofile, mode, S_IRUSR | S_IWUSR)) < 0) {
Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), ofile, strerror(errno));
return CF_ERROR;
}
} else {
tid = NULL;
}
- if ((*ofd = open(ofile, mode)) < 0) {
+ if ((bopen(ofd, ofile, mode, 0)) < 0) {
Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), ofile, strerror(errno));
stop_thread_timer(tid);
return CF_ERROR;
char fname[1];
};
+typedef struct s_bfile {
+ int fid; /* file id on Unix */
+} BFILE;
+
/*
* Definition of the find_files packet passed as the
* first argument to the find_files callback subroutine.
*/
-typedef struct ff {
+typedef struct s_ff {
char *fname; /* filename */
char *link; /* link if file linked */
POOLMEM *sys_fname; /* system filename */
uint32_t LinkFI; /* FileIndex of main hard linked file */
struct f_link *linked; /* Set if we are hard linked */
int type; /* FT_ type from above */
- int fid; /* file id if opened */
int flags; /* control flags */
int ff_errno; /* errno */
int incremental; /* do incremental save */
+ BFILE bfd; /* Bacula file descriptor */
time_t save_time; /* start of incremental time */
int mtime_only; /* incremental on mtime_only */
int dereference; /* follow links */
struct f_link *linklist; /* hard linked files */
} FF_PKT;
+
#include "protos.h"
#endif /* __FILES_H */
*/
/* from attribs.c */
-void encode_stat (char *buf, struct stat *statp, uint32_t LinkFI);
-void decode_stat (char *buf, struct stat *statp, uint32_t *LinkFI);
-int encode_attribsEx (void *jcr, char *attribsEx, FF_PKT *ff_pkt);
+void encode_stat (char *buf, struct stat *statp, uint32_t LinkFI);
+void decode_stat (char *buf, struct stat *statp, uint32_t *LinkFI);
+int encode_attribsEx (void *jcr, char *attribsEx, FF_PKT *ff_pkt);
int set_attributes(void *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd);
+ int type, int stream, struct stat *statp,
+ char *attribsEx, BFILE *ofd);
/* from create_file.c */
int create_file(void *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd, int replace);
+ int type, int stream, struct stat *statp,
+ char *attribsEx, BFILE *ofd, int replace);
/* From find.c */
FF_PKT *init_find_files();
int file_is_excluded(FF_PKT *ff, char *file);
int file_is_included(FF_PKT *ff, char *file);
struct s_included_file *get_next_included_file(FF_PKT *ff,
- struct s_included_file *inc);
+ struct s_included_file *inc);
/* From find_one.c */
int find_one_file(JCR *jcr, FF_PKT *ff, int handle_file(FF_PKT *ff_pkt, void *hpkt),
- void *pkt, char *p, dev_t parent_device, int top_level);
+ void *pkt, char *p, dev_t parent_device, int top_level);
int term_find_one(FF_PKT *ff);
/* from 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);
+ int parent_mode, uid_t owner, gid_t group,
+ int preserve_existing, char *verbose_fmt_string);
+
+/* from file_io.c */
+ssize_t bread(BFILE *bfd, void *buf, size_t count);
+int bopen(BFILE *bfd, const char *pathname, int flags, mode_t mode);
+int bclose(BFILE *bfd);
+ssize_t bread(BFILE *bfd, void *buf, size_t count);
+ssize_t bwrite(BFILE *bfd, void *buf, size_t count);
+off_t blseek(BFILE *bfd, off_t offset, int whence);
+int is_bopen(BFILE *bfd);
+void binit(BFILE *bfd);
if (i >= 0) {
Dmsg2(150, "level=%d id=%s\n", level, lc->str);
Dmsg1(150, "Keyword = %s\n", lc->str);
- scan_err1(lc, "Keyword %s not permitted in this resource", lc->str);
+ scan_err1(lc, "Keyword \"%s\" not permitted in this resource", lc->str);
/* NOT REACHED */
}
break;
/* NOT REACHED */
}
}
+ if (state != p_none) {
+ scan_err0(lc, "End of conf file reached with unclosed resource.");
+ }
if (debug_level > 50 && pass == 2) {
int i;
for (i=r_first; i<=r_last; i++) {
int close_wpipe(BPIPE *bpipe);
int close_bpipe(BPIPE *bpipe);
POOLMEM *edit_job_codes(void *jcr, char *omsg, char *imsg, char *to);
+void parse_command_args(POOLMEM *cmd, POOLMEM *args, int *argc,
+ char **argk, char **argv);
+char *next_arg(char **s);
/* watchdog.c */
}
return omsg;
}
+
+/*
+ * Return next argument from command line. Note, this
+ * routine is destructive.
+ */
+char *next_arg(char **s)
+{
+ char *p, *q, *n;
+ int in_quote = 0;
+
+ /* skip past spaces to next arg */
+ for (p=*s; *p && *p == ' '; ) {
+ p++;
+ }
+ Dmsg1(400, "Next arg=%s\n", p);
+ for (n = q = p; *p ; ) {
+ if (*p == '\\') {
+ p++;
+ if (*p) {
+ *q++ = *p++;
+ } else {
+ *q++ = *p;
+ }
+ continue;
+ }
+ if (*p == '"') { /* start or end of quote */
+ if (in_quote) {
+ p++; /* skip quote */
+ in_quote = 0;
+ continue;
+ }
+ in_quote = 1;
+ p++;
+ continue;
+ }
+ if (!in_quote && *p == ' ') { /* end of field */
+ p++;
+ break;
+ }
+ *q++ = *p++;
+ }
+ *q = 0;
+ *s = p;
+ Dmsg2(400, "End arg=%s next=%s\n", n, p);
+ return n;
+}
+
+/*
+ * This routine parses the input command line.
+ * It makes a copy in args, then builds an
+ * argc, argv like list where
+ *
+ * argc = count of arguments
+ * argk[i] = argument keyword (part preceding =)
+ * argv[i] = argument value (part after =)
+ *
+ * example: arg1 arg2=abc arg3=
+ *
+ * argc = c
+ * argk[0] = arg1
+ * argv[0] = NULL
+ * argk[1] = arg2
+ * argv[1] = abc
+ * argk[2] = arg3
+ * argv[2] =
+ */
+
+void parse_command_args(POOLMEM *cmd, POOLMEM *args, int *argc,
+ char **argk, char **argv)
+{
+ char *p, *q, *n;
+ int len;
+
+ len = strlen(cmd) + 1;
+ args = check_pool_memory_size(args, len);
+ bstrncpy(args, cmd, len);
+ strip_trailing_junk(args);
+ *argc = 0;
+ p = args;
+ /* Pick up all arguments */
+ while (*argc < MAX_CMD_ARGS) {
+ n = next_arg(&p);
+ if (*n) {
+ argk[*argc] = n;
+ argv[(*argc)++] = NULL;
+ } else {
+ break;
+ }
+ }
+ /* Separate keyword and value */
+ for (int i=0; i < *argc; i++) {
+ p = strchr(argk[i], '=');
+ if (p) {
+ *p++ = 0; /* terminate keyword and point to value */
+ /* Unquote quoted values */
+ if (*p == '"') {
+ for (n = q = ++p; *p && *p != '"'; ) {
+ if (*p == '\\') {
+ p++;
+ }
+ *q++ = *p++;
+ }
+ *q = 0; /* terminate string */
+ p = n; /* point to string */
+ }
+ if (strlen(p) > MAX_NAME_LENGTH-1) {
+ p[MAX_NAME_LENGTH-1] = 0; /* truncate to max len */
+ }
+ }
+ argv[i] = p; /* save ptr to value or NULL */
+ }
+#ifdef xxxx
+ for (i=0; i<argc; i++) {
+ Dmsg3(000, "Arg %d: kw=%s val=%s\n", i, argk[i], argv[i]?argv[i]:"NULL");
+ }
+#endif
+}
static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
static DEVICE *dev = NULL;
-static int ofd = -1;
+static BFILE bfd;
static JCR *jcr;
static FF_PKT my_ff;
static FF_PKT *ff = &my_ff;
memset(ff, 0, sizeof(FF_PKT));
init_include_exclude_files(ff);
+ binit(&bfd);
while ((ch = getopt(argc, argv, "b:c:d:e:i:?")) != -1) {
switch (ch) {
/* If output file is still open, it was the last one in the
* archive since we just hit an end of file, so close the file.
*/
- if (ofd >= 0) {
+ if (is_bopen(&bfd)) {
set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &ofd);
+ attribsEx, &bfd);
}
release_device(jcr, dev);
* close the output file.
*/
if (extract) {
- if (ofd < 0) {
- Emsg0(M_ERROR, 0, "Logic error output file should be open\n");
+ if (!is_bopen(&bfd)) {
+ Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
}
extract = FALSE;
set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &ofd);
+ attribsEx, &bfd);
}
if (sizeof_pool_memory(fname) < rec->data_len) {
strcat(ofile, "/");
}
strcat(ofile, fn); /* copy rest of name */
- /* Fixup link name */
- if (type == FT_LNK || type == FT_LNKSAVED) {
+ /* Fixup link name for hard links, but not for
+ * soft links
+ */
+ if (type == FT_LNKSAVED) {
if (lp[0] == '/') { /* if absolute path */
strcpy(lname, where);
}
extract = FALSE;
stat = create_file(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &ofd, REPLACE_ALWAYS);
+ &statp, attribsEx, &bfd, REPLACE_ALWAYS);
switch (stat) {
case CF_ERROR:
case CF_SKIP:
break;
case CF_EXTRACT:
extract = TRUE;
- /* Fall-through wanted */
+ print_ls_output(ofile, lname, type, &statp);
+ num_files++;
+ fileAddr = 0;
+ break;
case CF_CREATED:
+ set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
+ attribsEx, &bfd);
print_ls_output(ofile, lname, type, &statp);
num_files++;
fileAddr = 0;
unser_uint64(faddr);
if (fileAddr != faddr) {
fileAddr = faddr;
- if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) {
+ if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
}
}
}
total += wsize;
Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total);
- if ((uint32_t)write(ofd, wbuf, wsize) != wsize) {
+ if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
}
fileAddr += wsize;
unser_uint64(faddr);
if (fileAddr != faddr) {
fileAddr = faddr;
- if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) {
+ if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
}
}
}
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
- if ((uLongf)write(ofd, compress_buf, (size_t)compress_len) != compress_len) {
+ if ((uLongf)bwrite(&bfd, compress_buf, (size_t)compress_len) != compress_len) {
Pmsg0(0, "===Write error===\n");
Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
}
/* If extracting, wierd stream (not 1 or 2), close output file anyway */
} else if (extract) {
- if (ofd < 0) {
- Emsg0(M_ERROR, 0, "Logic error output file should be open\n");
+ if (!is_bopen(&bfd)) {
+ Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
}
extract = FALSE;
set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &ofd);
+ attribsEx, &bfd);
} else if (rec->Stream == STREAM_PROGRAM_NAMES || rec->Stream == STREAM_PROGRAM_DATA) {
if (!prog_name_msg) {
Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
/* */
#define VERSION "1.30"
#define VSTRING "1"
-#define BDATE "10 April 2003"
-#define LSMDATE "10Apr03"
+#define BDATE "12 April 2003"
+#define LSMDATE "12Apr03"
/* Debug flags */
#define DEBUG 1