LCOV - code coverage report
Current view: top level - lib/dpkg - file.c (source / functions) Coverage Total Hit
Test: dpkg 1.22.7-3-g89f48 C code coverage Lines: 56.9 % 109 62
Test Date: 2024-07-17 02:53:43 Functions: 75.0 % 12 9
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 30.4 % 56 17

             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                 :             : #include <dpkg/execname.h>
      39                 :             : 
      40                 :             : /**
      41                 :             :  * Get the current working directory.
      42                 :             :  *
      43                 :             :  */
      44                 :             : void
      45                 :           9 : file_getcwd(struct varbuf *cwd)
      46                 :             : {
      47                 :           9 :         varbuf_reset(cwd);
      48                 :           9 :         varbuf_grow(cwd, 64);
      49         [ -  + ]:           9 :         while (getcwd(cwd->buf, cwd->size) == NULL)
      50                 :           0 :                 varbuf_grow(cwd, cwd->size * 2);
      51                 :           9 :         varbuf_trunc(cwd, strlen(cwd->buf));
      52                 :           9 : }
      53                 :             : 
      54                 :             : /**
      55                 :             :  * Read the symlink content into a varbuf.
      56                 :             :  *
      57                 :             :  */
      58                 :             : ssize_t
      59                 :           9 : file_readlink(const char *slink, struct varbuf *content, size_t content_len)
      60                 :             : {
      61                 :             :         ssize_t linksize;
      62                 :             : 
      63                 :           9 :         varbuf_reset(content);
      64                 :           9 :         varbuf_grow(content, content_len + 1);
      65                 :             : 
      66                 :           9 :         linksize = readlink(slink, content->buf, content->size);
      67         [ -  + ]:           9 :         if (linksize < 0)
      68                 :           0 :                 return linksize;
      69                 :             : 
      70                 :           9 :         varbuf_trunc(content, linksize);
      71                 :             : 
      72                 :           9 :         return linksize;
      73                 :             : }
      74                 :             : 
      75                 :             : /**
      76                 :             :  * Check whether a filename is executable.
      77                 :             :  *
      78                 :             :  * @param filename The filename to check.
      79                 :             :  */
      80                 :             : bool
      81                 :          35 : file_is_exec(const char *filename)
      82                 :             : {
      83                 :             :         struct stat st;
      84                 :             : 
      85         [ +  + ]:          35 :         if (stat(filename, &st) < 0)
      86                 :          22 :                 return false;
      87                 :             : 
      88         [ -  + ]:          13 :         if (!S_ISREG(st.st_mode))
      89                 :           0 :                 return false;
      90                 :             : 
      91                 :          13 :         return st.st_mode & 0111;
      92                 :             : }
      93                 :             : 
      94                 :             : /**
      95                 :             :  * Copy file ownership and permissions from one file to another.
      96                 :             :  *
      97                 :             :  * @param src The source filename.
      98                 :             :  * @param dst The destination filename.
      99                 :             :  */
     100                 :             : void
     101                 :           0 : file_copy_perms(const char *src, const char *dst)
     102                 :             : {
     103                 :             :         struct stat stab;
     104                 :             : 
     105         [ #  # ]:           0 :         if (stat(src, &stab) < 0) {
     106         [ #  # ]:           0 :                 if (errno == ENOENT)
     107                 :           0 :                         return;
     108                 :           0 :                 ohshite(_("unable to stat source file '%.250s'"), src);
     109                 :             :         }
     110                 :             : 
     111         [ #  # ]:           0 :         if (chown(dst, stab.st_uid, stab.st_gid) < 0)
     112                 :           0 :                 ohshite(_("unable to change ownership of target file '%.250s'"),
     113                 :             :                         dst);
     114                 :             : 
     115         [ #  # ]:           0 :         if (chmod(dst, (stab.st_mode & ~S_IFMT)) < 0)
     116                 :           0 :                 ohshite(_("unable to set mode of target file '%.250s'"), dst);
     117                 :             : }
     118                 :             : 
     119                 :             : static int
     120                 :           4 : file_slurp_fd(int fd, const char *filename, struct varbuf *vb,
     121                 :             :               struct dpkg_error *err)
     122                 :             : {
     123                 :             :         struct stat st;
     124                 :             : 
     125         [ -  + ]:           4 :         if (fstat(fd, &st) < 0)
     126                 :           0 :                 return dpkg_put_errno(err, _("cannot stat %s"), filename);
     127                 :             : 
     128         [ +  + ]:           4 :         if (!S_ISREG(st.st_mode))
     129                 :           1 :                 return dpkg_put_error(err, _("%s is not a regular file"),
     130                 :             :                                       filename);
     131                 :             : 
     132         [ +  + ]:           3 :         if (st.st_size == 0)
     133                 :           1 :                 return 0;
     134                 :             : 
     135                 :           2 :         varbuf_init(vb, st.st_size + 1);
     136         [ -  + ]:           2 :         if (fd_read(fd, vb->buf, st.st_size) < 0)
     137                 :           0 :                 return dpkg_put_errno(err, _("cannot read %s"), filename);
     138                 :           2 :         varbuf_trunc(vb, st.st_size);
     139                 :             : 
     140                 :           2 :         return 0;
     141                 :             : }
     142                 :             : 
     143                 :             : int
     144                 :           5 : file_slurp(const char *filename, struct varbuf *vb, struct dpkg_error *err)
     145                 :             : {
     146                 :             :         int fd;
     147                 :             :         int rc;
     148                 :             : 
     149                 :           5 :         varbuf_init(vb, 0);
     150                 :             : 
     151                 :           5 :         fd = open(filename, O_RDONLY);
     152         [ +  + ]:           5 :         if (fd < 0)
     153                 :           1 :                 return dpkg_put_errno(err, _("cannot open %s"), filename);
     154                 :             : 
     155                 :           4 :         rc = file_slurp_fd(fd, filename, vb, err);
     156                 :             : 
     157                 :           4 :         (void)close(fd);
     158                 :             : 
     159                 :           4 :         return rc;
     160                 :             : }
     161                 :             : 
     162                 :             : static void
     163                 :          14 : file_lock_setup(struct flock *fl, short type)
     164                 :             : {
     165                 :          14 :         fl->l_type = type;
     166                 :          14 :         fl->l_whence = SEEK_SET;
     167                 :          14 :         fl->l_start = 0;
     168                 :          14 :         fl->l_len = 0;
     169                 :          14 :         fl->l_pid = 0;
     170                 :          14 : }
     171                 :             : 
     172                 :             : /**
     173                 :             :  * Unlock a previously locked file.
     174                 :             :  */
     175                 :             : void
     176                 :           7 : file_unlock(int lockfd, const char *lockfile, const char *lockdesc)
     177                 :             : {
     178                 :             :         struct flock fl;
     179                 :             : 
     180         [ -  + ]:           7 :         if (lockfd < 0)
     181                 :           0 :                 internerr("%s (%s) fd is %d < 0", lockdesc, lockfile, lockfd);
     182                 :             : 
     183                 :           7 :         file_lock_setup(&fl, F_UNLCK);
     184                 :             : 
     185         [ -  + ]:           7 :         if (fcntl(lockfd, F_SETLK, &fl) < 0)
     186                 :           0 :                 ohshite(_("unable to unlock %s"), lockdesc);
     187                 :           7 : }
     188                 :             : 
     189                 :             : static void
     190                 :           7 : file_unlock_cleanup(int argc, void **argv)
     191                 :             : {
     192                 :           7 :         int lockfd = *(int *)argv[0];
     193                 :           7 :         const char *lockfile = argv[1];
     194                 :           7 :         const char *lockdesc = argv[2];
     195                 :             : 
     196                 :           7 :         file_unlock(lockfd, lockfile, lockdesc);
     197                 :           7 : }
     198                 :             : 
     199                 :             : /**
     200                 :             :  * Check if a file has a lock acquired.
     201                 :             :  *
     202                 :             :  * @param lockfd The file descriptor for the lock.
     203                 :             :  * @param filename The file name associated to the file descriptor.
     204                 :             :  */
     205                 :             : bool
     206                 :           0 : file_is_locked(int lockfd, const char *filename)
     207                 :             : {
     208                 :             :         struct flock fl;
     209                 :             : 
     210                 :           0 :         file_lock_setup(&fl, F_WRLCK);
     211                 :             : 
     212         [ #  # ]:           0 :         if (fcntl(lockfd, F_GETLK, &fl) < 0)
     213                 :           0 :                 ohshit(_("unable to check file '%s' lock status"), filename);
     214                 :             : 
     215   [ #  #  #  # ]:           0 :         if (fl.l_type == F_WRLCK && fl.l_pid != getpid())
     216                 :           0 :                 return true;
     217                 :             :         else
     218                 :           0 :                 return false;
     219                 :             : }
     220                 :             : 
     221                 :             : /**
     222                 :             :  * Lock a file.
     223                 :             :  *
     224                 :             :  * @param lockfd The pointer to the lock file descriptor. It must be allocated
     225                 :             :  *        statically as its addresses is passed to a cleanup handler.
     226                 :             :  * @param flags The lock flags specifying what type of locking to perform.
     227                 :             :  * @param filename The name of the file to lock.
     228                 :             :  * @param desc The description of the file to lock.
     229                 :             :  */
     230                 :             : void
     231                 :           7 : file_lock(int *lockfd, enum file_lock_flags flags, const char *filename,
     232                 :             :           const char *desc)
     233                 :             : {
     234                 :             :         struct flock fl;
     235                 :             :         int lock_cmd;
     236                 :             : 
     237                 :           7 :         setcloexec(*lockfd, filename);
     238                 :             : 
     239                 :           7 :         file_lock_setup(&fl, F_WRLCK);
     240                 :             : 
     241         [ +  - ]:           7 :         if (flags == FILE_LOCK_WAIT)
     242                 :           7 :                 lock_cmd = F_SETLKW;
     243                 :             :         else
     244                 :           0 :                 lock_cmd = F_SETLK;
     245                 :             : 
     246         [ -  + ]:           7 :         if (fcntl(*lockfd, lock_cmd, &fl) < 0) {
     247                 :             :                 const char *warnmsg;
     248                 :             :                 char *execname;
     249                 :             : 
     250   [ #  #  #  # ]:           0 :                 if (errno != EACCES && errno != EAGAIN)
     251                 :           0 :                         ohshite(_("unable to lock %s"), desc);
     252                 :             : 
     253                 :           0 :                 warnmsg = _("Note: removing the lock file is always wrong, "
     254                 :             :                             "can damage the locked area\n"
     255                 :             :                             "and the entire system. "
     256                 :             :                             "See <https://wiki.debian.org/Teams/Dpkg/FAQ#db-lock>.");
     257                 :             : 
     258                 :           0 :                 file_lock_setup(&fl, F_WRLCK);
     259         [ #  # ]:           0 :                 if (fcntl(*lockfd, F_GETLK, &fl) < 0)
     260                 :           0 :                         ohshit(_("%s was locked by another process\n%s"),
     261                 :             :                                desc, warnmsg);
     262                 :             : 
     263                 :           0 :                 execname = dpkg_get_pid_execname(fl.l_pid);
     264                 :             : 
     265         [ #  # ]:           0 :                 ohshit(_("%s was locked by %s process with pid %d\n%s"),
     266                 :           0 :                        desc, execname ? execname : C_("process", "<unknown>"),
     267                 :             :                        fl.l_pid, warnmsg);
     268                 :             :         }
     269                 :             : 
     270                 :           7 :         push_cleanup(file_unlock_cleanup, ~0, 3, lockfd, filename, desc);
     271                 :           7 : }
     272                 :             : 
     273                 :             : void
     274                 :           0 : file_show(const char *filename)
     275                 :             : {
     276                 :             :         struct pager *pager;
     277                 :             :         struct dpkg_error err;
     278                 :             :         int fd, rc;
     279                 :             : 
     280         [ #  # ]:           0 :         if (filename == NULL)
     281                 :           0 :                 internerr("filename is NULL");
     282                 :             : 
     283                 :           0 :         fd = open(filename, O_RDONLY);
     284         [ #  # ]:           0 :         if (fd < 0)
     285                 :           0 :                 ohshite(_("cannot open file %s"), filename);
     286                 :             : 
     287                 :           0 :         pager = pager_spawn(_("pager to show file"));
     288                 :           0 :         rc = fd_fd_copy(fd, STDOUT_FILENO, -1, &err);
     289                 :           0 :         pager_reap(pager);
     290                 :             : 
     291                 :           0 :         close(fd);
     292                 :             : 
     293   [ #  #  #  # ]:           0 :         if (rc < 0 && err.syserrno != EPIPE) {
     294                 :           0 :                 errno = err.syserrno;
     295                 :           0 :                 ohshite(_("cannot write file %s into the pager"), filename);
     296                 :             :         }
     297                 :           0 : }
        

Generated by: LCOV version 2.0-1