LCOV - code coverage report
Current view: top level - src - attribs.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 120 148 81.1 %
Date: 2022-12-03 01:09:05 Functions: 4 6 66.7 %

          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       21955 : int attribs_encode(struct sbuf *sb)
      51             : {
      52             :         static char *p;
      53             :         static struct stat *statp;
      54             : 
      55       21955 :         if(!sb->attr.buf)
      56             :         {
      57       21901 :                 sb->attr.cmd=CMD_ATTRIBS; // should not be needed
      58       21901 :                 if(!(sb->attr.buf=(char *)malloc_w(256, __func__)))
      59             :                         return -1;
      60             :         }
      61       21955 :         p=sb->attr.buf;
      62       21955 :         statp=&sb->statp;
      63             : 
      64       21955 :         p += to_base64(statp->st_dev, p);
      65       21955 :         *p++ = ' ';
      66       21955 :         p += to_base64(statp->st_ino, p);
      67       21955 :         *p++ = ' ';
      68       21955 :         p += to_base64(statp->st_mode, p);
      69       21955 :         *p++ = ' ';
      70       21955 :         p += to_base64(statp->st_nlink, p);
      71       21955 :         *p++ = ' ';
      72       21955 :         p += to_base64(statp->st_uid, p);
      73       21955 :         *p++ = ' ';
      74       21955 :         p += to_base64(statp->st_gid, p);
      75       21955 :         *p++ = ' ';
      76       21955 :         p += to_base64(statp->st_rdev, p);
      77       21955 :         *p++ = ' ';
      78       21955 :         p += to_base64(statp->st_size, p);
      79       21955 :         *p++ = ' ';
      80             : #ifdef HAVE_WIN32
      81             :         p += to_base64(0, p); // place holder
      82             :         *p++ = ' ';
      83             :         p += to_base64(0, p); // place holder
      84             : #else
      85       21955 :         p += to_base64(statp->st_blksize, p);
      86       21955 :         *p++ = ' ';
      87       21955 :         p += to_base64(statp->st_blocks, p);
      88             : #endif
      89       21955 :         *p++ = ' ';
      90       21955 :         p += to_base64(statp->st_atime, p);
      91       21955 :         *p++ = ' ';
      92       21955 :         p += to_base64(statp->st_mtime, p);
      93       21955 :         *p++ = ' ';
      94       21955 :         p += to_base64(statp->st_ctime, p);
      95       21955 :         *p++ = ' ';
      96             : 
      97             : #ifdef HAVE_CHFLAGS
      98             :         // chflags is a FreeBSD function.
      99             :         p += to_base64(statp->st_flags, p);
     100             : #else
     101       21955 :         p += to_base64(0, p); // place holder
     102             : #endif
     103       21955 :         *p++ = ' ';
     104             : 
     105       21955 :         p += to_base64(sb->winattr, p);
     106             : 
     107       21955 :         *p++ = ' ';
     108       21955 :         p += to_base64(sb->compression, p);
     109       21955 :         *p++ = ' ';
     110       21955 :         p += to_base64(sb->encryption, p);
     111       21955 :         *p++ = ' ';
     112       21955 :         p += to_base64(sb->salt, p);
     113       21955 :         *p++ = ' ';
     114             :         // 0 means winapi is enabled, 1 means it is disabled.
     115       21955 :         p += to_base64(!sb->use_winapi, p);
     116       21955 :         *p = 0;
     117             : 
     118       21955 :         sb->attr.len=p-sb->attr.buf;
     119             : 
     120       21955 :         return 0;
     121             : }
     122             : 
     123             : // Do casting according to unknown type to keep compiler happy.
     124             : #define plug(st, val) st = (__typeof__(st))(val)
     125             : 
     126             : // Decode a stat packet from base64 characters.
     127       23686 : void attribs_decode(struct sbuf *sb)
     128             : {
     129             :         static const char *p;
     130             :         static int64_t val;
     131             :         static struct stat *statp;
     132             :         static int eaten;
     133             : 
     134       23686 :         if(!(p=sb->attr.buf)) return;
     135       23686 :         statp=&sb->statp;
     136             : 
     137       23686 :         if(!(eaten=from_base64(&val, p)))
     138             :                 return;
     139       23686 :         p+=eaten;
     140       23686 :         plug(statp->st_dev, val);
     141             : 
     142       23686 :         if(!(eaten=from_base64(&val, p)))
     143             :                 return;
     144       23685 :         p+=eaten;
     145       23685 :         plug(statp->st_ino, val);
     146             : 
     147       23685 :         if(!(eaten=from_base64(&val, p)))
     148             :                 return;
     149       23676 :         p+=eaten;
     150       23676 :         plug(statp->st_mode, val);
     151             : 
     152       23676 :         if(!(eaten=from_base64(&val, p)))
     153             :                 return;
     154       23676 :         p+=eaten;
     155       23676 :         plug(statp->st_nlink, val);
     156             : 
     157       23676 :         if(!(eaten=from_base64(&val, p)))
     158             :                 return;
     159       23676 :         p+=eaten;
     160       23676 :         plug(statp->st_uid, val);
     161             : 
     162       23676 :         if(!(eaten=from_base64(&val, p)))
     163             :                 return;
     164       23676 :         p+=eaten;
     165       23676 :         plug(statp->st_gid, val);
     166             : 
     167       23676 :         if(!(eaten=from_base64(&val, p)))
     168             :                 return;
     169       23676 :         p+=eaten;
     170       23676 :         plug(statp->st_rdev, val);
     171             : 
     172       23676 :         if(!(eaten=from_base64(&val, p)))
     173             :                 return;
     174       23676 :         p+=eaten;
     175       23676 :         plug(statp->st_size, val);
     176             : 
     177       23676 :         if(!(eaten=from_base64(&val, p)))
     178             :                 return;
     179       23676 :         p+=eaten;
     180             : #ifdef HAVE_WIN32
     181             :         //   plug(statp->st_blksize, val);
     182             : 
     183             :         if(!(eaten=from_base64(&val, p)))
     184             :                 return;
     185             :         p+=eaten;
     186             :         //   plug(statp->st_blocks, val);
     187             : #else
     188       23676 :         plug(statp->st_blksize, val);
     189             : 
     190       23676 :         if(!(eaten=from_base64(&val, p)))
     191             :                 return;
     192       23676 :         p+=eaten;
     193       23676 :         plug(statp->st_blocks, val);
     194             : #endif
     195             : 
     196       23676 :         if(!(eaten=from_base64(&val, p)))
     197             :                 return;
     198       23676 :         p+=eaten;
     199       23676 :         plug(statp->st_atime, val);
     200             : 
     201       23676 :         if(!(eaten=from_base64(&val, p)))
     202             :                 return;
     203       23676 :         p+=eaten;
     204       23676 :         plug(statp->st_mtime, val);
     205             : 
     206       23676 :         if(!(eaten=from_base64(&val, p)))
     207             :                 return;
     208       23676 :         p+=eaten;
     209       23676 :         plug(statp->st_ctime, val);
     210             : 
     211             :         // FreeBSD user flags.
     212       23676 :         if(!(eaten=from_base64(&val, p)))
     213             :                 return;
     214       23676 :         p+=eaten;
     215             : #ifdef HAVE_CHFLAGS
     216             :         statp->st_flags=0;
     217             :         plug(statp->st_flags, val);
     218             : #endif
     219             : 
     220             :         // Look for winattr.
     221       23676 :         sb->winattr=0;
     222       23676 :         if(!(eaten=from_base64(&val, p)))
     223             :                 return;
     224       23676 :         p+=eaten;
     225       23676 :         sb->winattr=val;
     226             : 
     227       23676 :         sb->compression=-1;
     228       23676 :         sb->encryption=ENCRYPTION_UNSET;
     229             : 
     230       23676 :         if(!(eaten=from_base64(&val, p)))
     231             :                 return;
     232       23676 :         p+=eaten;
     233       23676 :         sb->compression=val;
     234             : 
     235       23676 :         if(!(eaten=from_base64(&val, p)))
     236             :                 return;
     237       23676 :         p+=eaten;
     238       23676 :         sb->encryption=val;
     239             : 
     240       23676 :         if(!(eaten=from_base64(&val, p)))
     241             :                 return;
     242       23676 :         p+=eaten;
     243       23676 :         sb->salt=val;
     244             : 
     245       23676 :         if(!(eaten=from_base64(&val, p)))
     246             :                 return;
     247       23676 :         p+=eaten;
     248             :         // 0 means winapi is enabled, 1 means it is disabled.
     249       23676 :         sb->use_winapi=!val;
     250             : }
     251             : 
     252          12 : int attribs_set_file_times(struct asfd *asfd,
     253             :         const char *path, struct stat *statp,
     254             :         struct cntr *cntr)
     255             : {
     256             :         int e;
     257             : 
     258             : #ifdef HAVE_WIN32
     259             :         // You (probably) cannot set times on Windows junction points.
     260             :         if(statp->st_rdev==WIN32_JUNCTION_POINT)
     261             :                 return 0;
     262             : 
     263             :         // The mingw64 utime() appears not to work on read-only files.
     264             :         // Use the utime() from bacula instead.
     265             :         e=win32_utime(path, statp);
     266             : #elif HAVE_LUTIMES
     267             :         struct timeval t[2];
     268          12 :         t[0].tv_sec = statp->st_atime;
     269          12 :         t[0].tv_usec = 0;
     270          12 :         t[1].tv_sec = statp->st_mtime;
     271          12 :         t[1].tv_usec = 0;
     272          12 :         e=lutimes(path, t);
     273             : #else
     274             :         struct timespec ts[2];
     275             :         ts[0].tv_sec=statp->st_atime;
     276             :         ts[0].tv_nsec=0;
     277             :         ts[1].tv_sec=statp->st_mtime;
     278             :         ts[1].tv_nsec=0;
     279             :         e=utimensat(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW);
     280             : #endif
     281          12 :         if(e<0)
     282             :         {
     283             :                 struct berrno be;
     284           0 :                 berrno_init(&be);
     285           0 :                 logw(asfd, cntr, "Unable to set file times %s: ERR=%s\n",
     286           0 :                         path, berrno_bstrerror(&be, errno));
     287             :                 return -1;
     288             :         }
     289             :         return 0;
     290             : }
     291             : 
     292           0 : uint64_t decode_file_no(struct iobuf *iobuf)
     293             : {
     294           0 :         int64_t val=0;
     295           0 :         from_base64(&val, iobuf->buf);
     296           0 :         return (uint64_t)val;
     297             : }
     298             : 
     299           0 : uint64_t decode_file_no_and_save_path(struct iobuf *iobuf, char **save_path)
     300             : {
     301             :         int64_t val;
     302             :         int eaten;
     303           0 :         char *p=iobuf->buf;
     304           0 :         if(!(eaten=from_base64(&val, iobuf->buf)))
     305             :                 return 0;
     306           0 :         *save_path=p+eaten+1;
     307           0 :         return (uint64_t)val;
     308             : }
     309             : 
     310          12 : int attribs_set(struct asfd *asfd, const char *path,
     311             :         struct stat *statp, uint64_t winattr, struct cntr *cntr)
     312             : {
     313             : #ifdef HAVE_WIN32
     314             :         win32_chmod(path, statp->st_mode, winattr);
     315             :         attribs_set_file_times(asfd, path, statp, cntr);
     316             :         return 0;
     317             : #else
     318          12 :         if(lchown(path, statp->st_uid, statp->st_gid)<0)
     319             :         {
     320             :                 struct berrno be;
     321           0 :                 berrno_init(&be);
     322           0 :                 char msg[256]="";
     323             : 
     324           0 :                 snprintf(msg, sizeof(msg),
     325             :                         "Unable to set file owner of %s to %d:%d: ERR=%s",
     326             :                         path, statp->st_uid, statp->st_gid,
     327           0 :                         berrno_bstrerror(&be, errno));
     328             : 
     329           0 :                 if(errno==EPERM)
     330             :                 {
     331             :                         static int do_owner_warning=1;
     332           0 :                         if(getuid()!=0)
     333             :                         {
     334           0 :                                 if(!do_owner_warning)
     335             :                                         return -1;
     336             : 
     337           0 :                                 logw(asfd, cntr, "%s - possibly because you are not root. Will suppress subsequent messages of this type.\n", msg);
     338           0 :                                 do_owner_warning=0;
     339           0 :                                 return -1;
     340             :                         }
     341             :                 }
     342           0 :                 logw(asfd, cntr, "%s\n", msg);
     343             : 
     344           0 :                 return -1;
     345             :         }
     346             : 
     347             :         /* Watch out, a metadata restore will have cmd set to CMD_METADATA or
     348             :            CMD_ENC_META, but that is OK at the moment because we are not doing
     349             :            meta stuff on links. */
     350          12 :         if(S_ISLNK(statp->st_mode))
     351             :         {
     352           0 :                 if(attribs_set_file_times(asfd, path, statp, cntr))
     353             :                         return -1;
     354             :         }
     355             :         else
     356             :         {
     357          12 :                 if(chmod(path, statp->st_mode) < 0)
     358             :                 {
     359             :                         struct berrno be;
     360           0 :                         berrno_init(&be);
     361           0 :                         logw(asfd, cntr,
     362             :                                 "Unable to set file modes %s: ERR=%s\n",
     363           0 :                                 path, berrno_bstrerror(&be, errno));
     364             :                         return -1;
     365             :                 }
     366             : 
     367          12 :                 if(attribs_set_file_times(asfd, path, statp, cntr))
     368             :                         return -1;
     369             : #ifdef HAVE_CHFLAGS
     370             :                 /*
     371             :                  * FreeBSD user flags
     372             :                  *
     373             :                  * Note, this should really be done before the utime() above,
     374             :                  *  but if the immutable bit is set, it will make the utimes()
     375             :                  *  fail.
     376             :                  */
     377             :                 if(chflags(path, statp->st_flags)<0)
     378             :                 {
     379             :                         struct berrno be;
     380             :                         berrno_init(&be);
     381             :                         logw(asfd, cntr,
     382             :                                 "Unable to set file flags %s: ERR=%s\n",
     383             :                                 path, berrno_bstrerror(&be, errno));
     384             :                         return -1;
     385             :                 }
     386             : #endif
     387             :         }
     388             : 
     389             :         return 0;
     390             : #endif
     391             : }

Generated by: LCOV version 1.13