]> git.sur5r.net Git - bacula/bacula/commitdiff
Big reorganization of restore code into lib/attr.c
authorKern Sibbald <kern@sibbald.com>
Mon, 9 Jun 2003 16:41:24 +0000 (16:41 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 9 Jun 2003 16:41:24 +0000 (16:41 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@574 91ce42f0-d328-0410-95d8-f526ca767f89

40 files changed:
bacula/kernstodo
bacula/src/baconfig.h
bacula/src/cats/sql_create.c
bacula/src/dird/backup.c
bacula/src/dird/catreq.c
bacula/src/dird/job.c
bacula/src/dird/restore.c
bacula/src/dird/ua_run.c
bacula/src/filed/backup.c
bacula/src/filed/estimate.c
bacula/src/filed/job.c
bacula/src/filed/restore.c
bacula/src/filed/verify.c
bacula/src/filed/verify_vol.c
bacula/src/findlib/attribs.c
bacula/src/findlib/bfile.c
bacula/src/findlib/bfile.h
bacula/src/findlib/create_file.c
bacula/src/findlib/find.c
bacula/src/findlib/find.h
bacula/src/findlib/protos.h
bacula/src/jcr.h
bacula/src/lib/Makefile.in
bacula/src/lib/attr.c [new file with mode: 0644]
bacula/src/lib/attr.h [new file with mode: 0644]
bacula/src/lib/bnet.c
bacula/src/lib/jcr.c
bacula/src/lib/lib.h
bacula/src/lib/message.c
bacula/src/lib/message.h
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/.cvsignore
bacula/src/stored/append.c
bacula/src/stored/bextract.c
bacula/src/stored/bls.c
bacula/src/stored/bscan.c
bacula/src/stored/butil.c
bacula/src/stored/record.c
bacula/src/stored/stored.h

index 874ca22d7cc18ba64e06ed47a47e2e7f8b0dda80..fe52edebffa43e4224da025b925008dd8ec7b657 100644 (file)
@@ -34,10 +34,14 @@ Testing to do: (painful)
 - Figure out how to use ssh or stunnel to protect Bacula communications.
 
 For 1.31 release:
+- Implement non-blocking writes and bsock->terminate in heartbeat thread,
+  or set it in status.c cancel.
+- Add restore to specific date.
 - lstat() is not going to work on Win32 for testing date.
 - Implement a Recycle command
 - Something is not right in last block of fill command.
 - Check this below from Phil.
+  This was SD reported data rather than FD data!
   > When the job was done, Bacula reported 11084 files restored:
   > 
   > JobId:                  527                                                     
index ff4eef9e06f8e23426239716f739be6006b25758..4a7dc15d97ee459f3d2ef1255936e10a0a04d9a0 100644 (file)
 #define DEV_BSIZE 512
 #endif
 
-/* Maximum number of bytes that you can push into a
+/*
+ * Maximum number of bytes that you can push into a
  * socket.
  */
 #define MAX_NETWORK_BUFFER_SIZE (32 * 1024)
 
-/* Stream definitions.  Once defined these must NEVER
+/*
+ * Stream definitions.  Once defined these must NEVER
  *   change as they go on the storage media.
+ * Note, the following streams are passed from the SD to the DIR
+ *   so that they may be put into the catalog (actually only the
+ *   stat packet part of the attr record is put in the catalog.
+ *
+ *   STREAM_UNIX_ATTRIBUTES
+ *   STREAM_UNIX_ATTRIBUTES_EX
+ *   STREAM_MD5_SIGNATURE
+ *   STREAM_SHA1_SIGNATURE
  */
 #define STREAM_UNIX_ATTRIBUTES    1    /* Generic Unix attributes */
 #define STREAM_FILE_DATA          2    /* Standard uncompressed data */
 #define STREAM_MD5_SIGNATURE      3    /* MD5 signature for the file */
 #define STREAM_GZIP_DATA          4    /* GZip compressed file data */
-#define STREAM_UNIX_ATTRIBUTES_EX 5    /* Extended Unix attr. Win32Ex/FreeBSD */
+/* Extended Unix attributes with Win32 Extended data.  Deprecated. */
+#define STREAM_UNIX_ATTRIBUTES_EX 5    /* Extended Unix attr for Win32 EX */
 #define STREAM_SPARSE_DATA        6    /* Sparse data stream */
 #define STREAM_SPARSE_GZIP_DATA   7
 #define STREAM_PROGRAM_NAMES      8    /* program names for program data */
 #define STREAM_SHA1_SIGNATURE    10    /* SHA1 signature for the file */
 #define STREAM_WIN32_DATA        11    /* Win32 BackupRead data */
 #define STREAM_WIN32_GZIP_DATA   12    /* Gzipped Win32 BackupRead data */
+#define STREAM_WIN32_ATTRIBUTES  13    /* Unix attribs, but WIN32_DATA follows */
+
+/* 
+ *  File type (Bacula defined).           
+ *  NOTE!!! These are saved in the Attributes record on the tape, so
+ *          do not change them. If need be, add to them.
+ *
+ *  This is stored as 32 bits on tape, but only FT_MASK bits are
+ *    used for the file type. The upper bits are used to indicate
+ *    additional optional fields in the attribute record.
+ */
+#define FT_MASK       0xFFFF          /* Bits used by FT (type) */
+#define FT_LNKSAVED   1               /* hard link to file already saved */  
+#define FT_REGE       2               /* Regular file but empty */
+#define FT_REG        3               /* Regular file */
+#define FT_LNK        4               /* Soft Link */
+#define FT_DIR        5               /* Directory */
+#define FT_SPEC       6               /* Special file -- chr, blk, fifo, sock */
+#define FT_NOACCESS   7               /* Not able to access */
+#define FT_NOFOLLOW   8               /* Could not follow link */
+#define FT_NOSTAT     9               /* Could not stat file */
+#define FT_NOCHG     10               /* Incremental option, file not changed */
+#define FT_DIRNOCHG  11               /* Incremental option, directory not changed */
+#define FT_ISARCH    12               /* Trying to save archive file */
+#define FT_NORECURSE 13               /* No recursion into directory */
+#define FT_NOFSCHG   14               /* Different file system, prohibited */
+#define FT_NOOPEN    15               /* Could not open directory */
+#define FT_RAW       16               /* Raw block device */
+#define FT_FIFO      17               /* Raw fifo device */
+
+/* Definitions for upper part of type word (see above). */
+#define AR_DATA_STREAM (1<<16)        /* Data stream id present */
 
 /*
  * Internal code for Signature types
index 0b6c4183be0f37eacdcf5080a85c58b9c6553dec..e8edba50b6e78d1d762a4e96fe8f538f6b8fdf07 100644 (file)
@@ -521,8 +521,8 @@ static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
 
    /* Must create it */
    Mmsg(&mdb->cmd,
-"INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \
-LStat, MD5) VALUES (%u, %u, %u, %u, '%s', '0')", 
+"INSERT INTO File (FileIndex,JobId,PathId,FilenameId,"
+"LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')", 
       ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, 
       ar->attr);
 
@@ -589,7 +589,7 @@ static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
       sql_free_result(mdb);
    }
 
-   Mmsg(&mdb->cmd, "INSERT INTO Path (Path)  VALUES ('%s')", mdb->esc_name);
+   Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name);
 
    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"), 
index 21ec4630c068a0c8720badb59908f005cf6169c0..e9151ec85bdbd6e80728a5ec4245b66308981454 100644 (file)
@@ -120,7 +120,7 @@ int do_backup(JCR *jcr)
         jcr->jr.JobId = 0;
         if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) {
             Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
-            Jmsg(jcr, M_INFO, 0, _("No prior or suitable FULL backup found. Doing FULL backup.\n"));
+            Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n"));
             bsnprintf(since, sizeof(since), " (upgraded from %s)", 
               level_to_str(jcr->jr.Level));
            jcr->JobLevel = jcr->jr.Level = L_FULL;
index 9abe3b509d683fd35a3010ee5058ec363b8dd0b3..6c091d90fe868fdab0b46744c9024d92629f56c5 100644 (file)
@@ -356,7 +356,10 @@ next_volume:
 
 /*
  * Update File Attributes in the catalog with data
- *  sent by the Storage daemon.
+ *  sent by the Storage daemon.  Note, we receive the whole
+ *  attribute record, but we select out only the stat packet,
+ *  VolSessionId, VolSessionTime, FileIndex, and file name 
+ *  to store in the catalog.
  */
 void catalog_update(JCR *jcr, BSOCK *bs, char *msg)
 {
index 23f2b98a4c5d157495114743f1ae7bc84dd8750f..c67c4a0129a14950aec17e42d696f40046e69504 100644 (file)
@@ -565,9 +565,6 @@ void dird_free_jcr(JCR *jcr)
       Dmsg0(200, "Close DB\n");
       db_close_database(jcr, jcr->db);
    }
-   if (jcr->RestoreWhere) {
-      free(jcr->RestoreWhere);
-   }
    if (jcr->RestoreBootstrap) {
       free(jcr->RestoreBootstrap);
    }
index a017ab61844f65d0a9cb61d2490f27ff1166e840..52c1b66f88c9964d4734d791228d21de259a3758 100644 (file)
@@ -229,8 +229,8 @@ int do_restore(JCR *jcr)
    } else {
       replace = REPLACE_ALWAYS;       /* always replace */
    }
-   if (jcr->RestoreWhere) {
-      where = jcr->RestoreWhere;      /* override */
+   if (jcr->where) {
+      where = jcr->where;            /* override */
    } else if (jcr->job->RestoreWhere) {
       where = jcr->job->RestoreWhere; /* no override take from job */
    } else {
index e33543e4083ec22ae89605b6a92ebdb17a23c424..2da53b44c422b64f482b1b6054c97d2e8a3f8ece 100644 (file)
@@ -288,10 +288,10 @@ int runcmd(UAContext *ua, char *cmd)
    jcr->fileset = fileset;
    jcr->pool = pool;
    if (where) {
-      if (jcr->RestoreWhere) {
-        free(jcr->RestoreWhere);
+      if (jcr->where) {
+        free(jcr->where);
       }
-      jcr->RestoreWhere = bstrdup(where);
+      jcr->where = bstrdup(where);
    }
 
    if (when) {
@@ -414,7 +414,7 @@ Storage:    %s\n\
 When:       %s\n"),
                 job->hdr.name,
                 NPRT(jcr->RestoreBootstrap),
-                jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
+                jcr->where?jcr->where:NPRT(job->RestoreWhere),
                 replace,
                 jcr->fileset->hdr.name,
                 jcr->client->hdr.name,
@@ -432,7 +432,7 @@ Storage:    %s\n\
 When:       %s\n"),
                 job->hdr.name,
                 NPRT(jcr->RestoreBootstrap),
-                jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
+                jcr->where?jcr->where:NPRT(job->RestoreWhere),
                 replace,
                 jcr->fileset->hdr.name,
                 jcr->client->hdr.name,
@@ -619,14 +619,14 @@ When:       %s\n"),
          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
            break;
         }
-        if (jcr->RestoreWhere) {
-           free(jcr->RestoreWhere);
-           jcr->RestoreWhere = NULL;
+        if (jcr->where) {
+           free(jcr->where);
+           jcr->where = NULL;
         }
          if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
            ua->cmd[0] = 0;
         }
-        jcr->RestoreWhere = bstrdup(ua->cmd);
+        jcr->where = bstrdup(ua->cmd);
         goto try_again;
       case 8:
         /* Replace */
index 8db9a7ebbbe4462b88cbcaca45df9a41ee076c7a..a7f2ea0c247ebf56d404798d88d19c9aac40100a 100644 (file)
@@ -71,7 +71,7 @@ int blast_data_to_storage_daemon(JCR *jcr, char *addr)
    jcr->compress_buf = get_memory(jcr->compress_buf_size);
 
    Dmsg1(100, "set_find_options ff=%p\n", jcr->ff);
-   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
+   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only);
    Dmsg0(110, "start find files\n");
 
    start_heartbeat_monitor(jcr);
index dbec154325c59eebfabb23747bf089d14b453b39..24d047171711bbd5871a60458a3c92fbaf9dd9f3 100644 (file)
@@ -41,7 +41,7 @@ int make_estimate(JCR *jcr)
 
    jcr->JobStatus = JS_Running;
 
-   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
+   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only);
 
    stat = find_files(jcr, (FF_PKT *)jcr->ff, tally_file, (void *)jcr);
 
index 274bb7426df2196d247c38149de4d2ca1d251bef..343f1d2f7e372977f9545b4fec04de4a9b22e8a8 100644 (file)
@@ -739,7 +739,8 @@ static int restore_cmd(JCR *jcr)
       
    Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
    unbash_spaces(where);
-   jcr->where = where;
+   jcr->where = bstrdup(where);
+   free_pool_memory(where);
    jcr->replace = replace;
 
    bnet_fsend(dir, OKrestore);
@@ -854,9 +855,6 @@ static void filed_free_jcr(JCR *jcr)
    if (jcr->store_bsock) {
       bnet_close(jcr->store_bsock);
    }
-   if (jcr->where) {
-      free_pool_memory(jcr->where);
-   }
    if (jcr->RestoreBootstrap) {
       unlink(jcr->RestoreBootstrap);
       free_pool_memory(jcr->RestoreBootstrap);
index 766dd74e8151183091931d6797145d1c4b52581a..8b4a7e0772d7e1c588326db94984ef6bfaa72fb0 100644 (file)
@@ -33,7 +33,6 @@
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
 /* Forward referenced functions */
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp);
 
 #define RETRY 10                     /* retry wait time */
 
@@ -45,22 +44,21 @@ void do_restore(JCR *jcr)
 {
    int wherelen;
    BSOCK *sd;
-   POOLMEM *fname;                   /* original file name */
-   POOLMEM *ofile;                   /* output name with possible prefix */
-   POOLMEM *lname;                   /* link name with possible prefix */
-   POOLMEM *attribsEx;               /* Extended attributes (Win32) */
    int32_t stream;
    uint32_t size;
-   uint32_t VolSessionId, VolSessionTime, file_index;
-   uint32_t record_file_index;
-   struct stat statp;
+   uint32_t VolSessionId, VolSessionTime;
+   int32_t file_index;
    int extract = FALSE;
    BFILE bfd;
-   int type, stat;
+   int stat;
    uint32_t total = 0;               /* Job total but only 32 bits for debug */
    char *wbuf;                       /* write buffer */
    uint32_t wsize;                   /* write size */
    uint64_t fileAddr = 0;            /* file write address */
+   int non_support_data = 0;
+   int non_support_attr = 0;
+   int prog_name_msg = 0;
+   ATTR *attr;
    
    wherelen = strlen(jcr->where);
 
@@ -74,10 +72,7 @@ void do_restore(JCR *jcr)
    }
    jcr->buf_size = sd->msglen;
 
-   fname = get_pool_memory(PM_FNAME);
-   ofile = get_pool_memory(PM_FNAME);
-   lname = get_pool_memory(PM_FNAME);
-   attribsEx = get_pool_memory(PM_FNAME);
+   attr = new_attr();
 
 #ifdef HAVE_LIBZ
    uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
@@ -119,8 +114,9 @@ void do_restore(JCR *jcr)
       Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
 
       /* File Attributes stream */
-      if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) {
-        char *ap, *lp, *fp, *apex;
+      switch (stream) {
+      case STREAM_UNIX_ATTRIBUTES:
+      case STREAM_UNIX_ATTRIBUTES_EX:
         uint32_t LinkFI;
 
          Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
@@ -131,149 +127,33 @@ void do_restore(JCR *jcr)
            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, &bfd);
+           set_attributes(jcr, attr, &bfd);
            extract = FALSE;
             Dmsg0(30, "Stop extracting.\n");
         }
 
-        if ((int)sizeof_pool_memory(fname) <  sd->msglen) {
-           fname = realloc_pool_memory(fname, sd->msglen + 1);
-        }
-        if ((int)sizeof_pool_memory(ofile) < sd->msglen + wherelen + 1) {
-           ofile = realloc_pool_memory(ofile, sd->msglen + wherelen + 1);
-        }
-        if ((int)sizeof_pool_memory(lname) < sd->msglen + wherelen + 1) {
-           lname = realloc_pool_memory(lname, sd->msglen + wherelen + 1);
-        }
-        *fname = 0;
-        *lname = 0;
-
-        /*              
-         * An Attributes record consists of:
-         *    File_index
-         *    Type   (FT_types)
-         *    Filename
-         *    Attributes
-         *    Link name (if file linked i.e. FT_LNK)
-         *    Extended attributes (Win32)
-         *
-         */
-         Dmsg1(100, "Attr: %s\n", sd->msg);
-         if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
-            Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), sd->msg);
-            Dmsg1(100, "\nError scanning attributes. %s\n", sd->msg);
+        if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
            goto bail_out;
         }
-         Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
-        if (record_file_index != file_index) {
+        if (file_index != attr->file_index) {
             Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
-              file_index, record_file_index);
+                file_index, attr->file_index);
             Dmsg0(100, "File index error\n");
            goto bail_out;
         }
-        ap = sd->msg;
-         while (*ap++ != ' ')         /* skip record file index */
-           ;
-         while (*ap++ != ' ')         /* skip type */
-           ;
-        /* Save filename and position to attributes */
-        fp = fname;
-        while (*ap != 0) {
-           *fp++  = *ap++;           /* copy filename to fname */
-        }
-        *fp = *ap++;                 /* terminate filename & point to attribs */
+           
+         Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname, 
+              attr->attr, attr->attrEx);
 
-        /* Skip to Link name */
-        if (type == FT_LNK || type == FT_LNKSAVED) {
-           lp = ap;
-           while (*lp++ != 0) {
-              ;
-           }
-        } else {
-            lp = "";
-        }
+        decode_stat(attr->attr, &attr->statp, &LinkFI);
 
-        if (stream == STREAM_WIN32_ATTRIBUTES) {
-           apex = ap;                   /* start at attributes */
-           while (*apex++ != 0) {       /* skip attributes */
-              ;
-           }
-           while (*apex++ != 0) {       /* skip link name */
-              ;
-           }
-           pm_strcpy(&attribsEx, apex); /* make a copy */
-        } else {
-           *attribsEx = 0;              /* no extended attributes */
-        }
-
-         Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", fname, ap, attribsEx);
-
-        decode_stat(ap, &statp, &LinkFI);
-        /*
-         * Prepend the where directory so that the
-         * files are put where the user wants.
-         *
-         * We do a little jig here to handle Win32 files with
-         *   a drive letter -- we simply strip the drive: from
-         *   every filename if a prefix is supplied.
-         *     
-         */
-        if (jcr->where[0] == 0) {
-           strcpy(ofile, fname);
-           strcpy(lname, lp);
-        } else {
-           char *fn;
-           strcpy(ofile, jcr->where);  /* copy prefix */
-            if (win32_client && fname[1] == ':') {
-              fn = fname+2;          /* skip over drive: */
-           } else {
-              fn = fname;            /* take whole name */
-           }
-           /* Ensure where is terminated with a slash */
-            if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
-               strcat(ofile, "/");
-           }   
-           strcat(ofile, fn);        /* copy rest of name */
-           /*
-            * Fixup link name -- if it is an absolute path
-            */
-           if (type == FT_LNKSAVED || type == FT_LNK) {
-              int add_link;
-              /* 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 {
-                 lname[0] = 0;
-                 add_link = 0;
-              }
-               if (win32_client && lp[1] == ':') {
-                 fn = lp+2;             /* skip over drive: */
-              } else {
-                 fn = lp;               /* take whole name */
-              }
-              /* Ensure where is terminated with a slash */
-               if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
-                  strcat(lname, "/");
-              }   
-              strcat(lname, fn);     /* copy rest of link */
-           }
-        }
+        build_attr_output_fnames(jcr, attr);
 
-        P(jcr->mutex);
-        pm_strcpy(&jcr->last_fname, fname);
-        V(jcr->mutex);
         jcr->num_files_examined++;
 
-         Dmsg1(30, "Outfile=%s\n", ofile);
+         Dmsg1(30, "Outfile=%s\n", attr->ofname);
         extract = FALSE;
-        stat = create_file(jcr, fname, ofile, lname, type, 
-                           stream, &statp, attribsEx, &bfd, 
-                           jcr->replace);
+        stat = create_file(jcr, attr, &bfd, jcr->replace);
         switch (stat) {
         case CF_ERROR:
         case CF_SKIP:
@@ -281,32 +161,43 @@ void do_restore(JCR *jcr)
         case CF_EXTRACT:
            extract = TRUE;
            P(jcr->mutex);
-           pm_strcpy(&jcr->last_fname, ofile);
+           pm_strcpy(&jcr->last_fname, attr->ofname);
            V(jcr->mutex);
            jcr->JobFiles++;
            fileAddr = 0;
-           print_ls_output(jcr, ofile, lname, type, &statp);
+           print_ls_output(jcr, attr);
            /* Set attributes after file extracted */
            break;
         case CF_CREATED:
+           P(jcr->mutex);
+           pm_strcpy(&jcr->last_fname, attr->ofname);
+           V(jcr->mutex);
            jcr->JobFiles++;
            fileAddr = 0;
-           print_ls_output(jcr, ofile, lname, type, &statp);
+           print_ls_output(jcr, attr);
            /* set attributes now because file will not be extracted */
-           set_attributes(jcr, fname, ofile, lname, type, stream, 
-                          &statp, attribsEx, &bfd);
+           set_attributes(jcr, attr, &bfd);
            break;
         }  
+        break;
 
-
-      /* Data stream */
-      } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA ||
-                stream == STREAM_WIN32_DATA) {
-        if (stream == STREAM_WIN32_DATA && !is_win32_backup()) {
-            Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n"));
+      /* Windows Backup data stream */
+      case STREAM_WIN32_DATA:  
+        if (!is_win32_backup()) {
+           if (!non_support_data) {
+               Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n"));
+           }
            extract = FALSE;
+           non_support_data++;
            continue;
         }
+        goto extract_data;
+
+      /* Data stream */
+      case STREAM_FILE_DATA:
+      case STREAM_SPARSE_DATA: 
+
+extract_data:
         if (extract) {
            if (stream == STREAM_SPARSE_DATA) {
               ser_declare;
@@ -321,7 +212,7 @@ void do_restore(JCR *jcr)
                  fileAddr = faddr;
                  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, berror(&bfd));
+                        edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
                     extract = FALSE;
                     continue;
                  }
@@ -333,7 +224,7 @@ void do_restore(JCR *jcr)
             Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total);
            if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
                Dmsg0(0, "===Write error===\n");
-               Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), ofile, berror(&bfd));
+               Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), attr->ofname, berror(&bfd));
               extract = FALSE;
               continue;
            } 
@@ -342,15 +233,23 @@ void do_restore(JCR *jcr)
            jcr->ReadBytes += wsize;
            fileAddr += wsize;
         }
-       
-      /* GZIP data stream */
-      } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA ||
-                stream == STREAM_WIN32_GZIP_DATA) {
-        if (stream == STREAM_WIN32_GZIP_DATA && !is_win32_backup()) {
-            Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n"));
+        break;
+
+      /* Windows Backup GZIP data stream */
+      case STREAM_WIN32_GZIP_DATA:  
+        if (!is_win32_backup()) {
+           if (!non_support_attr) {
+               Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n"));
+           }
            extract = FALSE;
+           non_support_attr++;
            continue;
         }
+        /* Fall through desired */
+
+      /* GZIP data stream */
+      case STREAM_GZIP_DATA:
+      case STREAM_SPARSE_GZIP_DATA:  
 #ifdef HAVE_LIBZ
         if (extract) {
            ser_declare;
@@ -368,7 +267,7 @@ void do_restore(JCR *jcr)
                  fileAddr = faddr;
                  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, berror(&bfd));
+                        edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
                     extract = FALSE;
                     continue;
                  }
@@ -389,7 +288,7 @@ void do_restore(JCR *jcr)
             Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
            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, berror(&bfd));
+               Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, berror(&bfd));
               extract = FALSE;
               continue;
            }
@@ -405,26 +304,42 @@ void do_restore(JCR *jcr)
            continue;
         }
 #endif
-      /* If extracting, wierd stream (not 1 or 2), close output file anyway */
-      } else if (extract) {
-         Dmsg1(30, "Found wierd stream %d\n", stream);
-        if (!is_bopen(&bfd)) {
-            Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
+        break;
+
+      case STREAM_MD5_SIGNATURE:
+      case STREAM_SHA1_SIGNATURE:
+        break;
+
+      case STREAM_PROGRAM_NAMES:
+      case STREAM_PROGRAM_DATA:
+        if (!prog_name_msg) {
+            Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
+           prog_name_msg++;
         }
-        set_attributes(jcr, fname, ofile, lname, type, stream, 
-                       &statp, attribsEx, &bfd);
-        extract = FALSE;
-      } else if (!(stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE)) {
+        break;
+
+      default:
+        /* If extracting, wierd stream (not 1 or 2), close output file anyway */
+        if (extract) {
+            Dmsg1(30, "Found wierd stream %d\n", stream);
+           if (!is_bopen(&bfd)) {
+               Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
+           }
+           set_attributes(jcr, attr, &bfd);
+           extract = FALSE;
+        }
+         Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
          Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
-      }
-   }
+        break;
+      } /* end switch(stream) */
+
+   } /* end while get_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 (is_bopen(&bfd)) {
-      set_attributes(jcr, fname, ofile, lname, type, stream, 
-                    &statp, attribsEx, &bfd);
+      set_attributes(jcr, attr, &bfd);
    }
    set_jcr_job_status(jcr, JS_Terminated);
    goto ok_out;
@@ -436,52 +351,11 @@ ok_out:
       free(jcr->compress_buf);
       jcr->compress_buf = NULL;
    }
-   free_pool_memory(fname);
-   free_pool_memory(ofile);
-   free_pool_memory(lname);
-   free_pool_memory(attribsEx);
+   free_attr(attr);
    Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
       jcr->JobBytes);
-}         
-
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
-
-/*
- * Print an ls style message, also send INFO
- */
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp)
-{
-   char buf[5000]; 
-   char ec1[30];
-   char *p, *f;
-   int n;
-
-   p = encode_mode(statp->st_mode, buf);
-   n = sprintf(p, "  %2d ", (uint32_t)statp->st_nlink);
-   p += n;
-   n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
-   p += n;
-   n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
-   p += n;
-   p = encode_time(statp->st_ctime, p);
-   *p++ = ' ';
-   *p++ = ' ';
-   for (f=fname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
-      *p++ = *f++;
+   if (non_support_data > 1 || non_support_attr > 1) {
+      Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
+        non_support_data, non_support_attr);
    }
-   if (type == FT_LNK) {
-      *p++ = ' ';
-      *p++ = '-';
-      *p++ = '>';
-      *p++ = ' ';
-      /* Copy link name */
-      for (f=lname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
-        *p++ = *f++;
-      }
-   }
-   *p++ = '\n';
-   *p = 0;
-   Dmsg1(20, "%s", buf);
-   Jmsg(jcr, M_RESTORED, 0, "%s", buf);
-}
+}         
index 65b1607f8ccd93a590138ec2c63c854c785ea8ba..2919ad3fb27a2bcd65bceb49bea5b6d5d25af5c3 100644 (file)
@@ -43,7 +43,7 @@ void do_verify(JCR *jcr)
    if ((jcr->big_buf = (char *) malloc(jcr->buf_size)) == NULL) {
       Jmsg1(jcr, M_ABORT, 0, _("Cannot malloc %d network read buffer\n"), MAX_NETWORK_BUFFER_SIZE);
    }
-   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
+   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only);
    Dmsg0(10, "Start find files\n");
    /* Subroutine verify_file() is called for each file */
    find_files(jcr, (FF_PKT *)jcr->ff, verify_file, (void *)jcr);  
index 839874e633b81ddffd394d30afe4804becd8b04c..0fc907a9bc5cc6beb1f37260cdf0295383c921c4 100644 (file)
@@ -34,9 +34,6 @@
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
 /* Forward referenced functions */
-#ifdef needed
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp);
-#endif
 
 
 /* 
@@ -102,7 +99,7 @@ void do_verify_volume(JCR *jcr)
       /* File Attributes stream */
       switch (stream) {
       case STREAM_UNIX_ATTRIBUTES:
-      case STREAM_WIN32_ATTRIBUTES:
+      case STREAM_UNIX_ATTRIBUTES_EX:
         char *ap, *lp, *fp;
 
          Dmsg0(400, "Stream=Unix Attributes.\n");
@@ -246,45 +243,3 @@ ok_out:
    Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
       jcr->JobBytes);
 }         
-
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
-
-/*
- * Print an ls style message, also send INFO
- */
-#ifdef needed
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp)
-{
-   char buf[2000]; 
-   char ec1[30];
-   char *p, *f;
-   int n;
-
-   p = encode_mode(statp->st_mode, buf);
-   n = sprintf(p, "  %2d ", (uint32_t)statp->st_nlink);
-   p += n;
-   n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
-   p += n;
-   n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
-   p += n;
-   p = encode_time(statp->st_ctime, p);
-   *p++ = ' ';
-   *p++ = ' ';
-   for (f=fname; *f && (p-buf) < (int)sizeof(buf)-10; )
-      *p++ = *f++;
-   if (type == FT_LNK) {
-      *p++ = ' ';
-      *p++ = '-';
-      *p++ = '>';
-      *p++ = ' ';
-      /* Copy link name */
-      for (f=lname; *f && (p-buf) < (int)sizeof(buf)-10; )
-        *p++ = *f++;
-   }
-   *p++ = '\n';
-   *p = 0;
-   Dmsg0(20, buf);
-   Jmsg(jcr, M_INFO, 0, "%s", buf);
-}
-#endif
index 07f9092e47cd0e0451b1fcf293b53551d7a207d8..9ee69f574a7e7621592eb89f9b2fe6912bfabde9 100755 (executable)
@@ -35,9 +35,7 @@
 
 /* Forward referenced subroutines */
 static
-int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, 
-                        int type, int stream, struct stat *statp,
-                        char *attribsEx, BFILE *ofd);
+int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd);
 void unix_name_to_win32(POOLMEM **win32_name, char *name);
 void win_error(JCR *jcr, char *prefix, POOLMEM *ofile);
 HANDLE bget_handle(BFILE *bfd);
@@ -55,7 +53,17 @@ HANDLE bget_handle(BFILE *bfd);
 /*=============================================================*/
 
 
-/* Encode a stat structure into a base64 character string */
+/* 
+ * Encode a stat structure into a base64 character string   
+ *   All systems must create such a structure.
+ *   In addition, we tack on the LinkFI, which is non-zero in
+ *   the case of a hard linked file that has no data.  This
+ *   is a File Index pointing to the link that does have the
+ *   data (always the first one encountered in a save).
+ * You may piggyback attributes on this packet by encoding
+ *   them in the encode_attribsEx() subroutine, but this is
+ *   not recommended.
+ */
 void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI)
 {
    char *p = buf;
@@ -180,17 +188,15 @@ decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI)
  * Returns:  1 on success
  *          0 on failure
  */
-int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname, 
-                  int type, int stream, struct stat *statp,
-                  char *attribsEx, BFILE *ofd)
+int set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
 {
    struct utimbuf ut;   
    mode_t old_mask;
    int stat = 1;
 
 #ifdef HAVE_CYGWIN
-   if (set_win32_attributes(jcr, fname, ofile, lname, type, stream,
-                           statp, attribsEx, ofd)) {
+   if (stream == STREAM_UNIX_ATTRIBUTES_EX &&
+       set_win32_attributes(jcr, attr, ofd)) {
       return 1;
    }
    /*
@@ -205,47 +211,47 @@ int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
       bclose(ofd);                   /* first close file */
    }
 
-   ut.actime = statp->st_atime;
-   ut.modtime = statp->st_mtime;
+   ut.actime = attr->statp.st_atime;
+   ut.modtime = attr->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) {
+   if (attr->type == FT_LNK) {
       /* Change owner of link, not of real file */
-      if (lchown(ofile, statp->st_uid, statp->st_gid) < 0) {
+      if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
          Jmsg2(jcr, M_WARNING, 0, _("Unable to set file owner %s: ERR=%s\n"),
-           ofile, strerror(errno));
+           attr->ofname, strerror(errno));
         stat = 0;
       }
    } else {
-      if (chown(ofile, statp->st_uid, statp->st_gid) < 0) {
+      if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
          Jmsg2(jcr, M_WARNING, 0, _("Unable to set file owner %s: ERR=%s\n"),
-           ofile, strerror(errno));
+           attr->ofname, strerror(errno));
         stat = 0;
       }
-      if (chmod(ofile, statp->st_mode) < 0) {
+      if (chmod(attr->ofname, attr->statp.st_mode) < 0) {
          Jmsg2(jcr, M_WARNING, 0, _("Unable to set file modes %s: ERR=%s\n"),
-           ofile, strerror(errno));
+           attr->ofname, strerror(errno));
         stat = 0;
       }
 
       /* FreeBSD user flags */
 #ifdef HAVE_CHFLAGS
-      if (chflags(ofile, statp->st_flags) < 0) {
+      if (chflags(attr->ofname, attr->statp.st_flags) < 0) {
          Jmsg2(jcr, M_WARNING, 0, _("Unable to set file flags %s: ERR=%s\n"),
-           ofile, strerror(errno));
+           attr->ofname, strerror(errno));
         stat = 0;
       }
 #endif
       /*
        * Reset file times.
        */
-      if (utime(ofile, &ut) < 0) {
+      if (utime(attr->ofname, &ut) < 0) {
          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"),
-           ofile, strerror(errno));
+           attr->ofname, strerror(errno));
         stat = 0;
       }
    }
@@ -263,8 +269,13 @@ int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
 #ifndef HAVE_CYGWIN
     
 /*
- * If you have a Unix system with extended attributes (e.g.
- *  ACLs for Solaris, do it here.
+ * It is possible to piggyback additional data e.g. ACLs on
+ *   the encode_stat() data by returning the extended attributes
+ *   here.  They must be "self-contained" (i.e. you keep track
+ *   of your own length), and they must be in ASCII string
+ *   format. Using this feature is not recommended.
+ * The code below shows how to return nothing. See the Win32
+ *   code below for returning something in the attributes.
  */
 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 {
@@ -300,7 +311,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
    if (!p_GetFileAttributesEx(ff_pkt->sys_fname, GetFileExInfoStandard,
                            (LPVOID)&atts)) {
       win_error(jcr, "GetFileAttributesEx:", ff_pkt->sys_fname);
-      return STREAM_WIN32_ATTRIBUTES;
+      return STREAM_UNIX_ATTRIBUTES_EX;
    }
 
    p += to_base64((uint64_t)atts.dwFileAttributes, p);
@@ -321,7 +332,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
    *p++ = ' ';
    p += to_base64((uint64_t)atts.nFileSizeLow, p);
    *p = 0;
-   return STREAM_WIN32_ATTRIBUTES;
+   return STREAM_UNIX_ATTRIBUTES_EX;
 }
 
 /* Define attributes that are legal to set with SetFileAttributes() */
@@ -346,24 +357,22 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
  *          0 on failure
  */
 static
-int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname, 
-                        int type, int stream, struct stat *statp,
-                        char *attribsEx, BFILE *ofd)
+int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
 {
-   char *p = attribsEx;
+   char *p = attr->attrEx;
    int64_t val;
    WIN32_FILE_ATTRIBUTE_DATA atts;
    ULARGE_INTEGER li;
    POOLMEM *win32_ofile;
 
    if (!p || !*p) {                  /* we should have attributes */
-      Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, ofd->fid);
+      Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid);
       if (is_bopen(ofd)) {
         bclose(ofd);
       }
       return 0;
    } else {
-      Dmsg2(100, "Attribs %s = %s\n", ofile, attribsEx);
+      Dmsg2(100, "Attribs %s = %s\n", attr->ofname, attr->attrEx);
    }
 
    p += from_base64(&val, p);
@@ -392,7 +401,7 @@ int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
 
    /* Convert to Windows path format */
    win32_ofile = get_pool_memory(PM_FNAME);
-   unix_name_to_win32(&win32_ofile, ofile);
+   unix_name_to_win32(&win32_ofile, attr->ofname);
 
 
 
@@ -400,12 +409,12 @@ int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
 
 
    if (!is_bopen(ofd)) {
-      Dmsg1(100, "File not open: %s\n", ofile);
-      bopen(ofd, ofile, O_WRONLY|O_BINARY, 0);  /* attempt to open the file */
+      Dmsg1(100, "File not open: %s\n", attr->ofname);
+      bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0);  /* attempt to open the file */
    }
 
    if (is_bopen(ofd)) {
-      Dmsg1(100, "SetFileTime %s\n", ofile);
+      Dmsg1(100, "SetFileTime %s\n", attr->ofname);
       if (!SetFileTime(bget_handle(ofd),
                         &atts.ftCreationTime,
                         &atts.ftLastAccessTime,
@@ -415,7 +424,7 @@ int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
       bclose(ofd);
    }
 
-   Dmsg1(100, "SetFileAtts %s\n", ofile);
+   Dmsg1(100, "SetFileAtts %s\n", attr->ofname);
    if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
       if (!SetFileAttributes(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) {
          win_error(jcr, "SetFileAttributes:", win32_ofile);
index adbd0ac208836481cd0080bf690f48ff0de1f228..a42eb0300697229882685b525470c0856166a9d0 100644 (file)
@@ -63,11 +63,44 @@ int set_win32_backup(BFILE *bfd, int enable)
    return bfd->use_backup_api;
 }
 
+/*
+ * Return 1 if we can do Win32 backup
+ * return 0 if not
+ */
 int is_win32_backup(void)
 {
    return p_BackupRead && p_BackupWrite;
 }
 
+int is_stream_supported(int stream)
+{
+   if (is_win32_backup()) {
+      return 1;
+   }
+   /* No Win32 backup on this machine */
+   switch (stream) {
+   case STREAM_WIN32_ATTRIBUTES:
+   case STREAM_WIN32_DATA:
+   case STREAM_WIN32_GZIP_DATA:
+      return 0;
+
+   /* Known streams */
+   case STREAM_UNIX_ATTRIBUTES:
+   case STREAM_FILE_DATA:
+   case STREAM_MD5_SIGNATURE:
+   case STREAM_GZIP_DATA:
+   case STREAM_UNIX_ATTRIBUTES_EX:
+   case STREAM_SPARSE_DATA:
+   case STREAM_SPARSE_GZIP_DATA:
+   case STREAM_PROGRAM_NAMES:
+   case STREAM_PROGRAM_DATA:
+   case STREAM_SHA1_SIGNATURE:
+      return 1;
+
+   }
+   return 0;
+}
+
 HANDLE bget_handle(BFILE *bfd)
 {
    return bfd->fh;
@@ -308,6 +341,31 @@ int is_win32_backup(void)
    return 0;
 }
 
+int is_stream_supported(int stream)
+{
+   /* No Win32 backup on this machine */
+   switch (stream) {
+   case STREAM_WIN32_ATTRIBUTES:
+   case STREAM_WIN32_DATA:
+   case STREAM_WIN32_GZIP_DATA:
+      return 0;
+
+   /* Known streams */
+   case STREAM_UNIX_ATTRIBUTES:
+   case STREAM_FILE_DATA:
+   case STREAM_MD5_SIGNATURE:
+   case STREAM_GZIP_DATA:
+   case STREAM_UNIX_ATTRIBUTES_EX:
+   case STREAM_SPARSE_DATA:
+   case STREAM_SPARSE_GZIP_DATA:
+   case STREAM_PROGRAM_NAMES:
+   case STREAM_PROGRAM_DATA:
+   case STREAM_SHA1_SIGNATURE:
+      return 1;
+
+   }
+   return 0;
+}
 
 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
 {
index a666072e3ea30cdcef072eaf0aeb5774d478a79a..5250847eb9821a244af60d011f9152405dbf650d 100644 (file)
 #include "winapi.h"
 
 #define BF_CLOSED 0
-#define BF_READ   1                   /* BackupRead */
-#define BF_WRITE  2                   /* BackupWrite */
+#define BF_READ   1                  /* BackupRead */
+#define BF_WRITE  2                  /* BackupWrite */
 
 /* In bfile.c */
 
 /* Basic low level I/O file packet */
 typedef struct s_bfile {
 #ifdef xxx
-   int use_win_api;                   /* set if using WinAPI */
+   int use_win_api;                  /* set if using WinAPI */
 #endif
-   int use_backup_api;                /* set if using BackupRead/Write */
-   int mode;                          /* set if file is open */
-   HANDLE fh;                         /* Win32 file handle */
-   int fid;                           /* fd if doing Unix style */
-   LPVOID lpContext;                  /* BackupRead/Write context */
-   POOLMEM *errmsg;                   /* error message buffer */
-   DWORD rw_bytes;                    /* Bytes read or written */
-   DWORD lerror;                      /* Last error code */
+   int use_backup_api;               /* set if using BackupRead/Write */
+   int mode;                         /* set if file is open */
+   HANDLE fh;                        /* Win32 file handle */
+   int fid;                          /* fd if doing Unix style */
+   LPVOID lpContext;                 /* BackupRead/Write context */
+   POOLMEM *errmsg;                  /* error message buffer */
+   DWORD rw_bytes;                   /* Bytes read or written */
+   DWORD lerror;                     /* Last error code */
 } BFILE;
 
 HANDLE bget_handle(BFILE *bfd);
 
-#else   /* Linux/Unix systems */
+#else  /* Linux/Unix systems */
 
 /* Basic low level I/O file packet */
 typedef struct s_bfile {
-   int fid;                           /* file id on Unix */
+   int fid;                          /* file id on Unix */
    int berrno;
 } BFILE;
 
 #endif
 
-void binit(BFILE *bfd);
-int is_bopen(BFILE *bfd);
-int set_win32_backup(BFILE *bfd, int enable);
-int is_win32_backup();
-char *berror(BFILE *bfd);
-int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
-int bclose(BFILE *bfd);
+void   binit(BFILE *bfd);
+int    is_bopen(BFILE *bfd);
+int    set_win32_backup(BFILE *bfd, int enable);
+int    is_win32_backup();
+int    is_stream_supported(int stream);
+char   *berror(BFILE *bfd);
+int    bopen(BFILE *bfd, const char *fname, 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);
+off_t  blseek(BFILE *bfd, off_t offset, int whence);
 
 #endif /* __BFILE_H */
index 37e7c3e84b74694873579c91665488df68a89723..279f209ad9b4a62b84e3d83f9e1904f1c542f108 100644 (file)
@@ -61,9 +61,7 @@ static int path_already_seen(char *path, int pnl);
  *     files.
  *
  */
-int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
-               int type, int stream, struct stat *statp, 
-               char *attribsEx, BFILE *ofd, int replace)
+int create_file(JCR *jcr, ATTR *attr, BFILE *ofd, int replace)
 {
    int new_mode, parent_mode, mode;
    uid_t uid;
@@ -71,37 +69,37 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
    int pnl;
 
    binit(ofd);
-   new_mode = statp->st_mode;
-   Dmsg2(300, "newmode=%x file=%s\n", new_mode, ofile);
+   new_mode = attr->statp.st_mode;
+   Dmsg2(300, "newmode=%x file=%s\n", new_mode, attr->ofname);
    parent_mode = S_IWUSR | S_IXUSR | new_mode;
-   gid = statp->st_gid;
-   uid = statp->st_uid;
+   gid = attr->statp.st_gid;
+   uid = attr->statp.st_uid;
 
    Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
    /* If not always replacing, do a stat and decide */
    if (replace != REPLACE_ALWAYS) {
       struct stat mstatp;
-      if (lstat(ofile, &mstatp) == 0) {
+      if (lstat(attr->ofname, &mstatp) == 0) {
         switch (replace) {
         case REPLACE_IFNEWER:
-           if (statp->st_mtime <= mstatp.st_mtime) {
-               Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), ofile);
+           if (attr->statp.st_mtime <= mstatp.st_mtime) {
+               Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname);
               return CF_SKIP;
            }
            break;
         case REPLACE_IFOLDER:
-           if (statp->st_mtime >= mstatp.st_mtime) {
-               Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), ofile);
+           if (attr->statp.st_mtime >= mstatp.st_mtime) {
+               Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname);
               return CF_SKIP;
            }
            break;
         case REPLACE_NEVER:
-            Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), ofile);
+            Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname);
            return CF_SKIP;
         }
       }
    }
-   switch (type) {
+   switch (attr->type) {
    case FT_LNKSAVED:                 /* Hard linked, file already saved */
    case FT_LNK:
    case FT_RAW:
@@ -115,7 +113,7 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
        *   not already exist.  Below, we will split to
        *   do the file type specific work
        */
-      pnl = separate_path_and_file(jcr, fname, ofile);
+      pnl = separate_path_and_file(jcr, attr->fname, attr->ofname);
       if (pnl < 0) {
         return CF_ERROR;
       }
@@ -126,37 +124,37 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
        */
       if (pnl > 0) {
         char savechr;
-        savechr = ofile[pnl];
-        ofile[pnl] = 0;                 /* terminate path */
+        savechr = attr->ofname[pnl];
+        attr->ofname[pnl] = 0;                 /* terminate path */
 
-        if (!path_already_seen(ofile, pnl)) {
-            Dmsg1(50, "Make path %s\n", ofile);
+        if (!path_already_seen(attr->ofname, pnl)) {
+            Dmsg1(50, "Make path %s\n", attr->ofname);
            /*
             * If we need to make the directory, ensure that it is with
             * execute bit set (i.e. parent_mode), and preserve what already
             * exists. Normally, this should do nothing.
             */
-           if (make_path(jcr, ofile, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) {
-               Dmsg1(0, "Could not make path. %s\n", ofile);
+           if (make_path(jcr, attr->ofname, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) {
+               Dmsg1(0, "Could not make path. %s\n", attr->ofname);
               return CF_ERROR;
            }
         }
-        ofile[pnl] = savechr;           /* restore full name */
+        attr->ofname[pnl] = savechr;           /* restore full name */
       }
 
       /* Now we do the specific work for each file type */
-      switch(type) {
+      switch(attr->type) {
       case FT_REGE:
       case FT_REG:
-         Dmsg1(100, "Create file %s\n", ofile);
+         Dmsg1(100, "Create file %s\n", attr->ofname);
         mode =  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /*  O_NOFOLLOW; */
-        if (IS_CTG(statp->st_mode)) {
+        if (IS_CTG(attr->statp.st_mode)) {
            mode |= O_CTG;               /* set contiguous bit if needed */
         }
-         Dmsg1(50, "Create file: %s\n", ofile);
-        if ((bopen(ofd, ofile, mode, S_IRUSR | S_IWUSR)) < 0) {
+         Dmsg1(50, "Create file: %s\n", attr->ofname);
+        if ((bopen(ofd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
             Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), 
-                 ofile, berror(ofd));
+                 attr->ofname, berror(ofd));
            return CF_ERROR;
         }
         return CF_EXTRACT;
@@ -164,57 +162,57 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
       case FT_RAW:                   /* Bacula raw device e.g. /dev/sda1 */
       case FT_FIFO:                  /* Bacula fifo to save data */
       case FT_SPEC:                     
-        if (S_ISFIFO(statp->st_mode)) {
-            Dmsg1(200, "Restore fifo: %s\n", ofile);
-           if (mkfifo(ofile, statp->st_mode) != 0 && errno != EEXIST) {
+        if (S_ISFIFO(attr->statp.st_mode)) {
+            Dmsg1(200, "Restore fifo: %s\n", attr->ofname);
+           if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
                Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"), 
-                    ofile, strerror(errno));
+                    attr->ofname, strerror(errno));
               return CF_ERROR;
            }
         } else {          
-            Dmsg1(200, "Restore node: %s\n", ofile);
-           if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0 && errno != EEXIST) {
+            Dmsg1(200, "Restore node: %s\n", attr->ofname);
+           if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
                Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"), 
-                    ofile, strerror(errno));
+                    attr->ofname, strerror(errno));
               return CF_ERROR;
            }
         }       
-        if (type == FT_RAW || type == FT_FIFO) {
+        if (attr->type == FT_RAW || attr->type == FT_FIFO) {
            btimer_id tid;
-            Dmsg1(200, "FT_RAW|FT_FIFO %s\n", ofile);
+            Dmsg1(200, "FT_RAW|FT_FIFO %s\n", attr->ofname);
            mode =  O_WRONLY | O_BINARY;
            /* Timeout open() in 60 seconds */
-           if (type == FT_FIFO) {
+           if (attr->type == FT_FIFO) {
               tid = start_thread_timer(pthread_self(), 60);
            } else {
               tid = NULL;
            }
-           if ((bopen(ofd, ofile, mode, 0)) < 0) {
+           if ((bopen(ofd, attr->ofname, mode, 0)) < 0) {
                Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), 
-                    ofile, berror(ofd));
+                    attr->ofname, berror(ofd));
               stop_thread_timer(tid);
               return CF_ERROR;
            }
            stop_thread_timer(tid);
            return CF_EXTRACT;
         }
-         Dmsg1(200, "FT_SPEC %s\n", ofile);
+         Dmsg1(200, "FT_SPEC %s\n", attr->ofname);
         return CF_CREATED;
 
       case FT_LNK:
-         Dmsg2(130, "FT_LNK should restore: %s -> %s\n", ofile, lname);
-        if (symlink(lname, ofile) != 0 && errno != EEXIST) {
+         Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
+        if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
             Jmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
-                 ofile, lname, strerror(errno));
+                 attr->ofname, attr->olname, strerror(errno));
            return CF_ERROR;
         }
         return CF_CREATED;
 
       case FT_LNKSAVED:                 /* Hard linked, file already saved */
-         Dmsg2(130, "Hard link %s => %s\n", ofile, lname);
-        if (link(lname, ofile) != 0) {
+         Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
+        if (link(attr->olname, attr->ofname) != 0) {
             Jmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
-                 ofile, lname, strerror(errno));
+                 attr->ofname, attr->olname, strerror(errno));
            return CF_ERROR;
         }
         return CF_CREATED;
@@ -222,8 +220,8 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
       } /* End inner switch */
 
    case FT_DIR:
-      Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, ofile);
-      if (make_path(jcr, ofile, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
+      Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
+      if (make_path(jcr, attr->ofname, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
         return CF_ERROR;
       }
       /*
@@ -232,9 +230,9 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
        *   and saved.
        */
       if (is_win32_backup()) {
-        if ((bopen(ofd, ofile, O_WRONLY|O_BINARY, 0)) < 0) {
+        if ((bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) {
             Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), 
-                 ofile, berror(ofd));
+                 attr->ofname, berror(ofd));
            return CF_ERROR;
         }
         return CF_EXTRACT;
@@ -252,9 +250,11 @@ int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
    case FT_NORECURSE:
    case FT_NOFSCHG:
    case FT_NOOPEN:
-      Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), fname, type);
+      Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
+      break;
    default:
-      Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), type, fname);
+      Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
+      break;
    }
    return CF_ERROR;
 }
index e26a7fb09d4347f92c69424cbb6a5cd9fff1f299..348d9653988a6b3eb93ae3019aa691435cc16c42 100644 (file)
@@ -76,11 +76,12 @@ FF_PKT *init_find_files()
  * of save_time. For additional options, see above
  */
 void
-set_find_options(FF_PKT *ff, int incremental, time_t save_time)
+set_find_options(FF_PKT *ff, int incremental, time_t save_time, int mtime_only)
 {
   Dmsg0(100, "Enter set_find_options()\n");
   ff->incremental = incremental;
   ff->save_time = save_time;
+  ff->mtime_only = mtime_only;
   Dmsg0(100, "Leave set_find_options()\n");
 }
 
index e0ed71836bd7dc0e4a8e323440d79124af5d7437..22c272ccd96938aa9fbaf437723e6a665eb1342e 100755 (executable)
@@ -67,27 +67,6 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
 #define CF_EXTRACT    3               /* file created, data to extract */
 #define CF_CREATED    4               /* file created, no data to extract */
 
-/* 
- *  NOTE!!! These go on the tape, so don't change them. If 
- *  need be, add to them.
- */
-#define FT_LNKSAVED   1               /* hard link to file already saved */  
-#define FT_REGE       2               /* Regular file but empty */
-#define FT_REG        3               /* Regular file */
-#define FT_LNK        4               /* Soft Link */
-#define FT_DIR        5               /* Directory */
-#define FT_SPEC       6               /* Special file -- chr, blk, fifo, sock */
-#define FT_NOACCESS   7               /* Not able to access */
-#define FT_NOFOLLOW   8               /* Could not follow link */
-#define FT_NOSTAT     9               /* Could not stat file */
-#define FT_NOCHG     10               /* Incremental option, file not changed */
-#define FT_DIRNOCHG  11               /* Incremental option, directory not changed */
-#define FT_ISARCH    12               /* Trying to save archive file */
-#define FT_NORECURSE 13               /* No recursion into directory */
-#define FT_NOFSCHG   14               /* Different file system, prohibited */
-#define FT_NOOPEN    15               /* Could not open directory */
-#define FT_RAW       16               /* Raw block device */
-#define FT_FIFO      17               /* Raw fifo device */
 
 /* Options saved in "flag" of ff packet */
 #define FO_MD5          0x001         /* Do MD5 checksum */
index bab7afd7d01b320d138e6393892ad6d194ee747c..f1f5a188e844fcfbddafdcbd46cfd4f56fd4c79e 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       (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt);
-int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
-                   int type, int stream, struct stat *statp, 
-                   char *attribsEx, BFILE *ofd);
+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  (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt);
+int    set_attributes    (JCR *jcr, ATTR *attr, BFILE *ofd);
 
 /* from create_file.c */
-int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
-                int type, int stream, struct stat *statp, 
-                char *attribsEx, BFILE *ofd, int replace);
+int    create_file       (JCR *jcr, ATTR *attr, BFILE *ofd, int replace);
 
 /* From find.c */
 FF_PKT *init_find_files();
-void set_find_options(FF_PKT *ff, int incremental, time_t mtime);
-int find_files(JCR *jcr, FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt);
-int term_find_files(FF_PKT *ff);
+void  set_find_options(FF_PKT *ff, int incremental, time_t mtime, int mtime_only);
+int   find_files(JCR *jcr, FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt);
+int   term_find_files(FF_PKT *ff);
 
 /* From match.c */
-void init_include_exclude_files(FF_PKT *ff);
-void term_include_exclude_files(FF_PKT *ff);
-void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname);
-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);
+void  init_include_exclude_files(FF_PKT *ff);
+void  term_include_exclude_files(FF_PKT *ff);
+void  add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname);
+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);
 
 /* From find_one.c */
-int find_one_file(JCR *jcr, FF_PKT *ff, int handle_file(FF_PKT *ff_pkt, void *hpkt), 
+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);
-int term_find_one(FF_PKT *ff);
+int   term_find_one(FF_PKT *ff);
 
 
 /* From get_priv.c */
-int get_backup_privileges(JCR *jcr, int ignore_errors);
+int enable_backup_privileges(JCR *jcr, int ignore_errors);
 
 
 /* from makepath.c */
index f54d15b15d5c09ba1637ddcc4fe95bd7f8a51917..be78fcdae4de29db59bb6df074f43b132f67f5da 100644 (file)
@@ -117,6 +117,8 @@ struct JCR {
    char *sd_auth_key;                 /* SD auth key */
    MSGS *jcr_msgs;                    /* Copy of message resource -- actually used */
    uint32_t ClientId;                 /* Client associated with Job */
+   char *where;                       /* prefix to restore files to */
+   int prefix_links;                  /* Prefix links with Where path */
 
    /* Daemon specific part of JCR */
    /* This should be empty in the library */
@@ -148,7 +150,6 @@ struct JCR {
    POOLMEM *stime;                    /* start time for incremental/differential */
    JOB_DBR jr;                        /* Job record in Database */
    uint32_t RestoreJobId;             /* Id specified by UA */
-   char *RestoreWhere;                /* Where to restore the files */
    POOLMEM *client_uname;             /* client uname */ 
    int replace;                       /* Replace option */
    int acquired_resource_locks;       /* set if resource locks acquired */
@@ -170,9 +171,7 @@ struct JCR {
    char *big_buf;                     /* I/O buffer */
    POOLMEM *compress_buf;             /* Compression buffer */
    int32_t compress_buf_size;         /* Length of compression buffer */
-   POOLMEM *where;                    /* Root where to restore */
    int replace;                       /* Replace options */
-   int prefix_links;                  /* Prefix links with Where path */
    int buf_size;                      /* length of buffer */
    void *ff;                          /* Find Files packet */
    char stored_addr[MAX_NAME_LENGTH]; /* storage daemon address */
index 03fccf1956b18087d8d065dc5124d7ee500bd0ae..8229502d377faf3b93c48704720a189a843a6197 100644 (file)
@@ -31,7 +31,7 @@ GMP_INC=@GMP_INC@
 first_rule: all
 dummy:
 
-LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \
+LIBSRCS = alloc.c attr.c base64.c bsys.c bget_msg.c \
          bnet.c bnet_server.c \
          bpipe.c bshm.c btime.c \
          cram-md5.c crc32.c daemon.c edit.c fnmatch.c \
@@ -42,7 +42,7 @@ LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \
          util.c watchdog.c workq.c  
 
 
-LIBOBJS = alloc.o base64.o bsys.o bget_msg.o \
+LIBOBJS = alloc.o attr.o base64.o bsys.o bget_msg.o \
          bnet.o bnet_server.o \
          bpipe.o bshm.o btime.o \
          cram-md5.o crc32.o daemon.o edit.o fnmatch.o \
diff --git a/bacula/src/lib/attr.c b/bacula/src/lib/attr.c
new file mode 100644 (file)
index 0000000..bd30d9e
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ *   attr.c  Unpack an Attribute record returned from the tape
+ * 
+ *    Kern Sibbald, June MMIII (code pulled from filed/restore.c and updated)
+ *
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "jcr.h"
+
+extern int win32_client;
+
+ATTR *new_attr()
+{
+   ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
+   memset(attr, 0, sizeof(ATTR));
+   attr->ofname = get_pool_memory(PM_FNAME);
+   attr->olname = get_pool_memory(PM_FNAME);
+   return attr;
+}
+
+void free_attr(ATTR *attr)
+{
+   free_pool_memory(attr->olname);
+   free_pool_memory(attr->ofname);
+   free(attr);
+}
+
+int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
+{
+   char *p;
+   /*             
+    * An Attributes record consists of:
+    *   File_index
+    *   Type   (FT_types)
+    *   Filename
+    *   Attributes
+    *   Link name (if file linked i.e. FT_LNK)
+    *   Extended attributes (Win32)
+    *  plus optional values determined by AR_ flags in upper bits of Type
+    *   Data_stream
+    *
+    */
+   attr->stream = stream;
+   Dmsg1(100, "Attr: %s\n", rec);
+   if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
+      Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
+      Dmsg1(100, "\nError scanning attributes. %s\n", rec);
+      return 0;
+   }
+   Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
+   if (attr->type & AR_DATA_STREAM) {
+      attr->data_stream = 1;
+   } else {
+      attr->data_stream = 0;
+   }
+   attr->type &= FT_MASK;            /* keep only type bits */
+   p = rec;
+   while (*p++ != ' ')               /* skip record file index */
+      { }
+   while (*p++ != ' ')               /* skip type */
+      { }
+   
+   attr->fname = p;                  /* set filname position */
+   while (*p++ != 0)                 /* skip filename */
+      { }
+   attr->attr = p;                   /* set attributes position */
+   while (*p++ != 0)                 /* skip attributes */
+      { }
+   attr->lname = p;                  /* set link position */
+   while (*p++ != 0)                 /* skip link */
+      { }
+   attr->attrEx = p;                 /* set extended attributes position */
+
+   if (attr->data_stream) {
+      int64_t val;
+      while (*p++ != 0)              /* skip extended attributes */
+        { }
+      from_base64(&val, p);
+      attr->data_stream = (int32_t)val;
+   }
+   Dmsg7(200, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
+      attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
+      attr->attrEx, attr->data_stream);
+   *attr->ofname = 0;
+   *attr->olname = 0;
+   return 1;
+}
+
+/*
+ * Build attr->ofname from attr->fname and
+ *      attr->olname from attr->olname 
+ */
+void build_attr_output_fnames(JCR *jcr, ATTR *attr)
+{
+   /*
+    * Prepend the where directory so that the
+    * files are put where the user wants.
+    *
+    * We do a little jig here to handle Win32 files with
+    *  a drive letter -- we simply strip the drive: from
+    *  every filename if a prefix is supplied.
+    *    
+    */
+   if (jcr->where[0] == 0) {
+      pm_strcpy(&attr->ofname, attr->fname);
+      pm_strcpy(&attr->olname, attr->lname);
+   } else {
+      char *fn;
+      int wherelen = strlen(jcr->where);
+      pm_strcpy(&attr->ofname, jcr->where);  /* copy prefix */
+      if (win32_client && attr->fname[1] == ':') {
+        fn = attr->fname+2;          /* skip over drive: */
+      } else {
+        fn = attr->fname;            /* take whole name */
+      }
+      /* Ensure where is terminated with a slash */
+      if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
+         pm_strcat(&attr->ofname, "/");
+      }   
+      pm_strcat(&attr->ofname, fn); /* copy rest of name */
+      /*
+       * Fixup link name -- if it is an absolute path
+       */
+      if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
+        bool add_link;
+        /* Always add prefix to hard links (FT_LNKSAVED) and
+         *  on user request to soft links
+         */
+         if (attr->lname[0] == '/' &&
+            (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
+           pm_strcpy(&attr->olname, jcr->where);
+           add_link = true;
+        } else {
+           attr->olname[0] = 0;
+           add_link = false;
+        }
+         if (win32_client && attr->lname[1] == ':') {
+           fn = attr->lname+2;     /* skip over drive: */
+        } else {
+           fn = attr->lname;       /* take whole name */
+        }
+        /* Ensure where is terminated with a slash */
+         if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
+            pm_strcat(&attr->olname, "/");
+        }   
+        pm_strcat(&attr->olname, fn);     /* copy rest of link */
+      }
+   }
+}
+
+extern char *getuser(uid_t uid);
+extern char *getgroup(gid_t gid);
+
+/*
+ * Print an ls style message, also send M_RESTORED
+ */
+void print_ls_output(JCR *jcr, ATTR *attr)
+{
+   char buf[5000]; 
+   char ec1[30];
+   char *p, *f;
+   int n;
+
+   p = encode_mode(attr->statp.st_mode, buf);
+   n = sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
+   p += n;
+   n = sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid), getgroup(attr->statp.st_gid));
+   p += n;
+   n = sprintf(p, "%8.8s ", edit_uint64(attr->statp.st_size, ec1));
+   p += n;
+   p = encode_time(attr->statp.st_ctime, p);
+   *p++ = ' ';
+   *p++ = ' ';
+   for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
+      *p++ = *f++;
+   }
+   if (attr->type == FT_LNK) {
+      *p++ = ' ';
+      *p++ = '-';
+      *p++ = '>';
+      *p++ = ' ';
+      /* Copy link name */
+      for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
+        *p++ = *f++;
+      }
+   }
+   *p++ = '\n';
+   *p = 0;
+   Dmsg1(20, "%s", buf);
+   Jmsg(jcr, M_RESTORED, 0, "%s", buf);
+}
diff --git a/bacula/src/lib/attr.h b/bacula/src/lib/attr.h
new file mode 100644 (file)
index 0000000..7b19edd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *   attr.h Definition of attributes packet for unpacking from tape
+ * 
+ *    Kern Sibbald, June MMIII
+ *
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+struct ATTR {
+   int32_t stream;                    /* attribute stream id */
+   int32_t data_stream;               /* id of data stream to follow */
+   int32_t type;                      /* file type FT */
+   int32_t file_index;                /* file index */
+   struct stat statp;                 /* decoded stat packet */
+   char *attr;                        /* attributes position */
+   char *attrEx;                      /* extended attributes if any */
+   char *fname;                       /* filename */
+   char *lname;                       /* link name if any */
+   POOLMEM *ofname;                   /* output filename */
+   POOLMEM *olname;                   /* output link name */
+};
index fdc37d8c0d1cf549969c2fc63b7eb778fa2f1ae8..b274f93781e5452c61781ce1e4fe5c3d4bb9e930 100644 (file)
@@ -58,7 +58,10 @@ static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
       do {
         errno = 0;
         nread = read(bsock->fd, ptr, nleft);    
-      } while (!bsock->timed_out && nread == -1 && (errno == EINTR || errno == EAGAIN));
+        if (bsock->timed_out || bsock->terminated) {
+           return nread;
+        }
+      } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
       if (nread <= 0) {
         return nread;               /* error, or EOF */
       }
@@ -91,7 +94,19 @@ static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
       do {
         errno = 0;
         nwritten = write(bsock->fd, ptr, nleft);
-      } while (!bsock->timed_out && nwritten == -1 && (errno == EINTR || errno == EAGAIN));
+        if (bsock->timed_out || bsock->terminated) {
+           return nwritten;
+        }
+      } while (nwritten == -1 && errno == EINTR);
+      /*
+       * If connection is non-blocking, we will get eagain, so
+       * sleep long enough to keep from consuming all the CPU
+       * and try again.
+       */
+      if (nwritten == -1 && errno == EAGAIN) {
+        bmicrosleep(0, 50);       /* sleep 50 ms */
+        continue;
+      }
       if (nwritten <= 0) {
         return nwritten;            /* error */
       }
index fa716293ba0f7fb7da39a23597818f6a543fe7c3..25435d1277b0ddfb9f1524667c9b7ac1cec7df37 100755 (executable)
@@ -156,6 +156,10 @@ static void free_common_jcr(JCR *jcr)
       free_pool_memory(jcr->errmsg);
       jcr->errmsg = NULL;
    }
+   if (jcr->where) {
+      free(jcr->where);
+      jcr->where = NULL;
+   }
    free(jcr);
 }
 
index 9eeb48fed3a2da12e374b4d7acef714644b49b1b..bc2b74fdc76da8e8ffe3868425fed8437a98d64e 100644 (file)
@@ -50,5 +50,6 @@
 #include "tree.h"
 #include "watchdog.h"
 #include "bpipe.h"
+#include "attr.h"
 
 #include "protos.h"
index da1c76c3b7ac73ae5138d4744eee971bef904675..b68c96b823df2ee2cd30236d581ee417927b2e8f 100755 (executable)
@@ -58,7 +58,7 @@ char catalog_db[] = "MySQL";
 char catalog_db[] = "SQLite";
 #endif
 #ifdef HAVE_BACULA_DB
-char catlog_db[] = "Internal";
+char catalog_db[] = "Internal";
 #endif
 
 
index 17315c20629deb62f57052e48e81898d5df6e2c0..06b248e1c550eef565cf667a04ac11b05ca8d775 100644 (file)
@@ -114,3 +114,4 @@ extern int verbose;
 extern char my_name[];
 extern char *working_directory;
 extern time_t daemon_start_time;
+extern char catalog_db[];
index d7cffe259cf1e8ed17425e2fd2f40e56d516d1f5..33e4998131ef017c1fa236f28f6dbae07429fd8f 100644 (file)
 
 struct JCR;
 
+/* attr.c */
+ATTR    *new_attr();
+void     free_attr(ATTR *attr);
+int      unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
+void     build_attr_output_fnames(JCR *jcr, ATTR *attr);
+void     print_ls_output(JCR *jcr, ATTR *attr);
+
 /* base64.c */
-void      base64_init            (void);
-int       to_base64              (intmax_t value, char *where);
-int       from_base64            (intmax_t *value, char *where);
-int       bin_to_base64          (char *buf, char *bin, int len);
+void     base64_init            (void);
+int      to_base64              (intmax_t value, char *where);
+int      from_base64            (intmax_t *value, char *where);
+int      bin_to_base64          (char *buf, char *bin, int len);
 
 /* bsys.c */
-char     *bstrncpy               (char *dest, const char *src, int maxlen);
-char     *bstrncat               (char *dest, const char *src, int maxlen);
-void     *b_malloc               (char *file, int line, size_t size);
+char    *bstrncpy               (char *dest, const char *src, int maxlen);
+char    *bstrncat               (char *dest, const char *src, int maxlen);
+void    *b_malloc               (char *file, int line, size_t size);
 #ifndef DEBUG
-void     *bmalloc                (size_t size);
+void    *bmalloc                (size_t size);
 #endif
-void     *brealloc               (void *buf, size_t size);
-void     *bcalloc                (size_t size1, size_t size2);
-int       bsnprintf              (char *str, size_t size, const  char  *format, ...);
-int       bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
-int       pool_sprintf           (char *pool_buf, char *fmt, ...);
-void      create_pid_file        (char *dir, char *progname, int port);
-int       delete_pid_file        (char *dir, char *progname, int port);
-void      drop                   (char *uid, char *gid);
-int       bmicrosleep            (time_t sec, long msec);
+void    *brealloc               (void *buf, size_t size);
+void    *bcalloc                (size_t size1, size_t size2);
+int      bsnprintf              (char *str, size_t size, const  char  *format, ...);
+int      bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
+int      pool_sprintf           (char *pool_buf, char *fmt, ...);
+void     create_pid_file        (char *dir, char *progname, int port);
+int      delete_pid_file        (char *dir, char *progname, int port);
+void     drop                   (char *uid, char *gid);
+int      bmicrosleep            (time_t sec, long msec);
 #ifndef HAVE_STRTOLL
 long long int strtoll(const char *ptr, char **endptr, int base);
 #endif
 
 /* bnet.c */
-int32_t    bnet_recv             (BSOCK *bsock);
-int        bnet_send             (BSOCK *bsock);
-int        bnet_fsend            (BSOCK *bs, char *fmt, ...);
-int        bnet_set_buffer_size  (BSOCK *bs, uint32_t size, int rw);
-int        bnet_sig              (BSOCK *bs, int sig);
-int        bnet_ssl_server       (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
-int        bnet_ssl_client       (BSOCK *bsock, char *password, int ssl_need);
-BSOCK *    bnet_connect            (JCR *jcr, int retry_interval,
-               int max_retry_time, char *name, char *host, char *service, 
-               int port, int verbose);
-void       bnet_close            (BSOCK *bsock);
-BSOCK *    init_bsock            (JCR *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK *    dup_bsock             (BSOCK *bsock);
-void       term_bsock            (BSOCK *bsock);
-char *     bnet_strerror         (BSOCK *bsock);
-char *     bnet_sig_to_ascii     (BSOCK *bsock);
-int        bnet_wait_data        (BSOCK *bsock, int sec);
-int        bnet_wait_data_intr   (BSOCK *bsock, int sec);
-int        bnet_despool          (BSOCK *bsock);
-int        is_bnet_stop          (BSOCK *bsock);
-int        is_bnet_error         (BSOCK *bsock);
-void       bnet_suppress_error_messages(BSOCK *bsock, int flag);
+int32_t    bnet_recv            (BSOCK *bsock);
+int       bnet_send             (BSOCK *bsock);
+int       bnet_fsend            (BSOCK *bs, char *fmt, ...);
+int       bnet_set_buffer_size  (BSOCK *bs, uint32_t size, int rw);
+int       bnet_sig              (BSOCK *bs, int sig);
+int       bnet_ssl_server       (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
+int       bnet_ssl_client       (BSOCK *bsock, char *password, int ssl_need);
+BSOCK *    bnet_connect           (JCR *jcr, int retry_interval,
+              int max_retry_time, char *name, char *host, char *service, 
+              int port, int verbose);
+void      bnet_close            (BSOCK *bsock);
+BSOCK *    init_bsock           (JCR *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK *    dup_bsock            (BSOCK *bsock);
+void      term_bsock            (BSOCK *bsock);
+char *    bnet_strerror         (BSOCK *bsock);
+char *    bnet_sig_to_ascii     (BSOCK *bsock);
+int       bnet_wait_data        (BSOCK *bsock, int sec);
+int       bnet_wait_data_intr   (BSOCK *bsock, int sec);
+int       bnet_despool          (BSOCK *bsock);
+int       is_bnet_stop          (BSOCK *bsock);
+int       is_bnet_error         (BSOCK *bsock);
+void      bnet_suppress_error_messages(BSOCK *bsock, int flag);
 
 /* bget_msg.c */
-int      bget_msg(BSOCK *sock);
+int     bget_msg(BSOCK *sock);
 
 /* bpipe.c */
-BPIPE *          open_bpipe(char *prog, int wait, char *mode);
-int              close_wpipe(BPIPE *bpipe);
-int              close_bpipe(BPIPE *bpipe);
+BPIPE *         open_bpipe(char *prog, int wait, char *mode);
+int             close_wpipe(BPIPE *bpipe);
+int             close_bpipe(BPIPE *bpipe);
 
 /* cram-md5.c */
 int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
 int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
 void hmac_md5(uint8_t* text, int text_len, uint8_t*  key,
-              int key_len, uint8_t *hmac);
+             int key_len, uint8_t *hmac);
 
 /* crc32.c */
 
 uint32_t bcrc32(uint8_t *buf, int len);
 
 /* daemon.c */
-void     daemon_start            ();
+void    daemon_start            ();
 
 /* edit.c */
-uint64_t         str_to_uint64(char *str);
-int64_t          str_to_int64(char *str);
-char *           edit_uint64_with_commas   (uint64_t val, char *buf);
-char *           add_commas              (char *val, char *buf);
-char *           edit_uint64             (uint64_t val, char *buf);
-int              duration_to_utime       (char *str, utime_t *value);
-int              size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char             *edit_utime             (utime_t val, char *buf);
-int              is_a_number             (const char *num);
-int              is_an_integer           (const char *n);
+uint64_t        str_to_uint64(char *str);
+int64_t         str_to_int64(char *str);
+char *          edit_uint64_with_commas   (uint64_t val, char *buf);
+char *          add_commas              (char *val, char *buf);
+char *          edit_uint64             (uint64_t val, char *buf);
+int             duration_to_utime       (char *str, utime_t *value);
+int             size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char            *edit_utime             (utime_t val, char *buf);
+int             is_a_number             (const char *num);
+int             is_an_integer           (const char *n);
 
 /* lex.c */
-LEX *     lex_close_file         (LEX *lf);
-LEX *     lex_open_file          (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int       lex_get_char           (LEX *lf);
-void      lex_unget_char         (LEX *lf);
-char *    lex_tok_to_str         (int token);
-int       lex_get_token          (LEX *lf, int expect);
+LEX *    lex_close_file         (LEX *lf);
+LEX *    lex_open_file          (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int      lex_get_char           (LEX *lf);
+void     lex_unget_char         (LEX *lf);
+char *   lex_tok_to_str         (int token);
+int      lex_get_token          (LEX *lf, int expect);
 
 /* message.c */
-void       my_name_is            (int argc, char *argv[], char *name);
-void       init_msg              (JCR *jcr, MSGS *msg);
-void       term_msg              (void);
-void       close_msg             (JCR *jcr);
-void       add_msg_dest          (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void       rem_msg_dest          (MSGS *msg, int dest, int type, char *where);
-void       Jmsg                  (JCR *jcr, int type, int level, char *fmt, ...);
-void       dispatch_message      (JCR *jcr, int type, int level, char *buf);
-void       init_console_msg      (char *wd);
-void       free_msgs_res         (MSGS *msgs);
-int        open_spool_file       (JCR *jcr, BSOCK *bs);
-int        close_spool_file      (JCR *jcr, BSOCK *bs);
+void      my_name_is            (int argc, char *argv[], char *name);
+void      init_msg              (JCR *jcr, MSGS *msg);
+void      term_msg              (void);
+void      close_msg             (JCR *jcr);
+void      add_msg_dest          (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void      rem_msg_dest          (MSGS *msg, int dest, int type, char *where);
+void      Jmsg                  (JCR *jcr, int type, int level, char *fmt, ...);
+void      dispatch_message      (JCR *jcr, int type, int level, char *buf);
+void      init_console_msg      (char *wd);
+void      free_msgs_res         (MSGS *msgs);
+int       open_spool_file       (JCR *jcr, BSOCK *bs);
+int       close_spool_file      (JCR *jcr, BSOCK *bs);
 
 
 /* bnet_server.c */
-void       bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, 
-                   void *handle_client_request(void *bsock));
-void             bnet_server             (int port, void handle_client_request(BSOCK *bsock));
-int              net_connect             (int port);
-BSOCK *          bnet_bind               (int port);
-BSOCK *          bnet_accept             (BSOCK *bsock, char *who);
+void      bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, 
+                  void *handle_client_request(void *bsock));
+void            bnet_server             (int port, void handle_client_request(BSOCK *bsock));
+int             net_connect             (int port);
+BSOCK *         bnet_bind               (int port);
+BSOCK *         bnet_accept             (BSOCK *bsock, char *who);
 
 /* signal.c */
-void             init_signals             (void terminate(int sig));
-void             init_stack_dump          (void);
+void            init_signals             (void terminate(int sig));
+void            init_stack_dump          (void);
 
 /* scan.c */
-void             strip_trailing_junk     (char *str);
-void             strip_trailing_slashes  (char *dir);
-int              skip_spaces             (char **msg);
-int              skip_nonspaces          (char **msg);
-int              fstrsch                 (char *a, char *b);
-int              parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
-                        char **argk, char **argv, int max_args);
-char            *next_arg(char **s);
+void            strip_trailing_junk     (char *str);
+void            strip_trailing_slashes  (char *dir);
+int             skip_spaces             (char **msg);
+int             skip_nonspaces          (char **msg);
+int             fstrsch                 (char *a, char *b);
+int             parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
+                       char **argk, char **argv, int max_args);
+char           *next_arg(char **s);
 
 /* util.c */
-int              is_buf_zero             (char *buf, int len);
-void             lcase                   (char *str);
-void             bash_spaces             (char *str);
-void             unbash_spaces           (char *str);
-char *           encode_time             (time_t time, char *buf);
-char *           encode_mode             (mode_t mode, char *buf);
-int              do_shell_expansion      (char *name, int name_len);
-void             jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
-void             pm_strcat               (POOLMEM **pm, char *str);
-void             pm_strcpy               (POOLMEM **pm, char *str);
-int              run_program             (char *prog, int wait, POOLMEM *results);
-char *           job_type_to_str         (int type);
-char *           job_status_to_str       (int stat);
-char *           job_level_to_str        (int level);
-void             make_session_key        (char *key, char *seed, int mode);
-POOLMEM         *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);  
-void             set_working_directory(char *wd);
+int             is_buf_zero             (char *buf, int len);
+void            lcase                   (char *str);
+void            bash_spaces             (char *str);
+void            unbash_spaces           (char *str);
+char *          encode_time             (time_t time, char *buf);
+char *          encode_mode             (mode_t mode, char *buf);
+int             do_shell_expansion      (char *name, int name_len);
+void            jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
+void            pm_strcat               (POOLMEM **pm, char *str);
+void            pm_strcpy               (POOLMEM **pm, char *str);
+int             run_program             (char *prog, int wait, POOLMEM *results);
+char *          job_type_to_str         (int type);
+char *          job_status_to_str       (int stat);
+char *          job_level_to_str        (int level);
+void            make_session_key        (char *key, char *seed, int mode);
+POOLMEM        *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);  
+void            set_working_directory(char *wd);
 
 
 /* watchdog.c */
index 8331f3899b1d066636c3caa2aa552c181b408b14..fda802a52d4d4271f6be2519a21c75aef40fcfe3 100644 (file)
@@ -350,12 +350,6 @@ int do_shell_expansion(char *name, int name_len)
           if ((shellcmd = getenv("SHELL")) == NULL) {
              shellcmd = "/bin/sh";
          }
-#ifdef xxx
-         close(1); dup(pfd[1]);          /* attach pipes to stdout and stderr */
-         close(2); dup(pfd[1]);
-         for (i = 3; i < 32; i++)        /* close everything else */
-            close(i);
-#endif
          close(pfd[0]);                  /* close stdin */
          dup2(pfd[1], 1);                /* attach to stdout */
          dup2(pfd[1], 2);                /* and stderr */
index 7446154068eef8376cc14a94c32e817861b844de..a3104e4eea6a16636c48efe197384edd67ccf186 100644 (file)
@@ -16,3 +16,5 @@ job2.bsr
 restore.bsr
 startit
 stopit
+changer.out
+mtx-changer
index 73a8c1ef7e61ff0a03ee1ef382bfa3ade0128f09..020817636b88066ab552d9b9da44ce37815f6d24 100644 (file)
@@ -115,8 +115,8 @@ int do_append_data(JCR *jcr)
 
       /* Read Stream header from the File daemon.
        *  The stream header consists of the following:
-       *    file_index (sequential Bacula file index)
-       *    stream     (arbitrary Bacula number to distinguish parts of data)
+       *    file_index (sequential Bacula file index, base 1)
+       *    stream     (Bacula number to distinguish parts of data)
        *    info       (Info for Storage daemon -- compressed, encryped, ...)
        *       info is not currently used, so is read, but ignored!
        */
@@ -189,8 +189,8 @@ int do_append_data(JCR *jcr)
            stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
 
         /* Send attributes and MD5 to Director for Catalog */
-        if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE ||
-            stream == STREAM_WIN32_ATTRIBUTES || stream == STREAM_SHA1_SIGNATURE) { 
+        if (stream == STREAM_UNIX_ATTRIBUTES    || stream == STREAM_MD5_SIGNATURE ||
+            stream == STREAM_UNIX_ATTRIBUTES_EX || stream == STREAM_SHA1_SIGNATURE) { 
            if (!jcr->no_attributes) {
               if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) {
                  jcr->dir_bsock->spool = 1;
index 5e507ebe0921360e4edff133076966aed11f44cb..ba9f4443bc5395a89fe5ceeb04128f1580f230d6 100644 (file)
@@ -48,20 +48,14 @@ static FF_PKT my_ff;
 static FF_PKT *ff = &my_ff;
 static BSR *bsr = NULL;
 static int extract = FALSE;
-static long record_file_index;
+static int non_support_data = 0;
+static int non_support_attr = 0;
 static long total = 0;
-static POOLMEM *fname;                   /* original file name */
-static POOLMEM *ofile;                   /* output name with prefix */
-static POOLMEM *lname;                   /* link name */
-static POOLMEM *attribsEx;               /* extended attributes (Win32) */
+static ATTR *attr;
 static char *where;
-static int wherelen;                     /* prefix length */
 static uint32_t num_files = 0;
-static struct stat statp;
 static uint32_t compress_buf_size = 70000;
 static POOLMEM *compress_buf;
-static int type;
-static int stream;
 static int prog_name_msg = 0;
 static int win32_data_msg = 0;
 static char *VolumeName = NULL;
@@ -107,63 +101,63 @@ int main (int argc, char *argv[])
 
    while ((ch = getopt(argc, argv, "b:c:d:e:i:?")) != -1) {
       switch (ch) {
-         case 'b':                    /* bootstrap file */
-           bsr = parse_bsr(NULL, optarg);
-//         dump_bsr(bsr);
-           break;
-
-         case 'c':                    /* specify config file */
-           if (configfile != NULL) {
-              free(configfile);
-           }
-           configfile = bstrdup(optarg);
-           break;
-
-         case 'd':                    /* debug level */
-           debug_level = atoi(optarg);
-           if (debug_level <= 0)
-              debug_level = 1; 
-           break;
-
-         case 'e':                    /* exclude list */
-            if ((fd = fopen(optarg, "r")) == NULL) {
-               Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n",
-                 optarg, strerror(errno));
-              exit(1);
-           }
-           while (fgets(line, sizeof(line), fd) != NULL) {
-              strip_trailing_junk(line);
-               Dmsg1(900, "add_exclude %s\n", line);
-              add_fname_to_exclude_list(ff, line);
-           }
-           fclose(fd);
-           break;
-
-         case 'i':                    /* include list */
-            if ((fd = fopen(optarg, "r")) == NULL) {
-               Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
-                 optarg, strerror(errno));
-              exit(1);
-           }
-           while (fgets(line, sizeof(line), fd) != NULL) {
-              strip_trailing_junk(line);
-               Dmsg1(900, "add_include %s\n", line);
-              add_fname_to_include_list(ff, 0, line);
-           }
-           fclose(fd);
-           got_inc = TRUE;
-           break;
+      case 'b':                    /* bootstrap file */
+        bsr = parse_bsr(NULL, optarg);
+//      dump_bsr(bsr);
+        break;
+
+      case 'c':                    /* specify config file */
+        if (configfile != NULL) {
+           free(configfile);
+        }
+        configfile = bstrdup(optarg);
+        break;
+
+      case 'd':                    /* debug level */
+        debug_level = atoi(optarg);
+        if (debug_level <= 0)
+           debug_level = 1; 
+        break;
+
+      case 'e':                    /* exclude list */
+         if ((fd = fopen(optarg, "r")) == NULL) {
+            Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n",
+              optarg, strerror(errno));
+           exit(1);
+        }
+        while (fgets(line, sizeof(line), fd) != NULL) {
+           strip_trailing_junk(line);
+            Dmsg1(900, "add_exclude %s\n", line);
+           add_fname_to_exclude_list(ff, line);
+        }
+        fclose(fd);
+        break;
+
+      case 'i':                    /* include list */
+         if ((fd = fopen(optarg, "r")) == NULL) {
+            Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
+              optarg, strerror(errno));
+           exit(1);
+        }
+        while (fgets(line, sizeof(line), fd) != NULL) {
+           strip_trailing_junk(line);
+            Dmsg1(900, "add_include %s\n", line);
+           add_fname_to_include_list(ff, 0, line);
+        }
+        fclose(fd);
+        got_inc = TRUE;
+        break;
 
-         case 'V':                    /* Volume name */
-           VolumeName = optarg;
-           break;
+      case 'V':                    /* Volume name */
+        VolumeName = optarg;
+        break;
 
-         case '?':
-        default:
-           usage();
+      case '?':
+      default:
+        usage();
 
-      }  
-   }
+      } /* end switch */
+   } /* end while */
    argc -= optind;
    argv += optind;
 
@@ -201,7 +195,7 @@ int main (int argc, char *argv[])
 
 static void do_extract(char *devname)
 {
-
+   struct stat statp;
    jcr = setup_jcr("bextract", devname, bsr, VolumeName);
    dev = setup_to_access_device(jcr, 1);    /* acquire for read */
    if (!dev) {
@@ -217,11 +211,9 @@ static void do_extract(char *devname)
       Emsg1(M_ERROR_TERM, 0, "%s must be a directory.\n", where);
    }
 
-   wherelen = strlen(where);
-   fname = get_pool_memory(PM_FNAME);
-   ofile = get_pool_memory(PM_FNAME);
-   lname = get_pool_memory(PM_FNAME);
-   attribsEx = get_pool_memory(PM_FNAME);
+   free(jcr->where);
+   jcr->where = bstrdup(where);
+   attr = new_attr();
 
    compress_buf = get_memory(compress_buf_size);
 
@@ -230,15 +222,11 @@ static void do_extract(char *devname)
     * archive since we just hit an end of file, so close the file. 
     */
    if (is_bopen(&bfd)) {
-      set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
-                    attribsEx, &bfd);
+      set_attributes(jcr, attr, &bfd);
    }
    release_device(jcr, dev);
 
-   free_pool_memory(fname);
-   free_pool_memory(ofile);
-   free_pool_memory(lname);
-   free_pool_memory(compress_buf);
+   free_attr(attr);
    term_dev(dev);
    free_jcr(jcr);
    printf("%u files restored.\n", num_files);
@@ -257,155 +245,77 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
    }
 
    /* File Attributes stream */
-   if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) {
-      char *ap, *lp, *fp, *apex;
 
-      stream = rec->Stream;
+   switch (rec->Stream) {
+   case STREAM_UNIX_ATTRIBUTES:
+   case STREAM_UNIX_ATTRIBUTES_EX:  
 
       /* If extracting, it was from previous stream, so
        * close the output file.
        */
       if (extract) {
         if (!is_bopen(&bfd)) {
-            Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
+            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, &bfd);
+        set_attributes(jcr, attr, &bfd);
       }
 
-      if (sizeof_pool_memory(fname) < rec->data_len) {
-        fname = realloc_pool_memory(fname, rec->data_len + 1);
-      }
-      if (sizeof_pool_memory(ofile) < rec->data_len + wherelen + 1) {
-        ofile = realloc_pool_memory(ofile, rec->data_len + wherelen + 1);
+      if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) {
+         Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
       }
-      if (sizeof_pool_memory(lname) < rec->data_len) {
-        lname = realloc_pool_memory(lname, rec->data_len + wherelen + 1);
-      }
-      *fname = 0;
-      *lname = 0;
-
-      /*             
-       * An Attributes record consists of:
-       *    File_index
-       *    Type   (FT_types)
-       *    Filename
-       *    Attributes
-       *    Link name (if file linked i.e. FT_LNK)
-       *    Extended Attributes (Win32) 
-       *
-       */
-      sscanf(rec->data, "%ld %d", &record_file_index, &type);
-      if (record_file_index != rec->FileIndex)
-         Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
-           rec->FileIndex, record_file_index);
-      ap = rec->data;
-      while (*ap++ != ' ')         /* skip record file index */
-        ;
-      while (*ap++ != ' ')         /* skip type */
-        ;
-      /* Save filename and position to attributes */
-      fp = fname;
-      while (*ap != 0) {
-        *fp++  = *ap++;
-      }
-      *fp = *ap++;                /* terminate filename & point to attribs */
 
-      /* Skip to Link name */
-      if (type == FT_LNK || type == FT_LNKSAVED) {
-        lp = ap;
-        while (*lp++ != 0) {
-           ;
-        }
-      } else {
-         lp = "";
+      if (attr->file_index != rec->FileIndex) {
+         Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
+           rec->FileIndex, attr->file_index);
       }
-
-      if (rec->Stream == STREAM_WIN32_ATTRIBUTES) {
-        apex = ap;                   /* start at attributes */
-        while (*apex++ != 0) {       /* skip attributes */
-           ;
-        }
-        while (*apex++ != 0) {      /* skip link name */
-           ;
-        }
-        pm_strcpy(&attribsEx, apex);  /* make a copy of Extended attributes */
-      } else {
-        *attribsEx = 0;              /* no extended attributes */
-      }
-
         
-      if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
+      if (file_is_included(ff, attr->fname) && !file_is_excluded(ff, attr->fname)) {
         uint32_t LinkFI;
 
-        decode_stat(ap, &statp, &LinkFI);
-        /*
-         * Prepend the where directory so that the
-         * files are put where the user wants.
-         *
-         * We do a little jig here to handle Win32 files with
-         *   a drive letter -- we simply strip the drive: from
-         *   every filename if a prefix is supplied.
-         */
-        if (where[0] == 0) {
-           strcpy(ofile, fname);
-           strcpy(lname, lp);
-        } else {
-           char *fn;
-           strcpy(ofile, where);
-            if (win32_client && fname[1] == ':') {
-              fn = fname+2;          /* skip over drive: */
-           } else {
-              fn = fname;            /* take whole name */
-           }
-           /* Ensure where is terminated with a slash */
-            if (where[wherelen-1] != '/' && fn[0] != '/') {
-               strcat(ofile, "/");
-           }
-           strcat(ofile, fn);        /* copy rest of name */
-           /* Fixup link name for hard links, but not for
-            * soft links 
-            */
-           if (type == FT_LNKSAVED) {
-               if (lp[0] == '/') {      /* if absolute path */
-                 strcpy(lname, where);
-              }       
-               if (win32_client && lp[1] == ':') {
-                 strcat(lname, lp+2); /* copy rest of name */
-              } else {
-                 strcat(lname, lp);   /* On Unix systems we take everything */
-              }
-           }
-        }
+        decode_stat(attr->attr, &attr->statp, &LinkFI);
 
-         /*          Pmsg1(000, "Restoring: %s\n", ofile); */
+        build_attr_output_fnames(jcr, attr);
 
         extract = FALSE;
-        stat = create_file(jcr, fname, ofile, lname, type, stream,
-                           &statp, attribsEx, &bfd, REPLACE_ALWAYS);   
+        stat = create_file(jcr, attr, &bfd, REPLACE_ALWAYS);   
         switch (stat) {
         case CF_ERROR:
         case CF_SKIP:
            break;
         case CF_EXTRACT:
            extract = TRUE;
-           print_ls_output(ofile, lname, type, &statp);   
+           print_ls_output(jcr, attr);
            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);   
+           set_attributes(jcr, attr, &bfd);
+           print_ls_output(jcr, attr);
            num_files++;
            fileAddr = 0;
            break;
         }  
       }
 
+   /* Windows Backup data stream */
+   case STREAM_WIN32_DATA:  
+      if (!is_win32_backup()) {
+        if (!non_support_data) {
+            Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n"));
+        }
+        extract = FALSE;
+        non_support_data++;
+        return;
+      }
+      goto extract_data;
+   
+
    /* Data stream and extracting */
-   } else if (rec->Stream == STREAM_FILE_DATA || rec->Stream == STREAM_SPARSE_DATA) {
+   case STREAM_FILE_DATA:
+   case STREAM_SPARSE_DATA:
+
+extract_data:
       if (extract) {
         if (rec->Stream == STREAM_SPARSE_DATA) {
            ser_declare;
@@ -417,7 +327,8 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            if (fileAddr != faddr) {
               fileAddr = faddr;
               if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
-                  Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
+                  Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), 
+                    attr->ofname, strerror(errno));
               }
            }
         } else {
@@ -427,12 +338,27 @@ 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)bwrite(&bfd, wbuf, wsize) != wsize) {
-            Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
+            Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), 
+              attr->ofname, strerror(errno));
         }
         fileAddr += wsize;
       }
 
-   } else if (rec->Stream == STREAM_GZIP_DATA || rec->Stream == STREAM_SPARSE_GZIP_DATA) {
+   /* Windows Backup GZIP data stream */
+   case STREAM_WIN32_GZIP_DATA:  
+      if (!is_win32_backup()) {
+        if (!non_support_attr) {
+            Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n"));
+        }
+        extract = FALSE;
+        non_support_attr++;
+        return;
+      }
+      /* Fall through desired */
+
+   /* GZIP data stream */
+   case STREAM_GZIP_DATA:
+   case STREAM_SPARSE_GZIP_DATA: 
 #ifdef HAVE_LIBZ
       if (extract) {
         uLongf compress_len;
@@ -448,7 +374,8 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            if (fileAddr != faddr) {
               fileAddr = faddr;
               if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
-                  Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
+                  Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), 
+                    attr->ofname, strerror(errno));
               }
            }
         } else {
@@ -464,7 +391,8 @@ 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)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));
+            Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), 
+              attr->ofname, strerror(errno));
         }
         total += compress_len;
         fileAddr += compress_len;
@@ -474,32 +402,37 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 #else
       if (extract) {
          Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n");
+        extract = FALSE;
+        return;
       }
 #endif
 
+   case STREAM_MD5_SIGNATURE:
+   case STREAM_SHA1_SIGNATURE:
+      break;
 
-   /* If extracting, wierd stream (not 1 or 2), close output file anyway */
-   } else if (extract) {
-      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, &bfd);
-   } else if (rec->Stream == STREAM_PROGRAM_NAMES || rec->Stream == STREAM_PROGRAM_DATA) {
+   case STREAM_PROGRAM_NAMES:
+   case STREAM_PROGRAM_DATA:
       if (!prog_name_msg) {
          Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
         prog_name_msg++;
       }
-   } else if (rec->Stream == STREAM_WIN32_DATA || rec->Stream == STREAM_WIN32_GZIP_DATA) {
-      if (!win32_data_msg) {
-         Pmsg0(000, "Got Win32 data or Win32 gzip data stream. Ignored.\n");
-        win32_data_msg++;
+      break;
+
+   default:
+      /* If extracting, wierd stream (not 1 or 2), close output file anyway */
+      if (extract) {
+        if (!is_bopen(&bfd)) {
+            Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
+        }
+        extract = FALSE;
+        set_attributes(jcr, attr, &bfd);
       }
-   } else if (!(rec->Stream == STREAM_MD5_SIGNATURE ||
-               rec->Stream == STREAM_SHA1_SIGNATURE)) {
-      Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
-   }
+      Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), 
+        rec->Stream);
+      break;
+      
+   } /* end switch */
 }
 
 
index 1e0a3b908a389b5b1689e00b80e9c9c48cd4cafd..4a72d543903f5abce353b678e2d87280796b8226 100644 (file)
 #include "stored.h"
 #include "findlib/find.h"
 
+#ifdef HAVE_CYGWIN
+int win32_client = 1;
+#else
+int win32_client = 0;
+#endif
+
+
 static void do_blocks(char *infname);
 static void do_jobs(char *infname);
 static void do_ls(char *fname);
@@ -44,7 +51,7 @@ static DEV_BLOCK *block;
 static JCR *jcr;
 static SESSION_LABEL sessrec;
 static uint32_t num_files = 0;
-static long record_file_index;
+static ATTR *attr;
 
 #define CONFIG_FILE "bacula-sd.conf"
 char *configfile;
@@ -91,77 +98,77 @@ int main (int argc, char *argv[])
 
    while ((ch = getopt(argc, argv, "b:c:d:e:i:jkLtvV:?")) != -1) {
       switch (ch) {
-         case 'b':
-           bsrName = optarg;
-           break;
+      case 'b':
+        bsrName = optarg;
+        break;
 
-         case 'c':                    /* specify config file */
-           if (configfile != NULL) {
-              free(configfile);
-           }
-           configfile = bstrdup(optarg);
-           break;
+      case 'c':                    /* specify config file */
+        if (configfile != NULL) {
+           free(configfile);
+        }
+        configfile = bstrdup(optarg);
+        break;
 
-         case 'd':                    /* debug level */
-           debug_level = atoi(optarg);
-           if (debug_level <= 0)
-              debug_level = 1; 
-           break;
+      case 'd':                    /* debug level */
+        debug_level = atoi(optarg);
+        if (debug_level <= 0)
+           debug_level = 1; 
+        break;
 
-         case 'e':                    /* exclude list */
-            if ((fd = fopen(optarg, "r")) == NULL) {
-               Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"),
-                 optarg, strerror(errno));
-              exit(1);
-           }
-           while (fgets(line, sizeof(line), fd) != NULL) {
-              strip_trailing_junk(line);
-               Dmsg1(100, "add_exclude %s\n", line);
-              add_fname_to_exclude_list(&ff, line);
-           }
-           fclose(fd);
-           break;
+      case 'e':                    /* exclude list */
+         if ((fd = fopen(optarg, "r")) == NULL) {
+            Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"),
+              optarg, strerror(errno));
+           exit(1);
+        }
+        while (fgets(line, sizeof(line), fd) != NULL) {
+           strip_trailing_junk(line);
+            Dmsg1(100, "add_exclude %s\n", line);
+           add_fname_to_exclude_list(&ff, line);
+        }
+        fclose(fd);
+        break;
 
-         case 'i':                    /* include list */
-            if ((fd = fopen(optarg, "r")) == NULL) {
-               Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
-                 optarg, strerror(errno));
-              exit(1);
-           }
-           while (fgets(line, sizeof(line), fd) != NULL) {
-              strip_trailing_junk(line);
-               Dmsg1(100, "add_include %s\n", line);
-              add_fname_to_include_list(&ff, 0, line);
-           }
-           fclose(fd);
-           break;
+      case 'i':                    /* include list */
+         if ((fd = fopen(optarg, "r")) == NULL) {
+            Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
+              optarg, strerror(errno));
+           exit(1);
+        }
+        while (fgets(line, sizeof(line), fd) != NULL) {
+           strip_trailing_junk(line);
+            Dmsg1(100, "add_include %s\n", line);
+           add_fname_to_include_list(&ff, 0, line);
+        }
+        fclose(fd);
+        break;
 
-         case 'j':
-           list_jobs = TRUE;
-           break;
+      case 'j':
+        list_jobs = TRUE;
+        break;
 
-         case 'k':
-           list_blocks = TRUE;
-           break;
+      case 'k':
+        list_blocks = TRUE;
+        break;
 
-         case 'L':
-           dump_label = TRUE;
-           break;
+      case 'L':
+        dump_label = TRUE;
+        break;
 
-         case 'v':
-           verbose++;
-           break;
+      case 'v':
+        verbose++;
+        break;
 
-         case 'V':                    /* Volume name */
-           VolumeName = optarg;
-           break;
+      case 'V':                    /* Volume name */
+        VolumeName = optarg;
+        break;
 
-         case '?':
-        default:
-           usage();
+      case '?':
+      default:
+        usage();
 
-      }  
-   }
+      } /* end switch */
+   } /* end while */
    argc -= optind;
    argv += optind;
 
@@ -191,6 +198,7 @@ int main (int argc, char *argv[])
       }
       rec = new_record();
       block = new_block(dev);
+      attr = new_attr();
       /*
        * Assume that we have already read the volume label.
        * If on second or subsequent volume, adjust buffer pointer 
@@ -220,6 +228,7 @@ Warning, this Volume is a continuation of Volume %s\n",
 static void do_close(JCR *jcr)
 {
    release_device(jcr, dev);
+   free_attr(attr);
    term_dev(dev);
    free_record(rec);
    free_block(block);
@@ -319,43 +328,28 @@ static void do_ls(char *infname)
  */
 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 {
-   char fname[2000];
-   struct stat statp;
-   int type;
-
    if (rec->FileIndex < 0) {
       get_session_record(dev, rec, &sessrec);
       return;
    }
    /* File Attributes stream */
-   if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) {
-      char *ap, *fp;
+   if (rec->Stream == STREAM_UNIX_ATTRIBUTES || 
+       rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) {
       uint32_t LinkFI;
 
-      sscanf(rec->data, "%ld %d", &record_file_index, &type);
-      if (record_file_index != rec->FileIndex) {
-         Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
-           rec->FileIndex, record_file_index);
+      if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) {
+         Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
       }
-      ap = rec->data;
-
-      while (*ap++ != ' ')         /* skip record file index */
-        ;
-      while (*ap++ != ' ')         /* skip type */
-        ;
-      /* Save filename and position to attributes */
-      fp = fname;
-      while (*ap != 0) {
-        *fp++  = *ap++;
+
+      if (attr->file_index != rec->FileIndex) {
+         Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
+           rec->FileIndex, attr->file_index);
       }
-      *fp = *ap++;                /* terminate filename & point to attribs */
-
-      decode_stat(ap, &statp, &LinkFI);
-      /* Skip to link name */  
-      while (*ap++ != 0)
-        ;
-      if (file_is_included(&ff, fname) && !file_is_excluded(&ff, fname)) {
-        print_ls_output(fname, ap, type, &statp);
+
+      decode_stat(attr->attr, &attr->statp, &LinkFI);
+
+      if (file_is_included(&ff, attr->fname) && !file_is_excluded(&ff, attr->fname)) {
+        print_ls_output(jcr, attr);
         num_files++;
       }
    }
index 99b9f23be93fe32e156956e84fefbf19628665a5..9056f635f7419ee1f10730312dae77f507762469 100644 (file)
@@ -55,18 +55,18 @@ static int update_SIG_record(B_DB *db, char *SIGbuf, DEV_RECORD *rec, int type);
 
 /* Global variables */
 STORES *me;
+#ifdef HAVE_CYGWIN
+int win32_client = 1;
+#else
+int win32_client = 0;
+#endif
+
 
 /* Local variables */
 static DEVICE *dev = NULL;
 static B_DB *db;
 static JCR *bjcr;                    /* jcr for bscan */
 static BSR *bsr = NULL;
-static struct stat statp;
-static int type;
-static long record_file_index;
-static POOLMEM *fname;                      /* original file name */
-static POOLMEM *ofile;                      /* output name with prefix */
-static POOLMEM *lname;                      /* link name */
 static MEDIA_DBR mr;
 static POOL_DBR pr;
 static JOB_DBR jr;
@@ -76,6 +76,7 @@ static ATTR_DBR ar;
 static FILE_DBR fr;
 static SESSION_LABEL label;
 static SESSION_LABEL elabel;
+static ATTR *attr;
 
 static time_t lasttime = 0;
 
@@ -126,62 +127,62 @@ int main (int argc, char *argv[])
 
    while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vw:?")) != -1) {
       switch (ch) {
-         case 'b':
-           bsr = parse_bsr(NULL, optarg);
-           break;
+      case 'b':
+        bsr = parse_bsr(NULL, optarg);
+        break;
 
-         case 'c':                    /* specify config file */
-           if (configfile != NULL) {
-              free(configfile);
-           }
-           configfile = bstrdup(optarg);
-           break;
+      case 'c':                    /* specify config file */
+        if (configfile != NULL) {
+           free(configfile);
+        }
+        configfile = bstrdup(optarg);
+        break;
 
-         case 'd':                    /* debug level */
-           debug_level = atoi(optarg);
-           if (debug_level <= 0)
-              debug_level = 1; 
-           break;
+      case 'd':                    /* debug level */
+        debug_level = atoi(optarg);
+        if (debug_level <= 0)
+           debug_level = 1; 
+        break;
 
-         case 'm':
-           update_vol_info = 1;
-           break;
+      case 'm':
+        update_vol_info = 1;
+        break;
 
-         case 'n':
-           db_name = optarg;
-           break;
+      case 'n':
+        db_name = optarg;
+        break;
 
-         case 'u':
-           db_user = optarg;
-           break;
+      case 'u':
+        db_user = optarg;
+        break;
 
-         case 'p':
-           db_password = optarg;
-           break;
+      case 'p':
+        db_password = optarg;
+        break;
 
-         case 'r':
-           list_records = 1;
-           break;
+      case 'r':
+        list_records = 1;
+        break;
 
-         case 's':
-           update_db = 1;
-           break;
+      case 's':
+        update_db = 1;
+        break;
 
-         case 'v':
-           verbose++;
-           break;
+      case 'v':
+        verbose++;
+        break;
 
-         case 'V':                    /* Volume name */
-           VolumeName = optarg;
-           break;
+      case 'V':                    /* Volume name */
+        VolumeName = optarg;
+        break;
 
-         case 'w':
-           wd = optarg;
-           break;
+      case 'w':
+        wd = optarg;
+        break;
 
-         case '?':
-        default:
-           usage();
+      case '?':
+      default:
+        usage();
 
       }  
    }
@@ -252,9 +253,7 @@ int main (int argc, char *argv[])
 
 static void do_scan()            
 {
-   fname = get_pool_memory(PM_FNAME);
-   ofile = get_pool_memory(PM_FNAME);
-   lname = get_pool_memory(PM_FNAME);
+   attr = new_attr();
 
    memset(&ar, 0, sizeof(ar));
    memset(&pr, 0, sizeof(pr));
@@ -268,9 +267,7 @@ static void do_scan()
    read_records(bjcr, dev, record_cb, mount_next_read_volume);
    release_device(bjcr, dev);
 
-   free_pool_memory(fname);
-   free_pool_memory(ofile);
-   free_pool_memory(lname);
+   free_attr(attr);
    term_dev(dev);
 }
 
@@ -298,255 +295,225 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         dump_label_record(dev, rec, 1);
       }
       switch (rec->FileIndex) {
-        case PRE_LABEL:
-            Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n"));
-           return;
-           break;
-        case VOL_LABEL:
-           unser_volume_label(dev, rec);
-           /* Check Pool info */
-           strcpy(pr.Name, dev->VolHdr.PoolName);
-           strcpy(pr.PoolType, dev->VolHdr.PoolType);
-           if (db_get_pool_record(bjcr, db, &pr)) {
-              if (verbose) {
-                  Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name);
-              }
-           } else {
-              if (!update_db) {
-                  Pmsg1(000, _("VOL_LABEL: Pool record not found for Pool: %s\n"),
-                    pr.Name);
-              }
-              create_pool_record(db, &pr);
+      case PRE_LABEL:
+         Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n"));
+        return;
+        break;
+      case VOL_LABEL:
+        unser_volume_label(dev, rec);
+        /* Check Pool info */
+        strcpy(pr.Name, dev->VolHdr.PoolName);
+        strcpy(pr.PoolType, dev->VolHdr.PoolType);
+        if (db_get_pool_record(bjcr, db, &pr)) {
+           if (verbose) {
+               Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name);
            }
-           if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
-               Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"),
-                 pr.PoolType, dev->VolHdr.PoolType);
-              return;
-           } else if (verbose) {
-               Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType);
+        } else {
+           if (!update_db) {
+               Pmsg1(000, _("VOL_LABEL: Pool record not found for Pool: %s\n"),
+                 pr.Name);
            }
+           create_pool_record(db, &pr);
+        }
+        if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
+            Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"),
+              pr.PoolType, dev->VolHdr.PoolType);
+           return;
+        } else if (verbose) {
+            Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType);
+        }
 
-           /* Check Media Info */
-           memset(&mr, 0, sizeof(mr));
-           strcpy(mr.VolumeName, dev->VolHdr.VolName);
-           mr.PoolId = pr.PoolId;
-           if (db_get_media_record(bjcr, db, &mr)) {
-              if (verbose) {
-                  Pmsg1(000, _("Media record for %s found in DB.\n"), mr.VolumeName);
-              }
-              /* Clear out some volume statistics that will be updated */
-              mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0;
-              mr.VolBytes = rec->data_len + 20;
-           } else {
-              if (!update_db) {
-                  Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"),
-                    mr.VolumeName);
-              }
-              strcpy(mr.MediaType, dev->VolHdr.MediaType);
-              create_media_record(db, &mr, &dev->VolHdr);
-           }
-           if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
-               Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"),
-                 mr.MediaType, dev->VolHdr.MediaType);
-              return;
-           } else if (verbose) {
-               Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType);
+        /* Check Media Info */
+        memset(&mr, 0, sizeof(mr));
+        strcpy(mr.VolumeName, dev->VolHdr.VolName);
+        mr.PoolId = pr.PoolId;
+        if (db_get_media_record(bjcr, db, &mr)) {
+           if (verbose) {
+               Pmsg1(000, _("Media record for %s found in DB.\n"), mr.VolumeName);
            }
-           /* Reset some JCR variables */
-           for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
-              mjcr->VolFirstIndex = mjcr->FileIndex = 0;
-              mjcr->StartBlock = mjcr->EndBlock = 0;
-              mjcr->StartFile = mjcr->EndFile = 0;
+           /* Clear out some volume statistics that will be updated */
+           mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0;
+           mr.VolBytes = rec->data_len + 20;
+        } else {
+           if (!update_db) {
+               Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"),
+                 mr.VolumeName);
            }
+           strcpy(mr.MediaType, dev->VolHdr.MediaType);
+           create_media_record(db, &mr, &dev->VolHdr);
+        }
+        if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
+            Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"),
+              mr.MediaType, dev->VolHdr.MediaType);
+           return;
+        } else if (verbose) {
+            Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType);
+        }
+        /* Reset some JCR variables */
+        for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+           mjcr->VolFirstIndex = mjcr->FileIndex = 0;
+           mjcr->StartBlock = mjcr->EndBlock = 0;
+           mjcr->StartFile = mjcr->EndFile = 0;
+        }
 
-            Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName);
-           break;
-        case SOS_LABEL:
-           mr.VolJobs++;
-           if (ignored_msgs > 0) {
-               Pmsg1(000, _("%d \"errors\" ignored before first Start of Session record.\n"), 
-                    ignored_msgs);
-              ignored_msgs = 0;
-           }
-           unser_session_label(&label, rec);
-           memset(&jr, 0, sizeof(jr));
-           jr.JobId = label.JobId;
-           if (db_get_job_record(bjcr, db, &jr)) {
-              /* Job record already exists in DB */
-               update_db = 0;  /* don't change db in create_job_record */
-              if (verbose) {
-                  Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId);
-              }
-           } else {
-              /* Must create a Job record in DB */
-              if (!update_db) {
-                  Pmsg1(000, _("SOS_LABEL: Job record not found for JobId: %d\n"),
-                    jr.JobId);
-              }
-           }
-           /* Create Client record if not already there */
-              strcpy(cr.Name, label.ClientName);
-              create_client_record(db, &cr);
-              jr.ClientId = cr.ClientId;
-
-            /* process label, if Job record exists don't update db */
-           mjcr = create_job_record(db, &jr, &label, rec);
-           update_db = save_update_db;
-
-           jr.PoolId = pr.PoolId;
-           /* Set start positions into JCR */
-           if (dev->state & ST_TAPE) {
-              mjcr->StartBlock = dev->block_num;
-              mjcr->StartFile = dev->file;
-           } else {
-              mjcr->StartBlock = (uint32_t)dev->file_addr;
-              mjcr->StartFile = (uint32_t)(dev->file_addr >> 32);
-           }
-           mjcr->start_time = jr.StartTime;
-           mjcr->JobLevel = jr.Level;
-
-           mjcr->client_name = get_pool_memory(PM_FNAME);
-           pm_strcpy(&mjcr->client_name, label.ClientName);
-           mjcr->pool_type = get_pool_memory(PM_FNAME);
-           pm_strcpy(&mjcr->pool_type, label.PoolType);
-           mjcr->fileset_name = get_pool_memory(PM_FNAME);
-           pm_strcpy(&mjcr->fileset_name, label.FileSetName);
-           mjcr->pool_name = get_pool_memory(PM_FNAME);
-           pm_strcpy(&mjcr->pool_name, label.PoolName);
-
-           if (rec->VolSessionId != jr.VolSessionId) {
-               Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"),
-                 jr.JobId,
-                 jr.VolSessionId, rec->VolSessionId);
-              return;
-           }
-           if (rec->VolSessionTime != jr.VolSessionTime) {
-               Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"),
-                 jr.JobId,
-                 jr.VolSessionTime, rec->VolSessionTime);
-              return;
+         Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName);
+        break;
+      case SOS_LABEL:
+        mr.VolJobs++;
+        if (ignored_msgs > 0) {
+            Pmsg1(000, _("%d \"errors\" ignored before first Start of Session record.\n"), 
+                 ignored_msgs);
+           ignored_msgs = 0;
+        }
+        unser_session_label(&label, rec);
+        memset(&jr, 0, sizeof(jr));
+        jr.JobId = label.JobId;
+        if (db_get_job_record(bjcr, db, &jr)) {
+           /* Job record already exists in DB */
+            update_db = 0;  /* don't change db in create_job_record */
+           if (verbose) {
+               Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId);
            }
-           if (jr.PoolId != pr.PoolId) {
-               Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"),
-                 jr.JobId,
-                 jr.PoolId, pr.PoolId);
-              return;
+        } else {
+           /* Must create a Job record in DB */
+           if (!update_db) {
+               Pmsg1(000, _("SOS_LABEL: Job record not found for JobId: %d\n"),
+                 jr.JobId);
            }
+        }
+        /* Create Client record if not already there */
+           strcpy(cr.Name, label.ClientName);
+           create_client_record(db, &cr);
+           jr.ClientId = cr.ClientId;
+
+         /* process label, if Job record exists don't update db */
+        mjcr = create_job_record(db, &jr, &label, rec);
+        update_db = save_update_db;
+
+        jr.PoolId = pr.PoolId;
+        /* Set start positions into JCR */
+        if (dev->state & ST_TAPE) {
+           mjcr->StartBlock = dev->block_num;
+           mjcr->StartFile = dev->file;
+        } else {
+           mjcr->StartBlock = (uint32_t)dev->file_addr;
+           mjcr->StartFile = (uint32_t)(dev->file_addr >> 32);
+        }
+        mjcr->start_time = jr.StartTime;
+        mjcr->JobLevel = jr.Level;
+
+        mjcr->client_name = get_pool_memory(PM_FNAME);
+        pm_strcpy(&mjcr->client_name, label.ClientName);
+        mjcr->pool_type = get_pool_memory(PM_FNAME);
+        pm_strcpy(&mjcr->pool_type, label.PoolType);
+        mjcr->fileset_name = get_pool_memory(PM_FNAME);
+        pm_strcpy(&mjcr->fileset_name, label.FileSetName);
+        mjcr->pool_name = get_pool_memory(PM_FNAME);
+        pm_strcpy(&mjcr->pool_name, label.PoolName);
+
+        if (rec->VolSessionId != jr.VolSessionId) {
+            Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"),
+              jr.JobId,
+              jr.VolSessionId, rec->VolSessionId);
+           return;
+        }
+        if (rec->VolSessionTime != jr.VolSessionTime) {
+            Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"),
+              jr.JobId,
+              jr.VolSessionTime, rec->VolSessionTime);
+           return;
+        }
+        if (jr.PoolId != pr.PoolId) {
+            Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"),
+              jr.JobId,
+              jr.PoolId, pr.PoolId);
+           return;
+        }
+        break;
+      case EOS_LABEL:
+        unser_session_label(&elabel, rec);
+
+        /* Create FileSet record */
+        strcpy(fsr.FileSet, label.FileSetName);
+        strcpy(fsr.MD5, label.FileSetMD5);
+        create_fileset_record(db, &fsr);
+        jr.FileSetId = fsr.FileSetId;
+
+        mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+        if (!mjcr) {
+            Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
+                 rec->VolSessionId, rec->VolSessionTime);
            break;
-        case EOS_LABEL:
-           unser_session_label(&elabel, rec);
-
-           /* Create FileSet record */
-           strcpy(fsr.FileSet, label.FileSetName);
-           strcpy(fsr.MD5, label.FileSetMD5);
-           create_fileset_record(db, &fsr);
-           jr.FileSetId = fsr.FileSetId;
-
-           mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-           if (!mjcr) {
-               Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
-                    rec->VolSessionId, rec->VolSessionTime);
-              break;
-           }
+        }
 
-           /* Do the final update to the Job record */
-           update_job_record(db, &jr, &elabel, rec);
+        /* Do the final update to the Job record */
+        update_job_record(db, &jr, &elabel, rec);
 
-           mjcr->end_time = jr.EndTime;
-           mjcr->JobStatus = JS_Terminated;
+        mjcr->end_time = jr.EndTime;
+        mjcr->JobStatus = JS_Terminated;
 
-           /* Create JobMedia record */
-           create_jobmedia_record(db, mjcr);
-           detach_jcr_from_device(dev, mjcr);
-           free_jcr(mjcr);
+        /* Create JobMedia record */
+        create_jobmedia_record(db, mjcr);
+        detach_jcr_from_device(dev, mjcr);
+        free_jcr(mjcr);
 
-           break;
-        case EOM_LABEL:
-           break;
-        case EOT_LABEL:              /* end of all tapes */
-           /* 
-            * Wiffle through all jobs still open and close
-            *   them.
-            */
-           if (update_db) {
-              for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
-                 jr.JobId = mjcr->JobId;
-                 jr.JobStatus = JS_ErrorTerminated;
-                 jr.JobFiles = mjcr->JobFiles;
-                 jr.JobBytes = mjcr->JobBytes;
-                 jr.VolSessionId = mjcr->VolSessionId;
-                 jr.VolSessionTime = mjcr->VolSessionTime;
-                 jr.JobTDate = (utime_t)mjcr->start_time;
-                 jr.ClientId = mjcr->ClientId;
-                 free_jcr(mjcr);
-                 if (!db_update_job_end_record(bjcr, db, &jr)) {
-                     Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
-                 }
+        break;
+      case EOM_LABEL:
+        break;
+      case EOT_LABEL:             /* end of all tapes */
+        /* 
+         * Wiffle through all jobs still open and close
+         *   them.
+         */
+        if (update_db) {
+           for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+              jr.JobId = mjcr->JobId;
+              jr.JobStatus = JS_ErrorTerminated;
+              jr.JobFiles = mjcr->JobFiles;
+              jr.JobBytes = mjcr->JobBytes;
+              jr.VolSessionId = mjcr->VolSessionId;
+              jr.VolSessionTime = mjcr->VolSessionTime;
+              jr.JobTDate = (utime_t)mjcr->start_time;
+              jr.ClientId = mjcr->ClientId;
+              free_jcr(mjcr);
+              if (!db_update_job_end_record(bjcr, db, &jr)) {
+                  Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
               }
            }
-           mr.VolFiles = rec->File;
-           mr.VolBlocks = rec->Block;
-           mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */
-           mr.VolMounts++;
-           update_media_record(db, &mr);
-            Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles,
-                      mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1));
-           break;
-        default:
-           break;
-      }
+        }
+        mr.VolFiles = rec->File;
+        mr.VolBlocks = rec->Block;
+        mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */
+        mr.VolMounts++;
+        update_media_record(db, &mr);
+         Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles,
+                   mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1));
+        break;
+      default:
+        break;
+      } /* end switch */
       return;
    }
 
 
    /* File Attributes stream */
-   if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) {
-      char *ap, *lp, *fp;
+   switch (rec->Stream) {
+   case STREAM_UNIX_ATTRIBUTES:   
+   case STREAM_UNIX_ATTRIBUTES_EX:  
 
-      if (sizeof_pool_memory(fname) < rec->data_len) {
-        fname = realloc_pool_memory(fname, rec->data_len + 1);
+      if (!unpack_attributes_record(bjcr, rec->Stream, rec->data, attr)) {
+         Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
       }
-      if (sizeof_pool_memory(lname) < rec->data_len) {
-        lname = realloc_pool_memory(lname, rec->data_len + 1);
-      }
-      *fname = 0;
-      *lname = 0;
-
-      /*             
-       * An Attributes record consists of:
-       *    File_index
-       *    Type   (FT_types)
-       *    Filename
-       *    Attributes
-       *    Link name (if file linked i.e. FT_LNK)
-       *
-       */
-      sscanf(rec->data, "%ld %d", &record_file_index, &type);
-      if (record_file_index != rec->FileIndex)
-         Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
-           rec->FileIndex, record_file_index);
-      ap = rec->data;
-      while (*ap++ != ' ')         /* skip record file index */
-        ;
-      while (*ap++ != ' ')         /* skip type */
-        ;
-      /* Save filename and position to attributes */
-      fp = fname;
-      while (*ap != 0) {
-        *fp++  = *ap++;
-      }
-      *fp = *ap++;                /* terminate filename & point to attribs */
 
-      /* Skip through attributes to link name */
-      lp = ap;
-      while (*lp++ != 0) {
-        ;
+      if (attr->file_index != rec->FileIndex) {
+         Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
+           rec->FileIndex, attr->file_index);
       }
-      strcat(lname, lp);        /* "save" link name */
+       
       if (verbose > 1) {
         uint32_t LinkFI;
-        decode_stat(ap, &statp, &LinkFI);
-        print_ls_output(fname, lname, type, &statp);   
+        decode_stat(attr->attr, &attr->statp, &LinkFI);
+        print_ls_output(bjcr, attr);
       }
       mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
       if (!mjcr) {
@@ -560,17 +527,21 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       }
       fr.JobId = mjcr->JobId;
       fr.FileId = 0;
-      if (db_get_file_attributes_record(bjcr, db, fname, &fr)) {
+      if (db_get_file_attributes_record(bjcr, db, attr->fname, &fr)) {
         if (verbose > 1) {
-            Pmsg1(000, _("File record already exists for: %s\n"), fname);
+            Pmsg1(000, _("File record already exists for: %s\n"), attr->fname);
         }
       } else {
-        create_file_attributes_record(db, mjcr, fname, lname, type, ap, rec);
+        create_file_attributes_record(db, mjcr, attr->fname, attr->lname, 
+           attr->type, attr->attr, rec);
       }
       free_jcr(mjcr);
+      break;
 
    /* Data stream */
-   } else if (rec->Stream == STREAM_FILE_DATA) {
+   case STREAM_WIN32_DATA:
+   case STREAM_FILE_DATA:
+   case STREAM_SPARSE_DATA:
       mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
       if (!mjcr) {
         if (mr.VolJobs > 0) {
@@ -582,23 +553,14 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         return;
       }
       mjcr->JobBytes += rec->data_len;
-      free_jcr(mjcr);                /* done using JCR */
-
-   } else if (rec->Stream == STREAM_SPARSE_DATA) {
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Sparse Data record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
+      if (rec->Stream == STREAM_SPARSE_DATA) {
+        mjcr->JobBytes -= sizeof(uint64_t);
       }
-      mjcr->JobBytes += rec->data_len - sizeof(uint64_t);
+        
       free_jcr(mjcr);                /* done using JCR */
+      break;
 
-   } else if (rec->Stream == STREAM_GZIP_DATA) {
+   case STREAM_GZIP_DATA:
       mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
       if (!mjcr) {
         if (mr.VolJobs > 0) {
@@ -611,8 +573,9 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       }
       mjcr->JobBytes += rec->data_len; /* No correct, we should expand it */
       free_jcr(mjcr);                /* done using JCR */
+      break;
 
-   } else if (rec->Stream == STREAM_SPARSE_GZIP_DATA) {
+   case STREAM_SPARSE_GZIP_DATA:
       mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
       if (!mjcr) {
         if (mr.VolJobs > 0) {
@@ -625,24 +588,10 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       }
       mjcr->JobBytes += rec->data_len - sizeof(uint64_t); /* No correct, we should expand it */
       free_jcr(mjcr);                /* done using JCR */
-
-   /* Win32 Data stream */
-   } else if (rec->Stream == STREAM_WIN32_DATA) {
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Win32 Data record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
-      }
-      mjcr->JobBytes += rec->data_len;
-      free_jcr(mjcr);                /* done using JCR */
+      break;
 
    /* Win32 GZIP stream */
-   } else if (rec->Stream == STREAM_WIN32_GZIP_DATA) {
+   case STREAM_WIN32_GZIP_DATA:
       mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
       if (!mjcr) {
         if (mr.VolJobs > 0) {
@@ -655,34 +604,41 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       }
       mjcr->JobBytes += rec->data_len;
       free_jcr(mjcr);                /* done using JCR */
+      break;
 
-   } else if (rec->Stream == STREAM_MD5_SIGNATURE) {
+   case STREAM_MD5_SIGNATURE:
       char MD5buf[50];
       bin_to_base64(MD5buf, (char *)rec->data, 16); /* encode 16 bytes */
       if (verbose > 1) {
          Pmsg1(000, _("Got MD5 record: %s\n"), MD5buf);
       }
       update_SIG_record(db, MD5buf, rec, MD5_SIG);
+      break;
 
-   } else if (rec->Stream == STREAM_SHA1_SIGNATURE) {
+   case STREAM_SHA1_SIGNATURE:
       char SIGbuf[50];
       bin_to_base64(SIGbuf, (char *)rec->data, 20); /* encode 20 bytes */
       if (verbose > 1) {
          Pmsg1(000, _("Got SHA1 record: %s\n"), SIGbuf);
       }
       update_SIG_record(db, SIGbuf, rec, SHA1_SIG);
+      break;
 
 
-   } else if (rec->Stream == STREAM_PROGRAM_NAMES) {
+   case STREAM_PROGRAM_NAMES:
       if (verbose) {
          Pmsg1(000, _("Got Prog Names Stream: %s\n"), rec->data);
       }
-   } else if (rec->Stream == STREAM_PROGRAM_DATA) {
+      break;
+
+   case STREAM_PROGRAM_DATA:
       if (verbose > 1) {
          Pmsg0(000, _("Got Prog Data Stream record.\n"));
       }
-   } else {
+      break;
+   default:
       Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data);
+      break;
    }
    return;
 }
index a9cad0198e052f3b83d6c642db2a34fc89a121e4..a23bb1646f796a553174a76754907bc6707772fb 100644 (file)
@@ -226,6 +226,7 @@ JCR *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName)
    if (!bsr && VolumeName) {
       pm_strcpy(&jcr->VolumeName, VolumeName);
    }
+   jcr->where = bstrdup("");
    return jcr;
 }
 
@@ -253,41 +254,3 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev)
    else
       Jmsg(jcr, M_ERROR, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno));
 }
-
-
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
-
-void print_ls_output(char *fname, char *link, int type, struct stat *statp)
-{
-   char buf[1000]; 
-   char ec1[30];
-   char *p, *f;
-   int n;
-
-   p = encode_mode(statp->st_mode, buf);
-   n = sprintf(p, "  %2d ", (uint32_t)statp->st_nlink);
-   p += n;
-   n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
-   p += n;
-   n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
-   p += n;
-   p = encode_time(statp->st_ctime, p);
-   *p++ = ' ';
-   *p++ = ' ';
-   /* Copy file name */
-   for (f=fname; *f && (p-buf) < (int)sizeof(buf); )
-      *p++ = *f++;
-   if (type == FT_LNK) {
-      *p++ = ' ';
-      *p++ = '-';
-      *p++ = '>';
-      *p++ = ' ';
-      /* Copy link name */
-      for (f=link; *f && (p-buf) < (int)sizeof(buf); )
-        *p++ = *f++;
-   }
-   *p++ = '\n';
-   *p = 0;
-   fputs(buf, stdout);
-}
index 22b3c4ebdf19b2e07e98e5cecea8480e242e854b..e560ad03853439a4e4b3439dc16529439c7a6cbf 100644 (file)
@@ -102,8 +102,8 @@ char *stream_to_ascii(int stream, int fi)
        return "SHA1";
     case STREAM_GZIP_DATA:
        return "GZIP";
-    case STREAM_WIN32_ATTRIBUTES:
-       return "WIN32-ATTR";
+    case STREAM_UNIX_ATTRIBUTES_EX:
+       return "UNIX-ATTR-EX";
     case STREAM_SPARSE_DATA:
        return "SPARSE-DATA";
     case STREAM_SPARSE_GZIP_DATA:
@@ -126,8 +126,8 @@ char *stream_to_ascii(int stream, int fi)
        return "contSHA1";
     case -STREAM_GZIP_DATA:
        return "contGZIP";
-    case -STREAM_WIN32_ATTRIBUTES:
-       return "contWIN32-ATTR";
+    case -STREAM_UNIX_ATTRIBUTES_EX:
+       return "contUNIX-ATTR-EX";
     case -STREAM_SPARSE_DATA:
        return "contSPARSE-DATA";
     case -STREAM_SPARSE_GZIP_DATA:
index 11cc78e6f07bd01d712713f830d114aa73d42776..ff27271b4404cb6b1b2448b8428673d9793ded2d 100644 (file)
 #include "jcr.h"
 #include "protos.h"
 #ifdef HAVE_LIBZ
-#include <zlib.h>                    /* compression headers */
+#include <zlib.h>                     /* compression headers */
 #else
 #define uLongf uint32_t
 #endif
 
-#include "findlib/find.h"
-
-extern char errmsg[];                /* general error message */
+extern char errmsg[];                 /* general error message */
 
 extern STORES *me;                    /* "Global" daemon resource */