]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/attr.c
Backport from BEE
[bacula/bacula] / bacula / src / lib / attr.c
index 4147da5670a6690313eca4e97d662e628170b60d..b6df46b8e2397f69d71031d75c1b9c660e2bcaaf 100644 (file)
@@ -1,42 +1,41 @@
 /*
- *   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
+   Bacula® - The Network Backup Solution
 
-   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.
+   Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
 
-   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.
+   The main author of Bacula is Kern Sibbald, with contributions from many
+   others, a complete list can be found in the file AUTHORS.
 
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
 
+   Bacula® is a registered trademark of Kern Sibbald.
+*/
+/*
+ *   attr.c  Unpack an Attribute record returned from the tape
+ *
+ *    Kern Sibbald, June MMIII  (code pulled from filed/restore.c and updated)
+ *
  */
 
+
 #include "bacula.h"
 #include "jcr.h"
+#include "lib/breg.h"
 
-extern int win32_client;
+static const int dbglvl = 150;
 
-ATTR *new_attr()
+ATTR *new_attr(JCR *jcr)
 {
    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);
+   attr->attrEx = get_pool_memory(PM_FNAME);
+   attr->jcr = jcr;
+   attr->uid = getuid();
    return attr;
 }
 
@@ -44,73 +43,111 @@ void free_attr(ATTR *attr)
 {
    free_pool_memory(attr->olname);
    free_pool_memory(attr->ofname);
+   free_pool_memory(attr->attrEx);
    free(attr);
 }
 
-int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
+int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, int32_t reclen, ATTR *attr)
 {
    char *p;
-   /*             
+   int object_len;
+   /*
     * An Attributes record consists of:
-    *   File_index
-    *   Type   (FT_types)
-    *   Filename
-    *   Attributes
-    *   Link name (if file linked i.e. FT_LNK)
-    *   Extended attributes (Win32)
+    *    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
+    *    Data_stream
     *
     */
    attr->stream = stream;
-   Dmsg1(100, "Attr: %s\n", rec);
+   Dmsg1(dbglvl, "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);
+      Dmsg1(dbglvl, "\nError scanning attributes. %s\n", rec);
       return 0;
    }
-   Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
+   Dmsg2(dbglvl, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
+   /*
+    * Note AR_DATA_STREAM should never be set since it is encoded
+    *  at the end of the attributes.
+    */
    if (attr->type & AR_DATA_STREAM) {
       attr->data_stream = 1;
    } else {
       attr->data_stream = 0;
    }
-   attr->type &= FT_MASK;            /* keep only type bits */
+   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->fname = p;                   /* set filname position */
+   while (*p++ != 0)                  /* skip filename */
       { }
-   attr->attr = p;                   /* set attributes position */
-   while (*p++ != 0)                 /* skip attributes */
+   attr->attr = p;                    /* set attributes position */
+   while (*p++ != 0)                  /* skip attributes */
       { }
-   attr->lname = p;                  /* set link position */
-   while (*p++ != 0)                 /* skip link */
+   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;
+   attr->delta_seq = 0;
+   if (attr->type == FT_RESTORE_FIRST) {
+      /* We have an object, so do a binary copy */
+      object_len = reclen + rec - p;
+      attr->attrEx = check_pool_memory_size(attr->attrEx, object_len + 1);
+      memcpy(attr->attrEx, p, object_len);
+      /* Add a EOS for those who attempt to print the object */
+      p = attr->attrEx + object_len;
+      *p = 0;
+   } else {
+      pm_strcpy(attr->attrEx, p);     /* copy extended attributes, if any */
+      if (attr->data_stream) {
+         int64_t val;
+         while (*p++ != 0)            /* skip extended attributes */
+            { }
+         from_base64(&val, p);
+         attr->data_stream = (int32_t)val;
+      } else {
+         while (*p++ != 0)            /* skip extended attributes */
+            { }
+         if (p - rec < reclen) {
+            attr->delta_seq = str_to_int32(p); /* delta_seq */
+         }
+      }
    }
-   Dmsg7(200, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
+   Dmsg8(dbglvl, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s datastr=%d delta_seq=%d\n",
       attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
-      attr->attrEx, attr->data_stream);
-   *mp_chr(attr->ofname) = 0;
-   *mp_chr(attr->olname) = 0;
+      attr->attrEx, attr->data_stream, attr->delta_seq);
+   *attr->ofname = 0;
+   *attr->olname = 0;
    return 1;
 }
 
+#if defined(HAVE_WIN32)
+static void strip_double_slashes(char *fname)
+{
+   char *p = fname;
+   while (p && *p) {
+      p = strpbrk(p, "/\\");
+      if (p != NULL) {
+         if (IsPathSeparator(p[1])) {
+            strcpy(p, p+1);
+         }
+         p++;
+      }
+   }
+}
+#endif
+
 /*
  * Build attr->ofname from attr->fname and
- *      attr->olname from attr->olname 
+ *       attr->olname from attr->olname
  */
 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
 {
@@ -119,81 +156,124 @@ void build_attr_output_fnames(JCR *jcr, ATTR *attr)
     * 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.
-    *    
+    *   a drive letter -- we simply change the drive
+    *   from, for example, c: to c/ for
+    *   every filename if a prefix is supplied.
+    *
     */
-   if (jcr->where[0] == 0) {
-      pm_strcpy(&attr->ofname, attr->fname);
-      pm_strcpy(&attr->olname, attr->lname);
+
+   if (jcr->where_bregexp) {
+      char *ret;
+      apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
+      pm_strcpy(attr->ofname, ret);
+
+      if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
+         /* Always add prefix to hard links (FT_LNKSAVED) and
+          *  on user request to soft links
+          */
+
+         if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
+            apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
+            pm_strcpy(attr->olname, ret);
+
+         } else {
+            pm_strcpy(attr->olname, attr->lname);
+         }
+      }
+
+   } else if (jcr->where[0] == 0) {
+      pm_strcpy(attr->ofname, attr->fname);
+      pm_strcpy(attr->olname, attr->lname);
+
    } else {
-      char *fn;
+      const 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 */
+      pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
+#if defined(HAVE_WIN32)
+      if (attr->fname[1] == ':') {
+         attr->fname[1] = '/';     /* convert : to / */
       }
+#endif
+      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 */
+      if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(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 {
-           mp_chr(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 */
+         bool add_link;
+         /* Always add prefix to hard links (FT_LNKSAVED) and
+          *  on user request to soft links
+          */
+         if (IsPathSeparator(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 defined(HAVE_WIN32)
+         if (attr->lname[1] == ':') {
+            attr->lname[1] = '/';    /* turn : into / */
+         }
+#endif
+         fn = attr->lname;       /* take whole name */
+         /* Ensure where is terminated with a slash */
+         if (add_link &&
+            !IsPathSeparator(jcr->where[wherelen-1]) &&
+            !IsPathSeparator(fn[0])) {
+            pm_strcat(attr->olname, "/");
+         }
+         pm_strcat(attr->olname, fn);     /* copy rest of link */
       }
    }
+#if defined(HAVE_WIN32)
+   strip_double_slashes(attr->ofname);
+   strip_double_slashes(attr->olname);
+#endif
 }
 
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
+extern char *getuser(uid_t uid, char *name, int len);
+extern char *getgroup(gid_t gid, char *name, int len);
 
 /*
  * Print an ls style message, also send M_RESTORED
  */
 void print_ls_output(JCR *jcr, ATTR *attr)
 {
-   char buf[5000]; 
+   char buf[5000];
    char ec1[30];
+   char en1[30], en2[30];
    char *p, *f;
-   int n;
+   guid_list *guid;
+
+   if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
+      bsnprintf(buf, sizeof(buf),
+                "----------   - -        -                  - ---------- --------  %s\n", attr->ofname);
+      Dmsg1(dbglvl, "%s", buf);
+      Jmsg(jcr, M_RESTORED, 1, "%s", buf);
+      return;
+   }
 
+   if (!jcr->id_list) {
+      jcr->id_list = new_guid_list();
+   }
+   guid = jcr->id_list;
    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 += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
+   p += sprintf(p, "%-8.8s %-8.8s",
+                guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
+                guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
+   p += sprintf(p, "%12.12s ", edit_int64(attr->statp.st_size, ec1));
    p = encode_time(attr->statp.st_ctime, p);
    *p++ = ' ';
    *p++ = ' ';
-   for (f=mp_chr(attr->ofname); *f && (p-buf) < (int)sizeof(buf)-10; ) {
+   for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
       *p++ = *f++;
    }
    if (attr->type == FT_LNK) {
@@ -202,12 +282,12 @@ void print_ls_output(JCR *jcr, ATTR *attr)
       *p++ = '>';
       *p++ = ' ';
       /* Copy link name */
-      for (f=mp_chr(attr->olname); *f && (p-buf) < (int)sizeof(buf)-10; ) {
-        *p++ = *f++;
+      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);
+   Dmsg1(dbglvl, "%s", buf);
+   Jmsg(jcr, M_RESTORED, 1, "%s", buf);
 }