"Fossies" - the Fresh Open Source Software Archive

Member "dmidecode-3.3/util.c" (14 Oct 2020, 6232 Bytes) of package /linux/privat/dmidecode-3.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "util.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.2_vs_3.3.

    1 /*
    2  * Common "util" functions
    3  * This file is part of the dmidecode project.
    4  *
    5  *   Copyright (C) 2002-2018 Jean Delvare <jdelvare@suse.de>
    6  *
    7  *   This program is free software; you can redistribute it and/or modify
    8  *   it under the terms of the GNU General Public License as published by
    9  *   the Free Software Foundation; either version 2 of the License, or
   10  *   (at your option) any later version.
   11  *
   12  *   This program is distributed in the hope that it will be useful,
   13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  *   GNU General Public License for more details.
   16  *
   17  *   You should have received a copy of the GNU General Public License
   18  *   along with this program; if not, write to the Free Software
   19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   20  *
   21  *   For the avoidance of doubt the "preferred form" of this code is one which
   22  *   is in an open unpatent encumbered format. Where cryptographic key signing
   23  *   forms part of the process of creating an executable the information
   24  *   including keys needed to generate an equivalently functional executable
   25  *   are deemed to be part of the source code.
   26  */
   27 
   28 #include <sys/types.h>
   29 #include <sys/stat.h>
   30 
   31 #include "config.h"
   32 
   33 #ifdef USE_MMAP
   34 #include <sys/mman.h>
   35 #ifndef MAP_FAILED
   36 #define MAP_FAILED ((void *) -1)
   37 #endif /* !MAP_FAILED */
   38 #endif /* USE MMAP */
   39 
   40 #include <stdio.h>
   41 #include <stdlib.h>
   42 #include <unistd.h>
   43 #include <string.h>
   44 #include <fcntl.h>
   45 #include <errno.h>
   46 
   47 #include "types.h"
   48 #include "util.h"
   49 
   50 static int myread(int fd, u8 *buf, size_t count, const char *prefix)
   51 {
   52     ssize_t r = 1;
   53     size_t r2 = 0;
   54 
   55     while (r2 != count && r != 0)
   56     {
   57         r = read(fd, buf + r2, count - r2);
   58         if (r == -1)
   59         {
   60             if (errno != EINTR)
   61             {
   62                 perror(prefix);
   63                 return -1;
   64             }
   65         }
   66         else
   67             r2 += r;
   68     }
   69 
   70     if (r2 != count)
   71     {
   72         fprintf(stderr, "%s: Unexpected end of file\n", prefix);
   73         return -1;
   74     }
   75 
   76     return 0;
   77 }
   78 
   79 int checksum(const u8 *buf, size_t len)
   80 {
   81     u8 sum = 0;
   82     size_t a;
   83 
   84     for (a = 0; a < len; a++)
   85         sum += buf[a];
   86     return (sum == 0);
   87 }
   88 
   89 /*
   90  * Reads all of file from given offset, up to max_len bytes.
   91  * A buffer of at most max_len bytes is allocated by this function, and
   92  * needs to be freed by the caller.
   93  * This provides a similar usage model to mem_chunk()
   94  *
   95  * Returns a pointer to the allocated buffer, or NULL on error, and
   96  * sets max_len to the length actually read.
   97  */
   98 void *read_file(off_t base, size_t *max_len, const char *filename)
   99 {
  100     struct stat statbuf;
  101     int fd;
  102     u8 *p;
  103 
  104     /*
  105      * Don't print error message on missing file, as we will try to read
  106      * files that may or may not be present.
  107      */
  108     if ((fd = open(filename, O_RDONLY)) == -1)
  109     {
  110         if (errno != ENOENT)
  111             perror(filename);
  112         return NULL;
  113     }
  114 
  115     /*
  116      * Check file size, don't allocate more than can be read.
  117      */
  118     if (fstat(fd, &statbuf) == 0)
  119     {
  120         if (base >= statbuf.st_size)
  121         {
  122             fprintf(stderr, "%s: Can't read data beyond EOF\n",
  123                 filename);
  124             p = NULL;
  125             goto out;
  126         }
  127         if (*max_len > (size_t)statbuf.st_size - base)
  128             *max_len = statbuf.st_size - base;
  129     }
  130 
  131     if ((p = malloc(*max_len)) == NULL)
  132     {
  133         perror("malloc");
  134         goto out;
  135     }
  136 
  137     if (lseek(fd, base, SEEK_SET) == -1)
  138     {
  139         fprintf(stderr, "%s: ", filename);
  140         perror("lseek");
  141         goto err_free;
  142     }
  143 
  144     if (myread(fd, p, *max_len, filename) == 0)
  145         goto out;
  146 
  147 err_free:
  148     free(p);
  149     p = NULL;
  150 
  151 out:
  152     if (close(fd) == -1)
  153         perror(filename);
  154 
  155     return p;
  156 }
  157 
  158 static void safe_memcpy(void *dest, const void *src, size_t n)
  159 {
  160 #ifdef USE_SLOW_MEMCPY
  161     size_t i;
  162 
  163     for (i = 0; i < n; i++)
  164         *((u8 *)dest + i) = *((const u8 *)src + i);
  165 #else
  166     memcpy(dest, src, n);
  167 #endif
  168 }
  169 
  170 /*
  171  * Copy a physical memory chunk into a memory buffer.
  172  * This function allocates memory.
  173  */
  174 void *mem_chunk(off_t base, size_t len, const char *devmem)
  175 {
  176     void *p;
  177     int fd;
  178 #ifdef USE_MMAP
  179     struct stat statbuf;
  180     off_t mmoffset;
  181     void *mmp;
  182 #endif
  183 
  184     if ((fd = open(devmem, O_RDONLY)) == -1)
  185     {
  186         perror(devmem);
  187         return NULL;
  188     }
  189 
  190     if ((p = malloc(len)) == NULL)
  191     {
  192         perror("malloc");
  193         goto out;
  194     }
  195 
  196 #ifdef USE_MMAP
  197     if (fstat(fd, &statbuf) == -1)
  198     {
  199         fprintf(stderr, "%s: ", devmem);
  200         perror("stat");
  201         goto err_free;
  202     }
  203 
  204     /*
  205      * mmap() will fail with SIGBUS if trying to map beyond the end of
  206      * the file.
  207      */
  208     if (S_ISREG(statbuf.st_mode) && base + (off_t)len > statbuf.st_size)
  209     {
  210         fprintf(stderr, "mmap: Can't map beyond end of file %s\n",
  211             devmem);
  212         goto err_free;
  213     }
  214 
  215 #ifdef _SC_PAGESIZE
  216     mmoffset = base % sysconf(_SC_PAGESIZE);
  217 #else
  218     mmoffset = base % getpagesize();
  219 #endif /* _SC_PAGESIZE */
  220     /*
  221      * Please note that we don't use mmap() for performance reasons here,
  222      * but to workaround problems many people encountered when trying
  223      * to read from /dev/mem using regular read() calls.
  224      */
  225     mmp = mmap(NULL, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
  226     if (mmp == MAP_FAILED)
  227         goto try_read;
  228 
  229     safe_memcpy(p, (u8 *)mmp + mmoffset, len);
  230 
  231     if (munmap(mmp, mmoffset + len) == -1)
  232     {
  233         fprintf(stderr, "%s: ", devmem);
  234         perror("munmap");
  235     }
  236 
  237     goto out;
  238 
  239 try_read:
  240 #endif /* USE_MMAP */
  241     if (lseek(fd, base, SEEK_SET) == -1)
  242     {
  243         fprintf(stderr, "%s: ", devmem);
  244         perror("lseek");
  245         goto err_free;
  246     }
  247 
  248     if (myread(fd, p, len, devmem) == 0)
  249         goto out;
  250 
  251 err_free:
  252     free(p);
  253     p = NULL;
  254 
  255 out:
  256     if (close(fd) == -1)
  257         perror(devmem);
  258 
  259     return p;
  260 }
  261 
  262 int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add)
  263 {
  264     FILE *f;
  265 
  266     f = fopen(dumpfile, add ? "r+b" : "wb");
  267     if (!f)
  268     {
  269         fprintf(stderr, "%s: ", dumpfile);
  270         perror("fopen");
  271         return -1;
  272     }
  273 
  274     if (fseek(f, base, SEEK_SET) != 0)
  275     {
  276         fprintf(stderr, "%s: ", dumpfile);
  277         perror("fseek");
  278         goto err_close;
  279     }
  280 
  281     if (fwrite(data, len, 1, f) != 1)
  282     {
  283         fprintf(stderr, "%s: ", dumpfile);
  284         perror("fwrite");
  285         goto err_close;
  286     }
  287 
  288     if (fclose(f))
  289     {
  290         fprintf(stderr, "%s: ", dumpfile);
  291         perror("fclose");
  292         return -1;
  293     }
  294 
  295     return 0;
  296 
  297 err_close:
  298     fclose(f);
  299     return -1;
  300 }
  301 
  302 /* Returns end - start + 1, assuming start < end */
  303 u64 u64_range(u64 start, u64 end)
  304 {
  305     u64 res;
  306 
  307     res.h = end.h - start.h;
  308     res.l = end.l - start.l;
  309 
  310     if (end.l < start.l)
  311         res.h--;
  312     if (++res.l == 0)
  313         res.h++;
  314 
  315     return res;
  316 }