LCOV - code coverage report
Current view: top level - lib/dpkg - file.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 49 92 53.3 %
Date: 2022-12-03 00:40:01 Functions: 7 10 70.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 15 50 30.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * libdpkg - Debian packaging suite library routines
       3                 :            :  * file.c - file handling functions
       4                 :            :  *
       5                 :            :  * Copyright © 1994, 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
       6                 :            :  * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
       7                 :            :  *
       8                 :            :  * This is free software; you can redistribute it and/or modify
       9                 :            :  * it under the terms of the GNU General Public License as published by
      10                 :            :  * the Free Software Foundation; either version 2 of the License, or
      11                 :            :  * (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :  * GNU General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU General Public License
      19                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : #include <compat.h>
      24                 :            : 
      25                 :            : #include <sys/types.h>
      26                 :            : #include <sys/stat.h>
      27                 :            : 
      28                 :            : #include <errno.h>
      29                 :            : #include <fcntl.h>
      30                 :            : #include <unistd.h>
      31                 :            : 
      32                 :            : #include <dpkg/dpkg.h>
      33                 :            : #include <dpkg/i18n.h>
      34                 :            : #include <dpkg/pager.h>
      35                 :            : #include <dpkg/fdio.h>
      36                 :            : #include <dpkg/buffer.h>
      37                 :            : #include <dpkg/file.h>
      38                 :            : 
      39                 :            : /**
      40                 :            :  * Check whether a filename is executable.
      41                 :            :  *
      42                 :            :  * @param filename The filename to check.
      43                 :            :  */
      44                 :            : bool
      45                 :          4 : file_is_exec(const char *filename)
      46                 :            : {
      47                 :            :         struct stat st;
      48                 :            : 
      49         [ +  + ]:          4 :         if (stat(filename, &st) < 0)
      50                 :          1 :                 return false;
      51                 :            : 
      52         [ -  + ]:          3 :         if (!S_ISREG(st.st_mode))
      53                 :          0 :                 return false;
      54                 :            : 
      55                 :          3 :         return st.st_mode & 0111;
      56                 :            : }
      57                 :            : 
      58                 :            : /**
      59                 :            :  * Copy file ownership and permissions from one file to another.
      60                 :            :  *
      61                 :            :  * @param src The source filename.
      62                 :            :  * @param dst The destination filename.
      63                 :            :  */
      64                 :            : void
      65                 :          0 : file_copy_perms(const char *src, const char *dst)
      66                 :            : {
      67                 :            :         struct stat stab;
      68                 :            : 
      69         [ #  # ]:          0 :         if (stat(src, &stab) == -1) {
      70         [ #  # ]:          0 :                 if (errno == ENOENT)
      71                 :          0 :                         return;
      72                 :          0 :                 ohshite(_("unable to stat source file '%.250s'"), src);
      73                 :            :         }
      74                 :            : 
      75         [ #  # ]:          0 :         if (chown(dst, stab.st_uid, stab.st_gid) == -1)
      76                 :          0 :                 ohshite(_("unable to change ownership of target file '%.250s'"),
      77                 :            :                         dst);
      78                 :            : 
      79         [ #  # ]:          0 :         if (chmod(dst, (stab.st_mode & ~S_IFMT)) == -1)
      80                 :          0 :                 ohshite(_("unable to set mode of target file '%.250s'"), dst);
      81                 :            : }
      82                 :            : 
      83                 :            : static int
      84                 :          4 : file_slurp_fd(int fd, const char *filename, struct varbuf *vb,
      85                 :            :               struct dpkg_error *err)
      86                 :            : {
      87                 :            :         struct stat st;
      88                 :            : 
      89         [ -  + ]:          4 :         if (fstat(fd, &st) < 0)
      90                 :          0 :                 return dpkg_put_errno(err, _("cannot stat %s"), filename);
      91                 :            : 
      92         [ +  + ]:          4 :         if (!S_ISREG(st.st_mode))
      93                 :          1 :                 return dpkg_put_error(err, _("%s is not a regular file"),
      94                 :            :                                       filename);
      95                 :            : 
      96         [ +  + ]:          3 :         if (st.st_size == 0)
      97                 :          1 :                 return 0;
      98                 :            : 
      99                 :          2 :         varbuf_init(vb, st.st_size);
     100         [ -  + ]:          2 :         if (fd_read(fd, vb->buf, st.st_size) < 0)
     101                 :          0 :                 return dpkg_put_errno(err, _("cannot read %s"), filename);
     102                 :          2 :         vb->used = st.st_size;
     103                 :            : 
     104                 :          2 :         return 0;
     105                 :            : }
     106                 :            : 
     107                 :            : int
     108                 :          5 : file_slurp(const char *filename, struct varbuf *vb, struct dpkg_error *err)
     109                 :            : {
     110                 :            :         int fd;
     111                 :            :         int rc;
     112                 :            : 
     113                 :          5 :         varbuf_init(vb, 0);
     114                 :            : 
     115                 :          5 :         fd = open(filename, O_RDONLY);
     116         [ +  + ]:          5 :         if (fd < 0)
     117                 :          1 :                 return dpkg_put_errno(err, _("cannot open %s"), filename);
     118                 :            : 
     119                 :          4 :         rc = file_slurp_fd(fd, filename, vb, err);
     120                 :            : 
     121                 :          4 :         (void)close(fd);
     122                 :            : 
     123                 :          4 :         return rc;
     124                 :            : }
     125                 :            : 
     126                 :            : static void
     127                 :         14 : file_lock_setup(struct flock *fl, short type)
     128                 :            : {
     129                 :         14 :         fl->l_type = type;
     130                 :         14 :         fl->l_whence = SEEK_SET;
     131                 :         14 :         fl->l_start = 0;
     132                 :         14 :         fl->l_len = 0;
     133                 :         14 :         fl->l_pid = 0;
     134                 :         14 : }
     135                 :            : 
     136                 :            : /**
     137                 :            :  * Unlock a previously locked file.
     138                 :            :  */
     139                 :            : void
     140                 :          7 : file_unlock(int lockfd, const char *lockfile, const char *lockdesc)
     141                 :            : {
     142                 :            :         struct flock fl;
     143                 :            : 
     144         [ -  + ]:          7 :         if (lockfd < 0)
     145                 :          0 :                 internerr("%s (%s) fd is %d < 0", lockdesc, lockfile, lockfd);
     146                 :            : 
     147                 :          7 :         file_lock_setup(&fl, F_UNLCK);
     148                 :            : 
     149         [ -  + ]:          7 :         if (fcntl(lockfd, F_SETLK, &fl) == -1)
     150                 :          0 :                 ohshite(_("unable to unlock %s"), lockdesc);
     151                 :          7 : }
     152                 :            : 
     153                 :            : static void
     154                 :          7 : file_unlock_cleanup(int argc, void **argv)
     155                 :            : {
     156                 :          7 :         int lockfd = *(int *)argv[0];
     157                 :          7 :         const char *lockfile = argv[1];
     158                 :          7 :         const char *lockdesc = argv[2];
     159                 :            : 
     160                 :          7 :         file_unlock(lockfd, lockfile, lockdesc);
     161                 :          7 : }
     162                 :            : 
     163                 :            : /**
     164                 :            :  * Check if a file has a lock acquired.
     165                 :            :  *
     166                 :            :  * @param lockfd The file descriptor for the lock.
     167                 :            :  * @param filename The file name associated to the file descriptor.
     168                 :            :  */
     169                 :            : bool
     170                 :          0 : file_is_locked(int lockfd, const char *filename)
     171                 :            : {
     172                 :            :         struct flock fl;
     173                 :            : 
     174                 :          0 :         file_lock_setup(&fl, F_WRLCK);
     175                 :            : 
     176         [ #  # ]:          0 :         if (fcntl(lockfd, F_GETLK, &fl) == -1)
     177                 :          0 :                 ohshit(_("unable to check file '%s' lock status"), filename);
     178                 :            : 
     179   [ #  #  #  # ]:          0 :         if (fl.l_type == F_WRLCK && fl.l_pid != getpid())
     180                 :          0 :                 return true;
     181                 :            :         else
     182                 :          0 :                 return false;
     183                 :            : }
     184                 :            : 
     185                 :            : /**
     186                 :            :  * Lock a file.
     187                 :            :  *
     188                 :            :  * @param lockfd The pointer to the lock file descriptor. It must be allocated
     189                 :            :  *        statically as its addresses is passed to a cleanup handler.
     190                 :            :  * @param flags The lock flags specifying what type of locking to perform.
     191                 :            :  * @param filename The name of the file to lock.
     192                 :            :  * @param desc The description of the file to lock.
     193                 :            :  */
     194                 :            : void
     195                 :          7 : file_lock(int *lockfd, enum file_lock_flags flags, const char *filename,
     196                 :            :           const char *desc)
     197                 :            : {
     198                 :            :         struct flock fl;
     199                 :            :         int lock_cmd;
     200                 :            : 
     201                 :          7 :         setcloexec(*lockfd, filename);
     202                 :            : 
     203                 :          7 :         file_lock_setup(&fl, F_WRLCK);
     204                 :            : 
     205         [ +  - ]:          7 :         if (flags == FILE_LOCK_WAIT)
     206                 :          7 :                 lock_cmd = F_SETLKW;
     207                 :            :         else
     208                 :          0 :                 lock_cmd = F_SETLK;
     209                 :            : 
     210         [ -  + ]:          7 :         if (fcntl(*lockfd, lock_cmd, &fl) == -1) {
     211                 :            :                 const char *warnmsg;
     212                 :            : 
     213   [ #  #  #  # ]:          0 :                 if (errno != EACCES && errno != EAGAIN)
     214                 :          0 :                         ohshite(_("unable to lock %s"), desc);
     215                 :            : 
     216                 :          0 :                 warnmsg = _("Note: removing the lock file is always wrong, "
     217                 :            :                             "can damage the locked area\n"
     218                 :            :                             "and the entire system. "
     219                 :            :                             "See <https://wiki.debian.org/Teams/Dpkg/FAQ#db-lock>.");
     220                 :            : 
     221                 :          0 :                 file_lock_setup(&fl, F_WRLCK);
     222         [ #  # ]:          0 :                 if (fcntl(*lockfd, F_GETLK, &fl) == -1)
     223                 :          0 :                         ohshit(_("%s was locked by another process\n%s"),
     224                 :            :                                desc, warnmsg);
     225                 :            : 
     226                 :          0 :                 ohshit(_("%s was locked by another process with pid %d\n%s"),
     227                 :            :                        desc, fl.l_pid, warnmsg);
     228                 :            :         }
     229                 :            : 
     230                 :          7 :         push_cleanup(file_unlock_cleanup, ~0, 3, lockfd, filename, desc);
     231                 :          7 : }
     232                 :            : 
     233                 :            : void
     234                 :          0 : file_show(const char *filename)
     235                 :            : {
     236                 :            :         struct pager *pager;
     237                 :            :         struct dpkg_error err;
     238                 :            :         int fd, rc;
     239                 :            : 
     240         [ #  # ]:          0 :         if (filename == NULL)
     241                 :          0 :                 internerr("filename is NULL");
     242                 :            : 
     243                 :          0 :         fd = open(filename, O_RDONLY);
     244         [ #  # ]:          0 :         if (fd < 0)
     245                 :          0 :                 ohshite(_("cannot open file %s"), filename);
     246                 :            : 
     247                 :          0 :         pager = pager_spawn(_("pager to show file"));
     248                 :          0 :         rc = fd_fd_copy(fd, STDOUT_FILENO, -1, &err);
     249                 :          0 :         pager_reap(pager);
     250                 :            : 
     251                 :          0 :         close(fd);
     252                 :            : 
     253   [ #  #  #  # ]:          0 :         if (rc < 0 && err.syserrno != EPIPE) {
     254                 :          0 :                 errno = err.syserrno;
     255                 :          0 :                 ohshite(_("cannot write file %s into the pager"), filename);
     256                 :            :         }
     257                 :          0 : }

Generated by: LCOV version 1.16