]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/findlib/attribs.c
Tweak fix MySQL quoting again :-(
[bacula/bacula] / bacula / src / findlib / attribs.c
old mode 100755 (executable)
new mode 100644 (file)
index 3988eae..6bbfb0a
@@ -1,42 +1,54 @@
 /*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version three of the GNU Affero General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   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 Affero General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of Kern Sibbald.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+/**
  *  Encode and decode standard Unix attributes and
  *   Extended attributes for Win32 and
  *   other non-Unix systems, or Unix systems with ACLs, ...
  *
  *    Kern Sibbald, October MMII
  *
- *   Version $Id$
- *
- */
-/*
-   Copyright (C) 2000-2005 Kern Sibbald
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
-
-   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 
-   the file LICENSE for additional details.
-
  */
 
 #include "bacula.h"
 #include "find.h"
 
-#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
-
-#include "../lib/winapi.h"
+static uid_t my_uid = 1;
+static gid_t my_gid = 1;                        
+static bool uid_set = false;
 
 
+#if defined(HAVE_WIN32)
 /* Forward referenced subroutines */
 static bool 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);
+void win_error(JCR *jcr, const char *prefix, POOLMEM *ofile);
 HANDLE bget_handle(BFILE *bfd);
-#endif
+#endif /* HAVE_WIN32 */
 
 /* For old systems that don't have lchown() use chown() */
 #ifndef HAVE_LCHOWN
@@ -49,23 +61,28 @@ HANDLE bget_handle(BFILE *bfd);
 /*                                                             */
 /*=============================================================*/
 
-/*
+/**
  * Return the data stream that will be used
  */
 int select_data_stream(FF_PKT *ff_pkt)
 {
    int stream;
 
-   /*
+   /* This is a plugin special restore object */
+   if (ff_pkt->type == FT_RESTORE_FIRST) {
+      ff_pkt->flags = 0;
+      return STREAM_FILE_DATA;
+   }
+
+   /**
     *  Fix all incompatible options
     */
-
-   /* No sparse option for encrypted data */
+   /** No sparse option for encrypted data */
    if (ff_pkt->flags & FO_ENCRYPT) {
       ff_pkt->flags &= ~FO_SPARSE;
    }
 
-   /* Note, no sparse option for win32_data */
+   /** Note, no sparse option for win32_data */
    if (!is_portable_backup(&ff_pkt->bfd)) {
       stream = STREAM_WIN32_DATA;
       ff_pkt->flags &= ~FO_SPARSE;
@@ -75,18 +92,18 @@ int select_data_stream(FF_PKT *ff_pkt)
       stream = STREAM_FILE_DATA;
    }
 
-   /* Encryption is only supported for file data */
+   /** Encryption is only supported for file data */
    if (stream != STREAM_FILE_DATA && stream != STREAM_WIN32_DATA &&
          stream != STREAM_MACOS_FORK_DATA) {
       ff_pkt->flags &= ~FO_ENCRYPT;
    }
 
-   /* Compression is not supported for Mac fork data */
+   /** Compression is not supported for Mac fork data */
    if (stream == STREAM_MACOS_FORK_DATA) {
       ff_pkt->flags &= ~FO_GZIP;
    }
 
-   /*
+   /**
     * Handle compression and encryption options
     */
 #ifdef HAVE_LIBZ
@@ -102,8 +119,10 @@ int select_data_stream(FF_PKT *ff_pkt)
          stream = STREAM_GZIP_DATA;
          break;
       default:
-         /* All stream types that do not support gzip should clear out
-          * FO_GZIP above, and this code block should be unreachable. */
+         /**
+          * All stream types that do not support gzip should clear out
+          * FO_GZIP above, and this code block should be unreachable.
+          */
          ASSERT(!(ff_pkt->flags & FO_GZIP));
          return STREAM_NONE;
       }
@@ -127,7 +146,7 @@ int select_data_stream(FF_PKT *ff_pkt)
       default:
          /* All stream types that do not support encryption should clear out
           * FO_ENCRYPT above, and this code block should be unreachable. */
-         ASSERT(!ff_pkt->flags & FO_ENCRYPT);
+         ASSERT(!(ff_pkt->flags & FO_ENCRYPT));
          return STREAM_NONE;
       }
    }
@@ -137,7 +156,7 @@ int select_data_stream(FF_PKT *ff_pkt)
 }
 
 
-/*
+/**
  * 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
@@ -148,11 +167,11 @@ int select_data_stream(FF_PKT *ff_pkt)
  *   them in the encode_attribsEx() subroutine, but this is
  *   not recommended.
  */
-void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream)
+void encode_stat(char *buf, struct stat *statp, int32_t LinkFI, int data_stream)
 {
    char *p = buf;
-   struct stat *statp = &ff_pkt->statp;
-   /*
+
+   /**
     *  Encode a stat packet.  I should have done this more intelligently
     *   with a length so that it could be easily expanded.
     */
@@ -189,7 +208,7 @@ void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream)
    *p++ = ' ';
    p += to_base64((int64_t)statp->st_ctime, p);
    *p++ = ' ';
-   p += to_base64((int64_t)ff_pkt->LinkFI, p);
+   p += to_base64((int64_t)LinkFI, p);
    *p++ = ' ';
 
 #ifdef HAVE_CHFLAGS
@@ -212,6 +231,8 @@ void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream)
   #if !HAVE_GCC & HAVE_SUN_OS
     /* Sun compiler does not handle templates correctly */
     #define plug(st, val) st = val
+  #elif __sgi
+    #define plug(st, val) st = val
   #else
     /* Use templates to do the casting */
     template <class T> void plug(T &st, uint64_t val)
@@ -219,7 +240,8 @@ void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream)
   #endif
 #endif
 
-/* Decode a stat packet from base64 characters */
+
+/** Decode a stat packet from base64 characters */
 int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI)
 {
    char *p = buf;
@@ -304,7 +326,7 @@ int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI)
    return (int)val;
 }
 
-/* Decode a LinkFI field of encoded stat packet */
+/** Decode a LinkFI field of encoded stat packet */
 int32_t decode_LinkFI(char *buf, struct stat *statp)
 {
    char *p = buf;
@@ -346,7 +368,7 @@ int32_t decode_LinkFI(char *buf, struct stat *statp)
    return 0;
 }
 
-/*
+/**
  * Set file modes, permissions and times
  *
  *  fname is the original filename
@@ -360,9 +382,15 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    struct utimbuf ut;
    mode_t old_mask;
    bool ok = true;
-   off_t fsize;
+   boffset_t fsize;
+   if (uid_set) {
+      my_uid = getuid();
+      my_gid = getgid();
+      uid_set = true;
+   }
 
-#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
+#if defined(HAVE_WIN32)
    if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX &&
        set_win32_attributes(jcr, attr, ofd)) {
        if (is_bopen(ofd)) {
@@ -381,7 +409,7 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    }
 
 
-   /*
+   /**
     * If Windows stuff failed, e.g. attempt to restore Unix file
     *  to Windows, simply fall through and we will do it the
     *  universal way.
@@ -393,68 +421,79 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
       char ec1[50], ec2[50];
       fsize = blseek(ofd, 0, SEEK_END);
       bclose(ofd);                    /* first close file */
-      if (fsize > 0 && fsize != (off_t)attr->statp.st_size) {
+      if (attr->type == FT_REG && fsize > 0 && attr->statp.st_size > 0 && 
+                        fsize != (boffset_t)attr->statp.st_size) {
          Jmsg3(jcr, M_ERROR, 0, _("File size of restored file %s not correct. Original %s, restored %s.\n"),
             attr->ofname, edit_uint64(attr->statp.st_size, ec1),
             edit_uint64(fsize, ec2));
       }
    }
 
+   /**
+    * We do not restore sockets, so skip trying to restore their
+    *   attributes.
+    */
+   if (attr->type == FT_SPEC && S_ISSOCK(attr->statp.st_mode)) {
+      goto bail_out;
+   }
+
    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 (attr->type == FT_LNK) {
-      /* Change owner of link, not of real file */
-      if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
+      /** Change owner of link, not of real file */
+      if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) {
          berrno be;
          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
-            attr->ofname, be.strerror());
+            attr->ofname, be.bstrerror());
          ok = false;
       }
    } else {
-      if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
+      if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) {
          berrno be;
          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
-            attr->ofname, be.strerror());
+            attr->ofname, be.bstrerror());
          ok = false;
       }
-      if (chmod(attr->ofname, attr->statp.st_mode) < 0) {
+      if (chmod(attr->ofname, attr->statp.st_mode) < 0 && my_uid == 0) {
          berrno be;
          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"),
-            attr->ofname, be.strerror());
+            attr->ofname, be.bstrerror());
          ok = false;
       }
 
-      /*
+      /**
        * Reset file times.
        */
-      if (utime(attr->ofname, &ut) < 0) {
+      if (utime(attr->ofname, &ut) < 0 && my_uid == 0) {
          berrno be;
          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"),
-            attr->ofname, be.strerror());
+            attr->ofname, be.bstrerror());
          ok = false;
       }
 #ifdef HAVE_CHFLAGS
-      /*
+      /**
        * FreeBSD user flags
        *
        * Note, this should really be done before the utime() above,
        *  but if the immutable bit is set, it will make the utimes()
        *  fail.
        */
-      if (chflags(attr->ofname, attr->statp.st_flags) < 0) {
+      if (chflags(attr->ofname, attr->statp.st_flags) < 0 && my_uid == 0) {
          berrno be;
          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"),
-            attr->ofname, be.strerror());
+            attr->ofname, be.bstrerror());
          ok = false;
       }
 #endif
    }
+
+bail_out:
    pm_strcpy(attr->ofname, "*none*");
    umask(old_mask);
    return ok;
@@ -467,9 +506,9 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
 /*                                                             */
 /*=============================================================*/
 
-#if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
+#if !defined(HAVE_WIN32)
 
-/*
+/**
  * 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
@@ -481,11 +520,16 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 {
 #ifdef HAVE_DARWIN_OS
-   /*
+   /**
     * We save the Mac resource fork length so that on a
     * restore, we can be sure we put back the whole resource.
     */
    char *p;
+
+   *attribsEx = 0;                 /* no extended attributes (yet) */
+   if (jcr->cmd_plugin || ff_pkt->type == FT_DELETED) {
+      return STREAM_UNIX_ATTRIBUTES;
+   }
    p = attribsEx;
    if (ff_pkt->flags & FO_HFSPLUS) {
       p += to_base64((uint64_t)(ff_pkt->hfsinfo.rsrclength), p);
@@ -507,7 +551,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 /*                                                             */
 /*=============================================================*/
 
-#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
+#if defined(HAVE_WIN32)
 
 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 {
@@ -517,14 +561,19 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 
    attribsEx[0] = 0;                  /* no extended attributes */
 
+   if (jcr->cmd_plugin || ff_pkt->type == FT_DELETED) {
+      return STREAM_UNIX_ATTRIBUTES;
+   }
+
    unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
 
-   // try unicode version
+   /** try unicode version */
    if (p_GetFileAttributesExW)  {
-      POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);   
+      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);   
       make_win32_path_UTF8_2_wchar(&pwszBuf, ff_pkt->fname);
 
-      BOOL b=p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, (LPVOID)&atts);
+      BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard, 
+                                    (LPVOID)&atts);
       free_pool_memory(pwszBuf);
 
       if (!b) {
@@ -564,7 +613,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
    return STREAM_UNIX_ATTRIBUTES_EX;
 }
 
-/* Define attributes that are legal to set with SetFileAttributes() */
+/** Define attributes that are legal to set with SetFileAttributes() */
 #define SET_ATTRS ( \
          FILE_ATTRIBUTE_ARCHIVE| \
          FILE_ATTRIBUTE_HIDDEN| \
@@ -576,7 +625,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
          FILE_ATTRIBUTE_TEMPORARY)
 
 
-/*
+/**
  * Set Extended File Attributes for Win32
  *
  *  fname is the original filename
@@ -593,9 +642,10 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    ULARGE_INTEGER li;
    POOLMEM *win32_ofile;
 
-   // if we have neither ansi nor wchar version, we leave
-   if (!(p_SetFileAttributesW || p_SetFileAttributesA))
+   /** if we have neither Win ansi nor wchar API, get out */
+   if (!(p_SetFileAttributesW || p_SetFileAttributesA)) {
       return false;
+   }
 
    if (!p || !*p) {                   /* we should have attributes */
       Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid);
@@ -631,11 +681,11 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    p += from_base64(&val, p);
    plug(atts.nFileSizeLow, val);
 
-   /* Convert to Windows path format */
+   /** Convert to Windows path format */
    win32_ofile = get_pool_memory(PM_FNAME);
    unix_name_to_win32(&win32_ofile, attr->ofname);
 
-   /* At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */
+   /** At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */
 
    if (!is_bopen(ofd)) {
       Dmsg1(100, "File not open: %s\n", attr->ofname);
@@ -654,10 +704,9 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    }
 
    Dmsg1(100, "SetFileAtts %s\n", attr->ofname);
-   if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
-   {
+   if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
       if (p_SetFileAttributesW) {
-         POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);   
+         POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);   
          make_win32_path_UTF8_2_wchar(&pwszBuf, attr->ofname);
 
          BOOL b=p_SetFileAttributesW((LPCWSTR)pwszBuf, atts.dwFileAttributes & SET_ATTRS);
@@ -676,7 +725,7 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    return true;
 }
 
-void win_error(JCR *jcr, char *prefix, POOLMEM *win32_ofile)
+void win_error(JCR *jcr, const char *prefix, POOLMEM *win32_ofile)
 {
    DWORD lerror = GetLastError();
    LPTSTR msg;
@@ -690,11 +739,11 @@ void win_error(JCR *jcr, char *prefix, POOLMEM *win32_ofile)
                  NULL);
    Dmsg3(100, "Error in %s on file %s: ERR=%s\n", prefix, win32_ofile, msg);
    strip_trailing_junk(msg);
-   Jmsg(jcr, M_ERROR, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg);
+   Jmsg3(jcr, M_ERROR, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg);
    LocalFree(msg);
 }
 
-void win_error(JCR *jcr, char *prefix, DWORD lerror)
+void win_error(JCR *jcr, const char *prefix, DWORD lerror)
 {
    LPTSTR msg;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
@@ -713,17 +762,4 @@ void win_error(JCR *jcr, char *prefix, DWORD lerror)
    }
    LocalFree(msg);
 }
-
-
-/* Conversion of a Unix filename to a Win32 filename */
-extern void conv_unix_to_win32_path(const char *path, char *win32_path, DWORD dwSize);
-void unix_name_to_win32(POOLMEM **win32_name, char *name)
-{
-   /* One extra byte should suffice, but we double it */
-   /* add MAX_PATH bytes for VSS shadow copy name */
-   DWORD dwSize = 2*strlen(name)+MAX_PATH;
-   *win32_name = check_pool_memory_size(*win32_name, dwSize);
-   conv_unix_to_win32_path(name, *win32_name, dwSize);
-}
-
-#endif  /* HAVE_CYGWIN */
+#endif  /* HAVE_WIN32 */