LCOV - code coverage report
Current view: top level - src - attribs.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 128 148 86.5 %
Date: 2016-07-31 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*
       2             :    Bacula® - The Network Backup Solution
       3             : 
       4             :    Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
       5             : 
       6             :    The main author of Bacula is Kern Sibbald, with contributions from
       7             :    many others, a complete list can be found in the file AUTHORS.
       8             :    This program is Free Software; you can redistribute it and/or
       9             :    modify it under the terms of version three of the GNU Affero General Public
      10             :    License as published by the Free Software Foundation and included
      11             :    in the file LICENSE.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU Affero General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             :    Bacula® is a registered trademark of Kern Sibbald.
      24             :    The licensor of Bacula is the Free Software Foundation Europe
      25             :    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
      26             :    Switzerland, email:ftf@fsfeurope.org.
      27             : */
      28             : /*
      29             :  *  Encode and decode standard Unix attributes and
      30             :  *   Extended attributes for Win32 and
      31             :  *   other non-Unix systems, ...
      32             :  */
      33             : /*
      34             :  *  Some of these functions come from src/findlib/attribs.c in bacula-5.0.3.
      35             :  *  Hence, the copyright notice above is retained.
      36             :  *   Graham Keeling, 2014
      37             :  */
      38             : 
      39             : #include "burp.h"
      40             : #include "attribs.h"
      41             : #include "alloc.h"
      42             : #include "base64.h"
      43             : #include "berrno.h"
      44             : #include "cmd.h"
      45             : #include "cntr.h"
      46             : #include "log.h"
      47             : #include "sbuf.h"
      48             : 
      49             : // Encode a stat structure into a base64 character string.
      50       95378 : int attribs_encode(struct sbuf *sb)
      51             : {
      52             :         static char *p;
      53             :         static struct stat *statp;
      54             : 
      55       95378 :         if(!sb->attr.buf)
      56             :         {
      57       95247 :                 sb->attr.cmd=CMD_ATTRIBS; // should not be needed
      58       95247 :                 if(!(sb->attr.buf=(char *)malloc_w(256, __func__)))
      59             :                         return -1;
      60             :         }
      61       95378 :         p=sb->attr.buf;
      62       95378 :         statp=&sb->statp;
      63             : 
      64       95378 :         if(sb->protocol2)
      65             :         {
      66             :                 // Protocol1 does not have this field.
      67       73444 :                 p += to_base64(sb->protocol2->index, p);
      68       73444 :                 *p++ = ' ';
      69             :                 // Protocol2 puts compression near the beginning.
      70       73444 :                 p += to_base64(sb->compression, p);
      71       73444 :                 *p++ = ' ';
      72             :                 // Protocol1 does not have this field.
      73       73444 :                 p += to_base64(sb->protocol2->encryption, p);
      74       73444 :                 *p++ = ' ';
      75             :         }
      76       95378 :         p += to_base64(statp->st_dev, p);
      77       95378 :         *p++ = ' ';
      78       95378 :         p += to_base64(statp->st_ino, p);
      79       95378 :         *p++ = ' ';
      80       95378 :         p += to_base64(statp->st_mode, p);
      81       95378 :         *p++ = ' ';
      82       95378 :         p += to_base64(statp->st_nlink, p);
      83       95378 :         *p++ = ' ';
      84       95378 :         p += to_base64(statp->st_uid, p);
      85       95378 :         *p++ = ' ';
      86       95378 :         p += to_base64(statp->st_gid, p);
      87       95378 :         *p++ = ' ';
      88       95378 :         p += to_base64(statp->st_rdev, p);
      89       95378 :         *p++ = ' ';
      90       95378 :         p += to_base64(statp->st_size, p);
      91       95378 :         *p++ = ' ';
      92             : #ifdef HAVE_WIN32
      93             :         p += to_base64(0, p); // place holder
      94             :         *p++ = ' ';
      95             :         p += to_base64(0, p); // place holder
      96             : #else
      97       95378 :         p += to_base64(statp->st_blksize, p);
      98       95378 :         *p++ = ' ';
      99       95378 :         p += to_base64(statp->st_blocks, p);
     100             : #endif
     101       95378 :         *p++ = ' ';
     102       95378 :         p += to_base64(statp->st_atime, p);
     103       95378 :         *p++ = ' ';
     104       95378 :         p += to_base64(statp->st_mtime, p);
     105       95378 :         *p++ = ' ';
     106       95378 :         p += to_base64(statp->st_ctime, p);
     107       95378 :         *p++ = ' ';
     108             : 
     109             : #ifdef HAVE_CHFLAGS
     110             :         // chflags is a FreeBSD function.
     111             :         p += to_base64(statp->st_flags, p);
     112             : #else
     113       95378 :         p += to_base64(0, p); // place holder
     114             : #endif
     115       95378 :         *p++ = ' ';
     116             : 
     117       95378 :         p += to_base64(sb->winattr, p);
     118             : 
     119       95378 :         if(sb->protocol1)
     120             :         {
     121             :                 // Protocol1 puts compression at the end.
     122       21934 :                 *p++ = ' ';
     123       21934 :                 p += to_base64(sb->compression, p);
     124             :         }
     125             : 
     126       95378 :         *p = 0;
     127             : 
     128       95378 :         sb->attr.len=p-sb->attr.buf;
     129             : 
     130       95378 :         return 0;
     131             : }
     132             : 
     133             : // Do casting according to unknown type to keep compiler happy.
     134             : #ifdef HAVE_TYPEOF
     135             :         #define plug(st, val) st = (typeof st)val
     136             : #else
     137             :         #if !HAVE_GCC & HAVE_SUN_OS
     138             :                 // Sun compiler does not handle templates correctly.
     139             :                 #define plug(st, val) st = val
     140             :         #elif __sgi
     141             :                 #define plug(st, val) st = val
     142             :         #else
     143             :                 // Use templates to do the casting.
     144             :                 template <class T> void plug(T &st, uint64_t val)
     145             :                 { st = static_cast<T>(val); }
     146             :         #endif
     147             : #endif
     148             : 
     149             : // Decode a stat packet from base64 characters.
     150       80758 : void attribs_decode(struct sbuf *sb)
     151             : {
     152             :         static const char *p;
     153             :         static int64_t val;
     154             :         static struct stat *statp;
     155             : 
     156       80758 :         if(!(p=sb->attr.buf)) return;
     157       80758 :         statp=&sb->statp;
     158             : 
     159       80758 :         if(sb->protocol2)
     160             :         {
     161             :                 // Protocol1 does not have this field.
     162       57093 :                 p += from_base64(&val, p);
     163       57093 :                 sb->protocol2->index=val;
     164       57093 :                 p++;
     165             :                 // Compression for protocol2.
     166       57093 :                 p += from_base64(&val, p);
     167       57093 :                 sb->compression=val;
     168       57093 :                 p++;
     169             :                 // Protocol1 does not have this field.
     170       57093 :                 p += from_base64(&val, p);
     171       57093 :                 sb->protocol2->encryption=val;
     172       57093 :                 p++;
     173             :         }
     174       80758 :         p += from_base64(&val, p);
     175       80758 :         plug(statp->st_dev, val);
     176       80758 :         p++;
     177       80758 :         p += from_base64(&val, p);
     178       80758 :         plug(statp->st_ino, val);
     179       80758 :         p++;
     180       80758 :         p += from_base64(&val, p);
     181       80758 :         plug(statp->st_mode, val);
     182       80758 :         p++;
     183       80758 :         p += from_base64(&val, p);
     184       80758 :         plug(statp->st_nlink, val);
     185       80758 :         p++;
     186       80758 :         p += from_base64(&val, p);
     187       80758 :         plug(statp->st_uid, val);
     188       80758 :         p++;
     189       80758 :         p += from_base64(&val, p);
     190       80758 :         plug(statp->st_gid, val);
     191       80758 :         p++;
     192       80758 :         p += from_base64(&val, p);
     193       80758 :         plug(statp->st_rdev, val);
     194       80758 :         p++;
     195       80758 :         p += from_base64(&val, p);
     196       80758 :         plug(statp->st_size, val);
     197       80758 :         p++;
     198       80758 :         p += from_base64(&val, p);
     199             : #ifdef HAVE_WIN32
     200             :         //   plug(statp->st_blksize, val);
     201             :         p++;
     202             :         p += from_base64(&val, p);
     203             :         //   plug(statp->st_blocks, val);
     204             : #else
     205       80758 :         plug(statp->st_blksize, val);
     206       80758 :         p++;
     207       80758 :         p += from_base64(&val, p);
     208       80758 :         plug(statp->st_blocks, val);
     209             : #endif
     210       80758 :         p++;
     211       80758 :         p += from_base64(&val, p);
     212       80758 :         plug(statp->st_atime, val);
     213       80758 :         p++;
     214       80758 :         p += from_base64(&val, p);
     215       80758 :         plug(statp->st_mtime, val);
     216       80758 :         p++;
     217       80758 :         p += from_base64(&val, p);
     218       80758 :         plug(statp->st_ctime, val);
     219             : 
     220             :         // FreeBSD user flags.
     221       80758 :         if(*p == ' ' || (*p != 0 && *(p+1) == ' '))
     222             :         {
     223       80740 :                 p++;
     224       80740 :                 if(!*p) return;
     225       80739 :                 p += from_base64(&val, p);
     226             : #ifdef HAVE_CHFLAGS
     227             :                 plug(statp->st_flags, val);
     228             :         }
     229             :         else
     230             :         {
     231             :                 statp->st_flags  = 0;
     232             : #endif
     233             :         }
     234             : 
     235             :         // Look for winattr.
     236       80757 :         if(*p == ' ' || (*p != 0 && *(p+1) == ' '))
     237             :         {
     238       80739 :                 p++;
     239       80739 :                 p += from_base64(&val, p);
     240             :         }
     241             :         else
     242          18 :                 val = 0;
     243       80757 :         sb->winattr=val;
     244             : 
     245             :         // Compression for protocol1.
     246       80757 :         if(sb->protocol1)
     247             :         {
     248       23664 :                 if(*p == ' ' || (*p != 0 && *(p+1) == ' '))
     249             :                 {
     250       23656 :                         p++;
     251       23656 :                         if(!*p) return;
     252       23656 :                         p += from_base64(&val, p);
     253       23656 :                         sb->compression=val;
     254             :                 }
     255             :                 else
     256           8 :                         sb->compression=-1;
     257             :         }
     258             : }
     259             : 
     260          28 : static int set_file_times(struct asfd *asfd,
     261             :         const char *path, struct utimbuf *ut,
     262             :         struct stat *statp, struct cntr *cntr)
     263             : {
     264             :         int e;
     265             : // The mingw64 utime() appears not to work on read-only files.
     266             : // Use the utime() from bacula instead.
     267             : #ifdef HAVE_WIN32
     268             :         //e=utime(path, ut);
     269             :         e=win32_utime(path, ut);
     270             : #else
     271          28 :         e=utime(path, ut);
     272             : #endif
     273          28 :         if(e<0)
     274             :         {
     275             :                 berrno be;
     276           0 :                 berrno_init(&be);
     277             :                 logw(asfd, cntr, "Unable to set file times %s: ERR=%s\n",
     278           0 :                         path, berrno_bstrerror(&be, errno));
     279             :                 return -1;
     280             :         }
     281             :         return 0;
     282             : }
     283             : 
     284       17034 : uint64_t decode_file_no(struct iobuf *iobuf)
     285             : {
     286             :         int64_t val;
     287       17034 :         from_base64(&val, iobuf->buf);
     288       17034 :         return (uint64_t)val;
     289             : }
     290             : 
     291           0 : uint64_t decode_file_no_and_save_path(struct iobuf *iobuf, char **save_path)
     292             : {
     293             :         int64_t val;
     294           0 :         char *p=iobuf->buf;
     295           0 :         p+=from_base64(&val, iobuf->buf);
     296           0 :         *save_path=p+1;
     297           0 :         return (uint64_t)val;
     298             : }
     299             : 
     300             : #ifdef HAVE_LUTIMES
     301             : static int do_lutimes(const char *path, struct stat *statp)
     302             : {
     303             :         struct timeval t[2];
     304           0 :         t[0].tv_sec = statp->st_atime;
     305           0 :         t[0].tv_usec = 0;
     306           0 :         t[1].tv_sec = statp->st_mtime;
     307           0 :         t[1].tv_usec = 0;
     308           0 :         return lutimes(path, t);
     309             : }
     310             : #endif
     311             : 
     312          28 : int attribs_set(struct asfd *asfd, const char *path,
     313           0 :         struct stat *statp, uint64_t winattr, struct cntr *cntr)
     314             : {
     315             :         struct utimbuf ut;
     316             : 
     317          28 :         ut.actime=statp->st_atime;
     318          28 :         ut.modtime=statp->st_mtime;
     319             : 
     320             : #ifdef HAVE_WIN32
     321             :         win32_chmod(path, statp->st_mode, winattr);
     322             :         set_file_times(asfd, path, &ut, statp, cntr);
     323             :         return 0;
     324             : #endif
     325             : 
     326          28 :         if(lchown(path, statp->st_uid, statp->st_gid)<0)
     327             :         {
     328             :                 berrno be;
     329           0 :                 berrno_init(&be);
     330             :                 logw(asfd, cntr,
     331             :                         "Unable to set file owner of %s to %d:%d: ERR=%s\n",
     332             :                         path, statp->st_uid, statp->st_gid,
     333           0 :                         berrno_bstrerror(&be, errno));
     334             :                 return -1;
     335             :         }
     336             : 
     337             :         /* Watch out, a metadata restore will have cmd set to CMD_METADATA or
     338             :            CMD_ENC_META, but that is OK at the moment because we are not doing
     339             :            meta stuff on links. */
     340          28 :         if(S_ISLNK(statp->st_mode))
     341             :         {
     342             : #ifdef HAVE_LUTIMES
     343           0 :                 if(do_lutimes(path, statp)) {
     344             :                         berrno be;
     345           0 :                         berrno_init(&be);
     346             :                         logw(asfd, cntr, "Unable to set lutimes %s: ERR=%s\n",
     347           0 :                                 path, berrno_bstrerror(&be, errno));
     348             :                         return -1;
     349             :                 }
     350             : #endif
     351             :         }
     352             :         else
     353             :         {
     354          28 :                 if(chmod(path, statp->st_mode) < 0)
     355             :                 {
     356             :                         berrno be;
     357           0 :                         berrno_init(&be);
     358             :                         logw(asfd, cntr,
     359             :                                 "Unable to set file modes %s: ERR=%s\n",
     360           0 :                                 path, berrno_bstrerror(&be, errno));
     361             :                         return -1;
     362             :                 }
     363             : 
     364          28 :                 if(set_file_times(asfd, path, &ut, statp, cntr))
     365             :                         return -1;
     366             : #ifdef HAVE_CHFLAGS
     367             :                 /*
     368             :                  * FreeBSD user flags
     369             :                  *
     370             :                  * Note, this should really be done before the utime() above,
     371             :                  *  but if the immutable bit is set, it will make the utimes()
     372             :                  *  fail.
     373             :                  */
     374             :                 if(chflags(path, statp->st_flags)<0)
     375             :                 {
     376             :                         berrno be;
     377             :                         berrno_init(&be);
     378             :                         logw(asfd, cntr,
     379             :                                 "Unable to set file flags %s: ERR=%s\n",
     380             :                                 path, berrno_bstrerror(&be, errno));
     381             :                         return -1;
     382             :                 }
     383             : #endif
     384             :         }
     385             : 
     386             :         return 0;
     387             : }

Generated by: LCOV version 1.10