]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/findlib/attribs.c
Tweak fix MySQL quoting again :-(
[bacula/bacula] / bacula / src / findlib / attribs.c
index 9a2fa235b7763df51571de6dbc6ae47435c840fa..6bbfb0a7852271e5e379242dd66dcf2c995b6d20 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+   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 two of the GNU General Public
+   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.
 
    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
+   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 John Walker.
+   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$
- *
  */
 
 #include "bacula.h"
 #include "find.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 /* HAVE_WIN32 */
 
@@ -58,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;
@@ -84,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
@@ -111,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;
       }
@@ -146,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
@@ -157,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.
     */
@@ -198,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
@@ -221,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)
@@ -229,7 +241,7 @@ void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream)
 #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;
@@ -314,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;
@@ -356,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
@@ -371,6 +383,12 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    mode_t old_mask;
    bool ok = true;
    boffset_t fsize;
+   if (uid_set) {
+      my_uid = getuid();
+      my_gid = getgid();
+      uid_set = true;
+   }
 
 #if defined(HAVE_WIN32)
    if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX &&
@@ -391,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.
@@ -411,7 +429,7 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
       }
    }
 
-   /*
+   /**
     * We do not restore sockets, so skip trying to restore their
     *   attributes.
     */
@@ -423,50 +441,50 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    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.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.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.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.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.bstrerror());
@@ -490,7 +508,7 @@ bail_out:
 
 #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
@@ -502,11 +520,16 @@ bail_out:
 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);
@@ -538,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) {
@@ -585,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| \
@@ -597,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
@@ -614,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);
@@ -652,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);
@@ -675,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);
@@ -697,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;
@@ -711,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|