]> git.sur5r.net Git - bacula/bacula/commitdiff
BFILE I/O, new console @ commands, regression, file mode restore fixes
authorKern Sibbald <kern@sibbald.com>
Sat, 12 Apr 2003 21:01:19 +0000 (21:01 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 12 Apr 2003 21:01:19 +0000 (21:01 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@436 91ce42f0-d328-0410-95d8-f526ca767f89

25 files changed:
bacula/src/baconfig.h
bacula/src/console/console.c
bacula/src/dird/bacula-dir.conf.in
bacula/src/dird/fd_cmds.c
bacula/src/dird/protos.h
bacula/src/dird/ua.h
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_server.c
bacula/src/filed/backup.c
bacula/src/filed/job.c
bacula/src/filed/restore.c
bacula/src/filed/verify.c
bacula/src/findlib/Makefile.in
bacula/src/findlib/attribs.c
bacula/src/findlib/bfile.c [new file with mode: 0644]
bacula/src/findlib/create_file.c
bacula/src/findlib/find.h
bacula/src/findlib/protos.h
bacula/src/lib/parse_conf.c
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/bextract.c
bacula/src/version.h

index 3d3bcadc0a97c17a82ab6a9d8b700bafede7ed15..a332332d081397673a447b536740b7540133f15b 100644 (file)
@@ -75,6 +75,9 @@
 /* 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)
index 69597b46ea722dd8429a3e3f0846fd8c2d08d346..8b00944f951814582395e8c061867e60317546a4 100644 (file)
@@ -45,13 +45,29 @@ extern int rl_catch_signals;
 /* 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 */
@@ -92,6 +108,56 @@ void got_tin(int sig)
 // 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) 
 {
@@ -125,6 +191,14 @@ 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 */
         }
@@ -135,16 +209,16 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
       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 */
@@ -174,6 +248,7 @@ int main(int argc, char *argv[])
    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) {
@@ -248,7 +323,7 @@ Without that I don't how to speak to the Director :-(\n", configfile);
    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)); ) {
@@ -261,7 +336,7 @@ try_again:
       }
       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();
@@ -278,7 +353,7 @@ try_again:
    }
       
 
-   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) {
@@ -315,6 +390,7 @@ static void terminate_console(int sig)
       exit(1);
    }
    already_here = TRUE;
+   free_pool_memory(args);
    exit(0);
 }
 
@@ -389,8 +465,10 @@ get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec)
 {
    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)) {
@@ -414,3 +492,114 @@ again:
 }
 
 #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);
+}
index 034a5b9d8979274da02dada6b5c47350be4f058c..9eface5fd8302fa4d1bd8a435249f78ec007f58b 100644 (file)
@@ -24,14 +24,16 @@ Director {                            # define myself
   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"
@@ -44,7 +46,7 @@ Job {
   Client=@hostname@-fd 
   FileSet="Catalog"
   Schedule = "WeeklyCycleAfterBackup"
-  Storage = DLTDrive
+  Storage = File
   Messages = Standard
   Pool = Default
   # This creates an ASCII copy of the catalog
@@ -60,7 +62,7 @@ Job {
   Type = Restore
   Client=@hostname@-fd 
   FileSet="Full Set"
-  Storage = DLTDrive
+  Storage = File
   Messages = Standard
   Pool = Default
   Where = /tmp/bacula-restores
@@ -75,16 +77,23 @@ FileSet {
 #  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 }
 }
 
@@ -197,3 +206,4 @@ Pool {
   AutoPrune = yes                     # Prune expired volumes
   Volume Retention = 365d             # one year
   Accept Any Volume = yes             # write on any volume in the pool
+}
index fed2e5ae562ef87b552a40f0ac03938e02b3fe82..31ac3208b736c5aa254a7c554f8c140ed79600f1 100644 (file)
@@ -187,6 +187,7 @@ static int send_list(JCR *jcr, int list)
            }
            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));
index d5acce284dd96d66fc2fba703a24f9d25084cf99..05ebb1d88fdec41924aecc6612e2d1ab2dc8d598 100644 (file)
@@ -87,9 +87,8 @@ int create_pool(JCR *jcr, B_DB *db, POOL *pool, int create);
 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);
index 48522f71ddd743da493c3c5fea16948cf798bc0d..b7d33892f55ae24246f41110bddfea845e63f5eb 100644 (file)
@@ -6,7 +6,7 @@
  *     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
@@ -28,7 +28,6 @@
 #ifndef __UA_H_
 #define __UA_H_ 1
 
-#define MAX_ARGS 30
 
 typedef struct s_ua_context {
    BSOCK *UA_sock;
@@ -38,8 +37,8 @@ typedef struct s_ua_context {
    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 */
index 43cb7a1b3b1543daf6f993c3372287533cf4f00b..0d69982c08524c6f83f027ce7addb13da2e5bf61 100644 (file)
@@ -76,6 +76,7 @@ static int delete_volume(UAContext *ua);
 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);
 
@@ -111,6 +112,7 @@ static struct cmdstruct commands[] = {
  { 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))
 
@@ -132,14 +134,15 @@ int do_a_command(UAContext *ua, char *cmd)
    }
 
    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);
    }
@@ -1383,6 +1386,32 @@ int quitcmd(UAContext *ua, char *cmd)
    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;
index 68bb7db56def75d8748f8cea8a48f5dbd06de1ba..13d7d3f6fd34e0c12c54f48c4f2ab540211fe6f1 100644 (file)
@@ -71,118 +71,7 @@ int get_cmd(UAContext *ua, char *prompt)
    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);
 }
index 77e91858f710ee7f35783765090221dda1a5880a..3a280fc135fe034356e2e8ae1967a7cbed20755a 100644 (file)
@@ -271,7 +271,7 @@ int restorecmd(UAContext *ua, char *cmd)
 
    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"));
@@ -577,7 +577,7 @@ static void user_select_files(TREE_CTX *tree)
       if (!get_cmd(tree->ua, "$ ")) {
         break;
       }
-      parse_command_args(tree->ua);
+      parse_ua_args(tree->ua);
       if (tree->ua->argc == 0) {
         return;
       }
index 40378b8b0f126ad5f3e4ffb7aaea9476902e9343..7e710d39d790e0022c915c3735d8a99ec0ffebff 100644 (file)
@@ -127,7 +127,7 @@ static void *handle_UA_client_request(void *arg)
       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 {
index 480fac4b90dbaab5c4d1016313be072bb99e504c..6983dfaa0aaae428d3b17635bd359d0daf289131 100644 (file)
@@ -184,7 +184,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
       } 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);
@@ -192,7 +192,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
       }
       stop_thread_timer(tid);
    } else {
-      ff_pkt->fid = -1;
+      binit(&ff_pkt->bfd);
    }
 
    Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);
@@ -212,8 +212,8 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
     */
 #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;
@@ -248,8 +248,8 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
 
    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;
@@ -261,7 +261,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
     * 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 */
@@ -306,7 +306,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
        *    <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;
       }
@@ -331,7 +331,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
       /* 
        * 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 */
@@ -372,7 +372,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
                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;
            }
@@ -393,7 +393,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
            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;
            }
@@ -410,7 +410,7 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr)
            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);
index 1d06cad6e2ea3960934de26a0d11cc942de7b032..e90e56dc136476b7ee9d7b6b5761b4bd9eea4cec 100644 (file)
@@ -161,7 +161,6 @@ void *handle_client_request(void *dirp)
    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;
 
index 864c3bd36f1d2211777c1ac212400a19500d732d..da0f6c136fe97997476b9e064403701faf800de4 100644 (file)
@@ -55,7 +55,7 @@ void do_restore(JCR *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 */
@@ -64,6 +64,7 @@ void do_restore(JCR *jcr)
    
    wherelen = strlen(jcr->where);
 
+   binit(&bfd);
    sd = jcr->store_bsock;
    set_jcr_job_status(jcr, JS_Running);
 
@@ -127,11 +128,11 @@ void do_restore(JCR *jcr)
          * 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");
         }
@@ -235,12 +236,15 @@ void do_restore(JCR *jcr)
            }   
            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 {
@@ -264,7 +268,7 @@ void do_restore(JCR *jcr)
 
         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:
@@ -274,11 +278,18 @@ void do_restore(JCR *jcr)
            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;
         }  
 
@@ -298,7 +309,7 @@ void do_restore(JCR *jcr)
               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;
@@ -309,7 +320,7 @@ void do_restore(JCR *jcr)
               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;
@@ -336,7 +347,7 @@ void do_restore(JCR *jcr)
               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;
@@ -355,7 +366,7 @@ void do_restore(JCR *jcr)
            }
 
             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;
@@ -373,11 +384,11 @@ void do_restore(JCR *jcr)
       /* 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);
@@ -387,9 +398,9 @@ void do_restore(JCR *jcr)
    /* 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;
index 0af6a2bd4b8f9603579b6fd8eb18ec1beb1f1c11..e996fc6fa5dab831d484a37d2d10042357e25840 100644 (file)
@@ -67,7 +67,8 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt)
 {
    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 */
@@ -140,13 +141,13 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt)
    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);
@@ -182,17 +183,17 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt)
    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;
       }
@@ -207,10 +208,10 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt)
       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;
       }
@@ -226,8 +227,8 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt)
         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;
 }
index 56e9307fd2712db8921f3c3ff9a6ce821e330331..9a8386b96f066b188cde897163c1f0db081a29e3 100644 (file)
@@ -21,9 +21,9 @@ dummy:
 
 #
 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:
index 346f4d43e481aa49f831d147a9dc8635cd41bbc9..13674ca23c33c86bbf4f1e7d3cbb4e7bfefe93f2 100755 (executable)
@@ -39,7 +39,7 @@
 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);
@@ -182,7 +182,7 @@ decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI)
  */
 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;
@@ -201,16 +201,20 @@ int set_attributes(void *jcr, char *fname, char *ofile, char *lname,
 #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));
@@ -222,29 +226,29 @@ int set_attributes(void *jcr, char *fname, char *ofile, char *lname,
            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;
@@ -347,20 +351,19 @@ int encode_attribsEx(void *jcr, char *attribsEx, FF_PKT *ff_pkt)
 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 {
@@ -397,25 +400,21 @@ int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname,
    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);
diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c
new file mode 100644 (file)
index 0000000..74618d1
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  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);
+}
index 8c503d14a775901c0f33fdf461281a50670da24c..2169ad03431b7bdc28412ea5995295300f436c8e 100644 (file)
@@ -60,7 +60,7 @@
  */
 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;
@@ -69,7 +69,7 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname,
    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;
@@ -108,7 +108,7 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname,
               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 */
@@ -162,7 +162,7 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname,
         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;
       }
@@ -208,7 +208,7 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname,
         } 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;
index 4318f9ed24bed266858f49ca149832e05991bd62..8800e49827e9e39bdacc8886e93f8f74ff6547cd 100755 (executable)
@@ -120,12 +120,16 @@ struct s_excluded_file {
    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 */
@@ -134,10 +138,10 @@ typedef struct ff {
    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 */
@@ -152,6 +156,7 @@ typedef struct ff {
    struct f_link *linklist;           /* hard linked files */
 } FF_PKT;
 
+
 #include "protos.h"
 
 #endif /* __FILES_H */
index 770f97ea4b343f24c54d78e2f2745eb0871e64ba..da28b453231ec386a61fd5a83718b610f7438cf4 100644 (file)
  */
 
 /* 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();
@@ -50,15 +50,25 @@ void add_fname_to_exclude_list(FF_PKT *ff, char *fname);
 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);
index a021e1905ea5c79865e36bdab13567f1a669c838..68e9e67050be9a34ff6d1109c425629c54cc1987 100755 (executable)
@@ -679,7 +679,7 @@ parse_config(char *cf)
                     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;
@@ -705,6 +705,9 @@ parse_config(char *cf)
               /* 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++) {
index 350c9e6df42d4ea4a7e636f20457031ad5551b6f..3b195b034b7797a45dede343d0a42111a05742e4 100644 (file)
@@ -153,6 +153,9 @@ BPIPE *      open_bpipe(char *prog, int wait, char *mode);
 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 */
index a38eff903cacd5d380f0de46969ac94eb2d7dfa5..a1230d91232eee33810550141e61f52d1dd2d01c 100644 (file)
@@ -644,3 +644,120 @@ POOLMEM *edit_job_codes(void *mjcr, char *omsg, char *imsg, char *to)
    }
    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
+}
index 69df799ba7415522ac3f977ea944d175cd3c45d7..826a247d49c38ddd7e07215629d2065e560ce878 100644 (file)
@@ -42,7 +42,7 @@ static void do_extract(char *fname);
 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;
@@ -102,6 +102,7 @@ int main (int argc, char *argv[])
 
    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) {
@@ -219,9 +220,9 @@ static void do_extract(char *devname)
    /* 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);
 
@@ -256,12 +257,12 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
        * 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) {
@@ -354,8 +355,10 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
                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);
               }       
@@ -371,15 +374,20 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
         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;
@@ -399,7 +407,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            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));
               }
            }
@@ -409,7 +417,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         }
         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;
@@ -430,7 +438,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            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));
               }
            }
@@ -445,7 +453,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         }
 
          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));
         }
@@ -463,12 +471,12 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
    /* 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");
index 2b1eb3cc193fbc28d15411779dd3f34c2f30a341..bb796f578d11455bc267e986ae8dcbeb6b25b4b1 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #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