LCOV - code coverage report
Current view: top level - src - utils.c (source / functions) Hit Total Coverage
Test: oc-runner-0.0.51.5.29c69 Code Coverage Lines: 371 404 91.8 %
Date: 2018-10-15 12:44:38 Functions: 30 30 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  Copyright (c) 2017 by Danny Goossen, Gioxa Ltd.
       3             : 
       4             :  This file is part of the oc-runner
       5             : 
       6             :  MIT License
       7             : 
       8             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       9             :  of this software and associated documentation files (the "Software"), to deal
      10             :  in the Software without restriction, including without limitation the rights
      11             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12             :  copies of the Software, and to permit persons to whom the Software is
      13             :  furnished to do so, subject to the following conditions:
      14             : 
      15             :  The above copyright notice and this permission notice shall be included in all
      16             :  copies or substantial portions of the Software.
      17             : 
      18             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             :  SOFTWARE.
      25             : 
      26             :  */
      27             : 
      28             : /*! @file utils.c
      29             :  *  @brief extra / modified c-functions
      30             :  *  @author danny@gioxa.com
      31             :  *  @date 10/5/17
      32             :  *  @copyright (c) 2017 Danny Goossen,Gioxa Ltd.
      33             :  */
      34             : 
      35             :  #define _GNU_SOURCE
      36             :  #include <stdio.h>
      37             : 
      38             : // stdio.h with _GNU_SOURCE already defines _XOPEN_SOURCE 500
      39             : //#define _XOPEN_SOURCE 500
      40             : #include <ftw.h>
      41             : typedef unsigned short int u_short;
      42             : #include <fts.h>
      43             : 
      44             : #include "deployd.h"
      45             : 
      46             : #ifndef OPEN_MAX
      47             : #define OPEN_MAX 1023
      48             : #endif
      49             : 
      50             : #include "wordexp_var.h"
      51             : 
      52             : 
      53             : /*------------------------------------------------------------------------
      54             :  * Convert string to uppercase
      55             :  *------------------------------------------------------------------------*/
      56           9 : void upper_string(char s[]) {
      57          18 :    if (!s) return;
      58             :    int c = 0;
      59             : 
      60          43 :    while (s[c] != '\0') {
      61          35 :       if (s[c] >= 'a' && s[c] <= 'z') {
      62          33 :          s[c] = s[c] - 32;
      63             :       }
      64          35 :       c++;
      65             :    }
      66             : }
      67             : /*------------------------------------------------------------------------
      68             :  * Convert string to lower case
      69             :  *------------------------------------------------------------------------*/
      70          39 : void lower_string(char s[]) {
      71          78 :    if (!s) return;
      72             :    int c = 0;
      73             : 
      74         389 :    while (s[c] != '\0') {
      75         351 :       if (s[c] >= 'A' && s[c] <= 'Z') {
      76          32 :          s[c] = s[c] + 32;
      77             :       }
      78         351 :       c++;
      79             :    }
      80             : }
      81             : 
      82             : /*------------------------------------------------------------------------
      83             :  * Convert non null terminated string to uppercase
      84             :  *------------------------------------------------------------------------*/
      85             : 
      86           3 : void upper_string_n(char s[],size_t n) {
      87           6 :    if (!s) return;
      88             :    int c = 0;
      89             : 
      90           3 :    while (s[c] != '\0' && c<n) {
      91           2 :       if (s[c] >= 'a' && s[c] <= 'z') {
      92           2 :          s[c] = s[c] - 32;
      93             :       }
      94           2 :       c++;
      95             :    }
      96             : }
      97             : 
      98             : /*
      99             : void split_path_file(char** p, char** f,const char *pf) {
     100             :   if (!pf || strlen(pf)==0) return;
     101             :    const char *slash = pf;
     102             :    char *next;
     103             :    while ((next = strpbrk(slash + 1, "\\/"))) slash = next;
     104             :    if (pf != slash) slash++;
     105             :    *p = cJSON_strdup_n((const unsigned char *)pf, slash - pf);
     106             :    *f = strdup(slash);
     107             : }
     108             : */
     109             : 
     110           4 : void split_path_file_2_path(char** p, const char *pf) {
     111           8 :     if (!pf || strlen(pf)==0) return;
     112             :    const char *slash = pf;
     113             :    char *next;
     114          22 :    while ((next = strpbrk(slash + 1, "\\/"))) slash = next;
     115           4 :    if (pf != slash) slash++;
     116           4 :    *p =cJSON_strdup_n((const unsigned char *)pf, slash - pf);
     117             : }
     118             : 
     119             : 
     120             : void * memrchr(const void *s,int c, size_t n)
     121             : {
     122             :    const unsigned char *cp;
     123             : 
     124          20 :    if (n != 0) {
     125          20 :       cp = (unsigned char *)s + n;
     126             :       do {
     127         160 :          if (*(--cp) == (unsigned char)c)
     128             :             return (void *)cp;
     129         143 :       } while (--n != 0);
     130             :    }
     131             :    return (void *)0;
     132             : }
     133             : 
     134             : 
     135           7 : char * normalizePath(const char* pwd, const char * src, char* res) {
     136             :    size_t res_len;
     137           7 :    size_t src_len = strlen(src);
     138             : 
     139           7 :    const char * ptr = src;
     140           7 :    const char * end = &src[src_len];
     141             :    const char * next;
     142             : 
     143           7 :    if (src_len == 0 || src[0] != '/') {
     144             :       // relative path
     145             :       size_t pwd_len;
     146             : 
     147           0 :       pwd_len = strlen(pwd);
     148           0 :       memcpy(res, pwd, pwd_len);
     149           0 :       res_len = pwd_len;
     150             :    } else {
     151             :       res_len = 0;
     152             :    }
     153          60 :    for (ptr = src; ptr < end; ptr=next+1) {
     154             :       size_t len;
     155          53 :       next = (char*)memchr(ptr, '/', end-ptr);
     156          53 :       if (next == NULL) {
     157           7 :          next = end;
     158             :       }
     159          53 :       len = next-ptr;
     160          53 :       switch(len) {
     161             :          case 2:
     162          11 :             if (ptr[0] == '.' && ptr[1] == '.') {
     163           3 :                const char * slash = (char*)memrchr(res, '/', res_len);
     164           3 :                if (slash != NULL) {
     165           3 :                   res_len = slash - res;
     166             :                }
     167           3 :                continue;
     168             :             }
     169             :             break;
     170             :          case 1:
     171           2 :             if (ptr[0] == '.') {
     172           1 :                continue;
     173             :             }
     174             :             break;
     175             :          case 0:
     176           7 :             continue;
     177             :       }
     178             : 
     179          42 :       if (res_len != 1)
     180          42 :          res[res_len++] = '/';
     181             : 
     182          42 :       memcpy(&res[res_len], ptr, len);
     183          42 :       res_len += len;
     184             :    }
     185             : 
     186           7 :    if (res_len == 0) {
     187           0 :       res[res_len++] = '/';
     188             :    }
     189           7 :    res[res_len] = '\0';
     190           7 :    return res;
     191             : }
     192             : 
     193             : /**
     194             :  \brief nftw() extended with payload \a data for callback function
     195             :  The function nftw_x() is the same as nftw(), except that it has one additional argument, \a data as payload for the fn()
     196             :  \see https://linux.die.net/man/3/nftw for the base function nftw()
     197             :  */
     198             : static int
     199           2 : nftw_x(const char *path, int (*fn)(const char *, const struct stat *, int,
     200             :                                  struct FTW *,void * data), int nfds, int ftwflags,void * data)
     201             : {
     202             :    const char *paths[2];
     203             :    struct FTW ftw;
     204             :    FTSENT *cur;
     205             :    FTS *ftsp;
     206             :    int ftsflags, fnflag, error, postorder, sverrno;
     207             : 
     208             :    /* XXX - nfds is currently unused */
     209           2 :    if (nfds < 1 || nfds > OPEN_MAX) {
     210           0 :       errno = EINVAL;
     211           0 :       return (-1);
     212             :    }
     213             : 
     214           2 :    ftsflags = FTS_COMFOLLOW;
     215           2 :    if (!(ftwflags & FTW_CHDIR))
     216           2 :       ftsflags |= FTS_NOCHDIR;
     217           2 :    if (ftwflags & FTW_MOUNT)
     218           0 :       ftsflags |= FTS_XDEV;
     219           2 :    if (ftwflags & FTW_PHYS)
     220           2 :       ftsflags |= FTS_PHYSICAL;
     221           2 :    postorder = (ftwflags & FTW_DEPTH) != 0;
     222           2 :    paths[0] = path;
     223           2 :    paths[1] = NULL;
     224           2 :    ftsp = fts_open((char * const *)paths, ftsflags, NULL);
     225           2 :    if (ftsp == NULL)
     226             :       return (-1);
     227             :    error = 0;
     228          13 :    while ((cur = fts_read(ftsp)) != NULL) {
     229          11 :       switch (cur->fts_info) {
     230             :          case FTS_D:
     231           4 :             if (postorder)
     232           0 :                continue;
     233             :             fnflag = FTW_D;
     234             :             break;
     235             :          case FTS_DNR:
     236             :             fnflag = FTW_DNR;
     237             :             break;
     238             :          case FTS_DP:
     239           4 :             if (!postorder)
     240           4 :                continue;
     241             :             fnflag = FTW_DP;
     242             :             break;
     243             :          case FTS_F:
     244             :          case FTS_DEFAULT:
     245           3 :             fnflag = FTW_F;
     246           3 :             break;
     247             :          case FTS_NS:
     248             :          case FTS_NSOK:
     249           0 :             fnflag = FTW_NS;
     250           0 :             break;
     251             :          case FTS_SL:
     252           0 :             fnflag = FTW_SL;
     253           0 :             break;
     254             :          case FTS_SLNONE:
     255           0 :             fnflag = FTW_SLN;
     256           0 :             break;
     257             :          case FTS_DC:
     258           0 :             errno = ELOOP;
     259             :             /* FALLTHROUGH */
     260             :          default:
     261             :             error = -1;
     262             :             goto done;
     263             :       }
     264           7 :       ftw.base = cur->fts_pathlen - cur->fts_namelen;
     265           7 :       ftw.level = cur->fts_level;
     266           7 :       error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw,data);
     267           7 :       if (error != 0)
     268             :          break;
     269             :    }
     270             : done:
     271           2 :    sverrno = errno;
     272           2 :    (void) fts_close(ftsp);
     273           2 :    errno = sverrno;
     274           2 :    return (error);
     275             : }
     276             : 
     277             : /**
     278             :  \brief callback funtion for nftw() rm -r
     279             :  */
     280          31 : static int remove_it(const char *path, __attribute__((unused)) const struct stat *s, int flag, __attribute__((unused)) struct FTW *f)
     281             : {
     282          31 :    int status=0;
     283             :    int (*rm_func)( const char * );
     284             : 
     285          31 :    switch( flag ) {
     286             :       default:     rm_func = unlink; break;
     287          20 :       case FTW_DP: rm_func = rmdir;
     288             :    }
     289          31 :   status = (rm_func( path ), status != 0 );
     290             :     //  perror( path );
     291          31 :    return status;
     292             : }
     293             : 
     294             : /**
     295             :  \brief wrapper for nftw_x payload used for getfilelist_item()
     296             :  */
     297             : struct payload{
     298             :    cJSON ** filelist;
     299             : };
     300             : 
     301             : /**
     302             :  \brief add path to filelist with attributes from \p mode
     303             :  \param path to add to list
     304             :  \param mode attributes to add
     305             :  \return 0 on success
     306             :  */
     307          10 : static int add_to_file_list(const char *path,int mode,cJSON ** filelist)
     308             : {
     309          10 :    int result=0;
     310          10 :    size_t len=strlen(path);
     311          10 :    if ((S_ISDIR(mode) && len>2 && strcmp(path+len-2, ".")!=0 && len >3 && strcmp(path+len-3, "..")!=0 )|| !S_ISDIR(mode))
     312             :    {
     313          10 :       if (!*filelist) *filelist=cJSON_CreateArray();
     314          10 :       if (*filelist)
     315             :       {
     316          10 :          cJSON * tmpo=cJSON_CreateObject();
     317          10 :          cJSON_AddStringToObject(tmpo, "path", path);
     318          10 :          cJSON_AddNumberToObject(tmpo, "mode", mode);
     319          10 :          cJSON_AddItemToArray(*filelist,tmpo);
     320             :       }
     321             :       else
     322             :          result=1;
     323             :    }
     324          10 :    return result;
     325             : }
     326             : 
     327             : /**
     328             :  * \brief calback function for the nftw_x for getfilelist_item()
     329             :  */
     330           7 : static int list_it(const char *path, const struct stat *s, int flag, __attribute__((unused)) struct FTW *f,void* data)
     331             : {
     332           7 :    int status=0;
     333             :    switch( flag ) {
     334             :       default:     ; break;
     335             :          /* we'll handle dir/symlinks/files */
     336             :       case FTW_SL:
     337             :       case FTW_F:
     338             :       case FTW_D:
     339           7 :          status=add_to_file_list( path,s->st_mode ,data) ;break;
     340             :    }
     341           7 :    return status;
     342             : }
     343             : 
     344             : /**
     345             :  \brief get filelist from \p item, traverse if \p item is a directory.
     346             :  \param projectdir base directory
     347             :  \param item to process
     348             :  \param filelist pointer to the result
     349             :  */
     350           7 : static void getfilelist_item(const char * projectdir,const char *item,cJSON ** filelist)
     351             : {
     352           7 :    debug("getfilelist_item %s in %s\n",item,projectdir);
     353             :    struct stat sb;
     354           7 :    if (strlen(item)>=PATH_MAX)
     355             :    {
     356           0 :       debug("item exceeds PATHMAX length\n");
     357           0 :       return;
     358             :    }
     359             :    char normalized_path_buf[PATH_MAX];
     360           7 :    const char * normalized_path=normalizePath(projectdir, item, normalized_path_buf);
     361           7 :    debug("normalized_path from %s => %s\n",item, normalized_path);
     362           7 :    if (!normalized_path)
     363             :    {
     364           0 :       debug("normalized path error\n");
     365             :    }
     366             :    char realpathbuffer[PATH_MAX];
     367             :    // check if we stay within the project dir
     368           7 :    char * therealpath=realpath(item, realpathbuffer);
     369           7 :    debug("therealpath %s\n",therealpath);
     370           7 :    if (therealpath)
     371             :    {
     372             : 
     373           6 :       if (strncmp(therealpath, projectdir, strlen(projectdir))!=0 && strncmp(therealpath,"/cache/",7)!=0)
     374             :       {
     375           1 :          debug("real_path outside project dir path\n");
     376           1 :          return;
     377             :       }
     378             :    }
     379             :    else
     380             :    {
     381           1 :       error("problem finding real path for %s: %s\n",item,strerror(errno));
     382           1 :       return;
     383             :    }
     384           5 :    if (stat(item, &sb) == 0 && S_ISDIR(sb.st_mode))
     385             :    {
     386             : 
     387             :       //add_to_file_list(normalized_path, sb.st_mode, filelist);
     388           2 :       if (nftw_x((char*)normalized_path, list_it, 6 ,FTW_PHYS ,(void*)filelist)) //| FTW_DEPTH
     389             :       {
     390           0 :          perror( normalized_path );
     391           0 :          error("nftw return non 0\n");
     392           0 :          return ;
     393             :       }
     394             :    }
     395           3 :    else if (stat(item, &sb) == 0 && (S_ISLNK(sb.st_mode)|| S_ISREG(sb.st_mode)))
     396           3 :       add_to_file_list(normalized_path, sb.st_mode, filelist);
     397             : }
     398             : 
     399             : 
     400             : // public
     401           1 : int getfilelist(const char * projectdir,cJSON * paths,cJSON ** filelist)
     402             : {
     403           1 :    if (!projectdir || !paths || !filelist ) return -1;
     404             :    char tmp[PATH_MAX];
     405             :    cJSON * path;
     406           6 :    cJSON_ArrayForEach(path,paths)
     407             :    {
     408           5 :       int res =snprintf((char*)tmp,PATH_MAX,"%s/%s",projectdir,path->valuestring);
     409           5 :       if (res>=PATH_MAX) continue;
     410           5 :       debug("get filelist for path %s\n",tmp);
     411             :       wordexp_t word_re;
     412             :       // errors on undef and commands
     413           5 :       switch (wordexp(tmp, &word_re, WRDE_UNDEF))
     414             :       {
     415             :          case 0: /* Successful. */
     416             :             {
     417             :                int i;
     418           4 :                debug("wordexp arti path found %d matches",word_re.we_wordc);
     419          11 :                for (i=0;i<word_re.we_wordc;i++)
     420             :                {
     421             : 
     422           7 :                   getfilelist_item(projectdir,word_re.we_wordv[i],filelist);
     423             :                }
     424           4 :                wordfree (&word_re);
     425             :             }
     426           4 :             break;
     427             :          case WRDE_NOSPACE:
     428             :             /* If the error was WRDE_NOSPACE,
     429             :              then perhaps part of the result was allocated. */
     430           0 :             error("WRDE_NOSPACE \n");
     431           0 :             wordfree (&word_re);
     432           0 :             break;
     433             :          default: /* Some other error. */
     434           1 :             error("some othe wordexp error \n");
     435           1 :             break;
     436             :       }
     437             :       //cleanup
     438             :    }
     439             :    return 0;
     440             : }
     441             : 
     442           8 : void vrmdir(const char *dir, ...) {
     443           9 :         if (!dir) return;
     444           7 :         char *tmp=CSPRINTF(dir);
     445             :         struct stat sb;
     446             : 
     447           7 :         if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     448             :         {
     449           7 :                 if (nftw((char*)tmp, remove_it, 6 ,FTW_PHYS | FTW_DEPTH))
     450             :                 {
     451           0 :                         perror( tmp );
     452             :                 }
     453             :         }
     454           7 :         if (tmp) free(tmp);
     455             : }
     456             : 
     457           2 : void vrmdir_s(const char *dir, ...) {
     458           3 :         if (!dir) return;
     459           1 :         char *tmp=CSPRINTF(dir);
     460             :         struct stat sb;
     461             : 
     462           1 :         if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     463             :         {
     464           1 :                 if (nftw((char*)tmp, remove_it, 6 , FTW_DEPTH))
     465             :                 {
     466           0 :                         perror( tmp );
     467             :                 }
     468             :         }
     469           1 :         if (tmp) free(tmp);
     470             : }
     471             : 
     472           5 : int v_exist_dir(const char *dir, ...)
     473             : {
     474           5 :         if (!dir) return 0;
     475           4 :         char *tmp=CSPRINTF(dir);
     476             :         struct stat sb;
     477           4 :         int result=0;
     478           4 :         if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     479           2 :                 result=1;
     480           4 :         if (tmp) free(tmp);
     481           4 :         return result;
     482             : }
     483             : 
     484             : // mdir -p
     485           6 : void vmkdir(const char *dir, ...) {
     486           7 :         if (!dir) return;
     487           5 :         char *tmp=CSPRINTF(dir);
     488           5 :         char *p=NULL;
     489           5 :         size_t len=0;
     490             :         struct stat sb;
     491           5 :         if (tmp)
     492             :         {
     493           5 :                 if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     494             :                 {
     495             :                         //debug("directory %s exists\n",tmp);
     496             :                 }
     497             :                 else
     498             :                 {
     499           5 :                         len = strlen(tmp);
     500           5 :                         if(tmp[len - 1] == '/')
     501           1 :                                 tmp[len - 1] = 0;
     502             :                         //debug("mkdir %s\n",tmp);
     503          88 :                         for(p = tmp + 1; *p; p++)
     504          83 :                                 if(*p == '/') {
     505          13 :                                         *p = 0;
     506          13 :                                         if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     507             :                                         {
     508             :                                                 //debug("sub directory %s exists\n",tmp);
     509             :                                         }
     510             :                                         else{
     511             :                                                 //debug("mkdir sub %s\n",tmp);
     512           7 :                                                 mkdir(tmp,S_IRWXG | S_IRWXU);
     513             :                                         }
     514          13 :                                         *p = '/';
     515             :                                 }
     516             :                         //debug("mkdir sub %s\n",tmp);
     517           5 :                         mkdir(tmp, S_IRWXG | S_IRWXU);
     518             :                 }
     519           5 :                 free(tmp);
     520             :         }
     521             : }
     522             : 
     523           4 : char * vcmkdir(const char *dir, ...) {
     524           4 :     if (!dir) return NULL;
     525           3 :         char *tmp=CSPRINTF(dir);
     526           3 :         char *p=NULL;
     527           3 :         size_t len=0;
     528             :         struct stat sb;
     529           3 :         if (tmp)
     530             :         {
     531           3 :                 if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     532             :                 {
     533             :                         //debug("directory %s exists\n",tmp);
     534             :                 }
     535             :                 else
     536             :                 {
     537           3 :                         len = strlen(tmp);
     538           3 :                         if(tmp[len - 1] == '/')
     539           1 :                                 tmp[len - 1] = 0;
     540             :                         //debug("mkdir %s\n",tmp);
     541          45 :                         for(p = tmp + 1; *p; p++)
     542          42 :                                 if(*p == '/') {
     543           6 :                                         *p = 0;
     544           6 :                                         if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
     545             :                                         {
     546             :                                                 //debug("sub directory %s exists\n",tmp);
     547             :                                         }
     548             :                                         else{
     549             :                                                 //debug("mkdir sub %s\n",tmp);
     550           3 :                                                 mkdir(tmp,S_IRWXG | S_IRWXU);
     551             :                                         }
     552           6 :                                         *p = '/';
     553             :                                 }
     554             :                         //debug("mkdir sub %s\n",tmp);
     555           3 :                         mkdir(tmp, S_IRWXG | S_IRWXU);
     556             :                 }
     557             :         }
     558           3 :         return tmp;
     559             : }
     560             : 
     561             : 
     562          10 : int write_file_v(const char *data,size_t len,const char * filepath,... )
     563             : {
     564          10 :         if (!filepath) return -1;
     565           9 :         char * filename=CSPRINTF(filepath);
     566           9 :         if (!data) return -1;
     567           9 :         if(!filename)
     568             :         {
     569           0 :                 error("processing filepath, no memory???\n");
     570           0 :                 return -1;
     571             :         }
     572             : 
     573             :    FILE * f;
     574           9 :    if (len)
     575           8 :       f = fopen ( filename, "wb" );
     576             :    else
     577             :    {
     578           1 :       len=strlen(data);
     579           1 :       f = fopen ( filename, "w" );
     580             :    }
     581           9 :    if ( !f ) {
     582             :       /* handle error */
     583           2 :       free(filename);
     584           2 :       return -1;
     585             :    }
     586           7 :    size_t wrote=fwrite(data, 1, len, f);
     587           7 :    fclose(f);
     588           7 :         free(filename);
     589           7 :    return (wrote!=len);
     590             : }
     591             : 
     592             : 
     593           3 : char * read_a_file_v(const char * filename,...)
     594             : {
     595           3 :         if(!filename) return NULL;
     596           2 :         char * dirpath=CSPRINTF(filename);
     597             : 
     598           2 :         if(!dirpath)
     599             :         {
     600           0 :                 error("processing filepath, no memory???\n");
     601           0 :                 return NULL;
     602             :         }
     603             : 
     604           2 :    int f=open(dirpath,O_RDONLY);
     605           2 :    if (f==INVALID_SOCKET)
     606             :    {
     607             : 
     608           1 :       debug("read_v file %s: %s\n",dirpath,strerror(errno));
     609           1 :            free(dirpath);
     610           1 :       return NULL;
     611             :    }
     612           1 :    dynbuffer *mem=dynbuffer_init();
     613             :    char buf[0x10000];
     614           1 :    bzero(buf, 0x10000);
     615             : 
     616           1 :    ssize_t n=0;
     617           3 :    while ((n=read(f,buf,0xffff)) > 0)
     618             : 
     619             :       //   while( ( fgets( buf, 1023, f )) != NULL )
     620             :    {
     621           1 :       dynbuffer_write_n(buf, n, mem );
     622           1 :       bzero(buf, 0x10000);
     623             :    }
     624             :    // fclose(f);
     625           1 :         free(dirpath);
     626           1 :    close(f);
     627           1 :         char * result=NULL;
     628           1 :         dynbuffer_pop(&mem, &result, NULL);
     629           1 :    return result;
     630             : }
     631             : 
     632           5 : char * read_a_file(const char * dirpath)
     633             : {
     634           5 :    if (!dirpath) return NULL;
     635             :    //FILE *f = fopen(dirpath, "r");
     636             :    //if (f == NULL)
     637           4 :    int f=open(dirpath,O_RDONLY);
     638           4 :    if (f==INVALID_SOCKET)
     639             :    {
     640           1 :       debug("read_previous release.json: %s\n",strerror(errno));
     641           1 :       return NULL;
     642             :    }
     643           3 :    dynbuffer* mem=dynbuffer_init();
     644             :    char buf[0x10000];
     645           3 :    bzero(buf, 0x10000);
     646             : 
     647           3 :    ssize_t n=0;
     648           9 :    while ((n=read(f,buf,0xffff)) > 0)
     649             : 
     650             : //   while( ( fgets( buf, 1023, f )) != NULL )
     651             :    {
     652           3 :       dynbuffer_write_n(buf, n, mem );
     653           3 :       bzero(buf, 0x10000);
     654             :    }
     655             :   // fclose(f);
     656           3 :    close(f);
     657           3 :         char * result=NULL;
     658           3 :         dynbuffer_pop(&mem, &result, NULL);
     659           3 :         return result;
     660             : }
     661             : 
     662             : static int cp_file_x(const char * source,const char * destination, int append);
     663             : 
     664             : 
     665           5 : int cp_file(const char * source,const char * destination)
     666             : {
     667           5 :    return(cp_file_x(source, destination, 0));
     668             : }
     669           5 : int append_file_2_file(const char * source,const char * destination)
     670             : {
     671           5 :    return(cp_file_x(source, destination, 1));
     672             : }
     673             : 
     674           3 : int append_data_2_file(const char * data,const char * destination)
     675             : {
     676             :    FILE  *exeout;
     677           3 :    exeout = fopen(destination, "ab");
     678           3 :    if (exeout == NULL) {
     679             :       /* handle error */
     680           1 :       debug("error opening: %s\n",destination);
     681           1 :       perror("file open for writing");
     682           1 :       return(-1);
     683             :    }
     684             : 
     685           2 :    size_t n=strlen(data);
     686           2 :    size_t m = fwrite(data, 1, n, exeout);
     687           2 :    if (fclose(exeout)) perror("close output file");
     688           2 :    return (int)m;
     689             : }
     690             : 
     691          10 : static int cp_file_x(const char * source,const char * destination, int append)
     692             : {
     693          10 :         if (!source || !destination) return -1;
     694           6 :     ssize_t count=0;
     695             :    FILE *exein, *exeout;
     696           6 :    exein = fopen(source, "rb");
     697           6 :    if (exein == NULL) {
     698             :       /* handle error */
     699           2 :             debug("error opening: %s\n",source);
     700           2 :       perror("file open for reading");
     701           2 :       return(-1);
     702             :    }
     703           4 :    if (append)
     704           2 :         exeout = fopen(destination, "ab");
     705             :    else
     706           2 :       exeout = fopen(destination, "wb");
     707           4 :    if (exeout == NULL) {
     708             :       /* handle error */
     709           2 :       debug("error opening: %s\n",destination);
     710           2 :       perror("file open for writing");
     711           2 :        if (fclose(exein)) perror("close input file");
     712             :       return(-1);
     713             :    }
     714             :    size_t n, m;
     715             :    unsigned char buff[8192];
     716             :    do {
     717           4 :       n = fread(buff, 1, sizeof buff, exein);
     718           4 :       if (n) m = fwrite(buff, 1, n, exeout);
     719             :       else   m = 0;
     720           4 :       count=count+m;
     721           4 :    } while ((n > 0) && (n == m));
     722           2 :    if (m)
     723             :    {
     724           0 :       perror("copy");
     725           0 :       count=-1;
     726             :    }
     727           2 :    if (fclose(exeout)) perror("close output file");
     728           2 :    if (fclose(exein)) perror("close input file");
     729           2 :    return (int)count;
     730             : }
     731             : 
     732             : 
     733             : static char const SIZE_PREFIXES[] = "kMGTPEZY";
     734             : 
     735             : const char *
     736          10 : format_size(char buf[FORMAT_SIZE_BUF], uint64_t sz)
     737             : {
     738          10 :         memset(buf,0,FORMAT_SIZE_BUF);
     739          10 :    int pfx = 0;
     740             :    unsigned int m, rem, hrem;
     741             :    uint64_t a,n;
     742          10 :    if (sz <= 0) {
     743           1 :       memcpy(buf, "0 B", 3);
     744           1 :       return buf;
     745             :    }
     746           9 :    a = sz;
     747           9 :    if (a < 1000) {
     748           1 :       n = a;
     749           1 :       snprintf(buf, FORMAT_SIZE_BUF, "%llu B", n);
     750           1 :       return buf;
     751             :    }
     752           3 :    for (pfx = 0, hrem = 0; ; pfx++) {
     753          11 :       rem = a % 1000ULL;
     754          11 :       a = a / 1000ULL;
     755          11 :       if (!SIZE_PREFIXES[pfx + 1] || a < 1000ULL)
     756             :          break;
     757           3 :       hrem |= rem;
     758           3 :    }
     759           8 :    n = a;
     760           8 :    if (n < 10) {
     761           4 :       if (rem >= 950) {
     762           1 :          buf[0] = '1';
     763           1 :          buf[1] = '0';
     764           1 :          buf[2] = ' ';
     765           1 :          buf[3] = SIZE_PREFIXES[pfx];
     766           1 :          buf[4] = 'B';
     767           1 :          buf[5] = '\0';
     768           1 :          return buf;
     769             :       } else {
     770           3 :          m = rem / 100;
     771           3 :          rem = rem % 100;
     772           3 :          if (rem > 50 || (rem == 50 && ((m & 1) || hrem)))
     773           1 :             m++;
     774           3 :          snprintf(buf, FORMAT_SIZE_BUF,
     775           3 :                   "%llu.%u %cB", n, m, SIZE_PREFIXES[pfx]);
     776             :       }
     777             :    } else {
     778           4 :       if (rem > 500 || (rem == 500 && ((n & 1) || hrem)))
     779           1 :          n++;
     780           4 :       if (n >= 1000 && SIZE_PREFIXES[pfx + 1]) {
     781           1 :          buf[0] = '1';
     782           1 :          buf[1] = '.';
     783           1 :          buf[2] = '0';
     784           1 :          buf[3] = ' ';
     785           1 :          buf[4] = SIZE_PREFIXES[pfx+1];
     786           1 :          buf[5] = 'B';
     787           1 :          buf[6] = '\0';
     788             :       } else {
     789           3 :          snprintf(buf, FORMAT_SIZE_BUF,
     790           3 :                   "%llu %cB", n, SIZE_PREFIXES[pfx]);
     791             :       }
     792             :    }
     793             :    return buf;
     794             : }
     795             : 
     796             : 
     797             : 
     798             : 
     799          34 : char * cvaprintf(const char * __restrict format , va_list vargs)
     800             : {
     801             :         va_list vargf;
     802          34 :         va_copy(vargf, vargs);
     803             : 
     804          34 :         int size=vsnprintf(NULL,0 ,format,vargs);
     805          34 :         va_end(vargs);
     806          34 :         if (size<0) return NULL; else size++;
     807             : 
     808          34 :         char * result=calloc(1,size);
     809          34 :         size=vsnprintf(result,size ,format,vargf);
     810          34 :         va_end(vargf);
     811          34 :         if (size<0)
     812             :         {
     813           0 :                 if (result) free(result);
     814             :                 result=NULL;
     815             :         }
     816          34 :         return result;
     817             : }
     818             : 
     819           1 : void strip_nl(char * data)
     820             : {
     821           1 :         if(data)
     822             :         {
     823           2 :                 while (strlen(data)>1 && data[strlen(data)-1]=='\n') data[strlen(data)-1]='\0';
     824             :         }
     825           1 :         return;
     826             : }
     827             : 
     828           4 : char * get_opt_value(const char * optarg,const char* default_value)
     829             : {
     830           4 :         char * result=NULL;
     831           4 :         if (optarg)
     832             :         {
     833           2 :                 result=calloc(1,strlen(optarg)+1);
     834           2 :                 sprintf(result,"%s",optarg);
     835             :         }
     836           2 :         else if (default_value)
     837             :         {
     838           1 :                 result=calloc(1,strlen(default_value)+1);
     839           1 :                 sprintf(result,"%s",default_value);
     840             :         }
     841             :         else
     842             :         {
     843           1 :                 result=calloc(1,1);
     844             :         }
     845           4 :         return result;
     846             : }
     847             : 
     848             : #ifndef HAVEPIPE2
     849             : #define pipe2(x,y) ({ int res=pipe(x); if (res==0) { fcntl(x[0], F_SETFL, y); fcntl(x[1], F_SETFL, y);} res;})
     850             : #endif
     851             : 
     852           2 : int pipe_redirect_stderr(int my_pipe[2])
     853             : {
     854           2 :         int t=0;
     855           2 :         if ((t=pipe2(my_pipe,O_NONBLOCK|FD_CLOEXEC))==0)
     856             :         {
     857           2 :                 int e = dup(fileno(stderr));
     858           2 :                 dup2(my_pipe[1], 2);
     859           2 :                 return e;
     860             :         }
     861             :         else
     862             :                 return -1;
     863             : }
     864             : 
     865           2 : void pipe_redirect_undo(int my_pipe[2],int saved_stderr,char**errormsg)
     866             : {
     867           2 :         if (saved_stderr !=-1)
     868             :         {
     869             :                 char reading_buf[1024];
     870           2 :                 memset(reading_buf, 0, 1024);
     871           2 :                 fcntl(my_pipe[0], F_SETFL, O_NONBLOCK);
     872           2 :                 ssize_t r=read(my_pipe[0], reading_buf, 1024);
     873           2 :                 if (r>0)
     874           2 :                         asprintf(errormsg, "%s",reading_buf);
     875           2 :                 dup2(saved_stderr,fileno(stderr));
     876           2 :                 close(saved_stderr);
     877           2 :                 if (my_pipe[0]>0)close(my_pipe[0]);
     878           2 :                 if (my_pipe[1]>0)close(my_pipe[1]);
     879             :         }
     880           2 : }
     881             : 
     882             : 
     883          11 : int xis_dir (const char *d)
     884             : {
     885             :         DIR *dirptr;
     886             :         
     887          11 :         if (access ( d, F_OK ) != -1 ) {
     888             :                 // file exists
     889           5 :                 if ((dirptr = opendir (d)) != NULL) {
     890           5 :                         closedir (dirptr);
     891             :                 } else {
     892             :                         return -2; /* d exists, but not dir */
     893             :                 }
     894             :         } else {
     895             :                 return -1;     /* d does not exist */
     896             :         }
     897             :         
     898           5 :         return 0;
     899             : }

Generated by: LCOV version 1.13