LCOV - code coverage report
Current view: top level - libpkg - fetch_file.c (source / functions) Hit Total Coverage
Test: plop Lines: 64 75 85.3 %
Date: 2024-12-28 18:40:32 Functions: 3 3 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 33 42 78.6 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2020-2023 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  *
       4                 :            :  * Redistribution and use in source and binary forms, with or without
       5                 :            :  * modification, are permitted provided that the following conditions
       6                 :            :  * are met:
       7                 :            :  * 1. Redistributions of source code must retain the above copyright
       8                 :            :  *    notice, this list of conditions and the following disclaimer
       9                 :            :  *    in this position and unchanged.
      10                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      11                 :            :  *    notice, this list of conditions and the following disclaimer in the
      12                 :            :  *    documentation and/or other materials provided with the distribution.
      13                 :            :  *
      14                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      15                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      16                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      17                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      18                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      19                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      20                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      21                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      22                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      23                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <sys/stat.h>
      27                 :            : #include <sys/param.h>
      28                 :            : 
      29                 :            : #include <stdio.h>
      30                 :            : #include <errno.h>
      31                 :            : 
      32                 :            : #include "pkg.h"
      33                 :            : #include "private/pkg.h"
      34                 :            : #include "private/event.h"
      35                 :            : #include "private/utils.h"
      36                 :            : #include "private/fetch.h"
      37                 :            : 
      38                 :            : int
      39                 :        289 : file_open(struct pkg_repo *repo, struct fetch_item *fi)
      40                 :            : {
      41                 :            :         struct stat st;
      42                 :        289 :         const char *u = fi->url;
      43                 :        289 :         size_t len = strlen(u);
      44                 :            : 
      45         [ -  + ]:        289 :         if (len > 5)
      46                 :        289 :                 u += 5; /* file: */
      47         [ -  + ]:        289 :         if (len < 8) {
      48                 :          0 :                 pkg_emit_error("Invalid url: %s'\n', "
      49                 :          0 :                     "file://<absolutepath> expected", fi->url);
      50                 :          0 :                 return (EPKG_FATAL);
      51                 :            :         }
      52         [ +  + ]:        289 :         if (strncmp(u, "//", 2) != 0) {
      53                 :          6 :                 pkg_emit_error("invalid url: '%s'\n", fi->url);
      54                 :          6 :                 return (EPKG_FATAL);
      55                 :            :         }
      56                 :        283 :         u+=2;
      57                 :            :         /* if we don't have a '/' it means we have a host FQDN component, otherwise just proceed */
      58                 :            :         /* we can fetch local files only, so we accept the localhost FQDN */
      59                 :            :         /* TODO: consider accepting gethostname/getdomainname and combinations of these. */
      60                 :            :         /* TODO: delegate to curl to fetch any URL, btw. curl bails on this as well. */
      61         [ +  + ]:        283 :         if (*u != '/') {
      62                 :         29 :                 char fqdn[256]="";
      63                 :         29 :                 char *path = strchr(u+1, '/');
      64         [ +  - ]:         29 :                 if (path == NULL) {
      65                 :          0 :                         pkg_emit_error("Invalid url: '%s',\n"
      66                 :          0 :                                         "file:///<path> or file://localhost/<path> expected.", fi->url);
      67                 :          0 :                         return (EPKG_FATAL);
      68                 :            :                 }
      69         [ -  + ]:         29 :                 strncat(fqdn, u, MIN(255, path-u));
      70         [ +  + ]:         29 :                 if (0 != strncmp("localhost", fqdn, sizeof(fqdn))) {
      71                 :         24 :                         pkg_emit_error("Invalid url: '%s'\n"
      72                 :         24 :                                         "file:///<path> or file://localhost/<path> expected.", fi->url);
      73                 :         24 :                         return (EPKG_FATAL);
      74                 :            :                         }
      75                 :          5 :                 u = path;
      76                 :          5 :         }
      77         [ +  + ]:        259 :         if (stat(u, &st) == -1) {
      78         [ -  + ]:         12 :                 if (!repo->silent)
      79                 :         24 :                         pkg_emit_error("%s: %s", fi->url,
      80                 :         12 :                             strerror(errno));
      81                 :         12 :                 return (EPKG_FATAL);
      82                 :            :         }
      83                 :        247 :         fi->size = st.st_size;
      84         [ +  + ]:        247 :         if (st.st_mtime <= fi->mtime)
      85                 :        104 :                 return (EPKG_UPTODATE);
      86                 :            : 
      87                 :        143 :         pkg_dbg(PKG_DBG_FETCH, 1,  "mtime: local %ld, remote %ld", st.st_mtime, fi->mtime);
      88                 :        143 :         repo->fh = fopen(u, "re");
      89         [ +  - ]:        143 :         if (repo->fh == NULL)
      90                 :          0 :                 return (EPKG_FATAL);
      91                 :        143 :         fi->mtime = st.st_mtime;
      92                 :        143 :         return (EPKG_OK);
      93                 :        289 : }
      94                 :            : 
      95                 :            : void
      96                 :        289 : fh_close(struct pkg_repo *repo)
      97                 :            : {
      98         [ +  + ]:        289 :         if (repo->fh != NULL)
      99                 :        143 :                 fclose(repo->fh);
     100                 :        289 :         repo->fh = NULL;
     101                 :        289 : }
     102                 :            : 
     103                 :            : int
     104                 :        143 : stdio_fetch(struct pkg_repo *repo, int dest, struct fetch_item *fi)
     105                 :            : {
     106                 :            :         char buf[8192];
     107                 :        143 :         size_t buflen = 0, left = 0;
     108                 :        143 :         off_t done = 0, r;
     109                 :            : 
     110                 :        143 :         pkg_emit_fetch_begin(fi->url);
     111                 :        143 :         pkg_emit_progress_start(NULL);
     112         [ +  - ]:        143 :         if (fi->offset > 0)
     113                 :          0 :                 done += fi->offset;
     114                 :        143 :         buflen = sizeof(buf);
     115                 :        143 :         left = sizeof(buf);
     116         [ +  + ]:        143 :         if (fi->size > 0)
     117                 :        140 :                 left = fi->size - done;
     118                 :            : 
     119   [ +  +  +  + ]:        289 :         while ((r = fread(buf, 1, left < buflen ? left : buflen, repo->fh)) > 0) {
     120         [ -  + ]:        146 :                 if (write(dest, buf, r) != r) {
     121                 :          0 :                         pkg_emit_errno("write", "");
     122                 :          0 :                         return (EPKG_FATAL);
     123                 :            :                 }
     124                 :        146 :                 done += r;
     125         [ +  - ]:        146 :                 if (fi->size > 0) {
     126                 :        146 :                         left -= r;
     127                 :        146 :                         pkg_dbg(PKG_DBG_FETCH, 1, "Read status: %jd over %jd", (intmax_t)done, (intmax_t)fi->size);
     128                 :        146 :                 } else
     129                 :          0 :                         pkg_dbg(PKG_DBG_FETCH, 1,  "Read status: %jd", (intmax_t)done);
     130         [ +  + ]:        146 :                 if (fi->size > 0)
     131                 :        140 :                         pkg_emit_progress_tick(done, fi->size);
     132                 :            :         }
     133   [ +  +  +  + ]:        429 :         if (ferror(repo->fh)) {
     134                 :        286 :                 pkg_emit_error("An error occurred while fetching package");
     135                 :        286 :                 return(EPKG_FATAL);
     136                 :            :         }
     137                 :        143 :         return (EPKG_OK);
     138                 :        143 : }

Generated by: LCOV version 1.15