LCOV - code coverage report
Current view: top level - utils/private - utils_c_system.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 33.3 % 69 23
Test Date: 2026-01-29 18:28:55 Functions: 80.0 % 5 4

            Line data    Source code
       1              : //! ***********************************************************************
       2              : //!
       3              : //!   Copyright (C) 2018 Robert Farmer & The MESA Team
       4              : //!
       5              : //!   This program is free software: you can redistribute it and/or modify
       6              : //!   it under the terms of the GNU Lesser General Public License
       7              : //!   as published by the Free Software Foundation,
       8              : //!   either version 3 of the License, or (at your option) any later version.
       9              : //!
      10              : //!   This program is distributed in the hope that it will be useful,
      11              : //!   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : //!   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : //!   See the GNU Lesser General Public License for more details.
      14              : //!
      15              : //!   You should have received a copy of the GNU Lesser General Public License
      16              : //!   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : //!
      18              : //! ***********************************************************************
      19              : 
      20              : #include "utils_c_system.h"
      21              : #include <dirent.h>
      22              : #include <errno.h>
      23              : #include <fcntl.h>
      24              : #include <stdbool.h>
      25              : #include <stdio.h>
      26              : #include <stdlib.h>
      27              : #include <string.h>
      28              : #include <sys/stat.h> /* mkdir(2) */
      29              : #include <sys/types.h>
      30              : #include <unistd.h>
      31              : 
      32              : #define PATHLEN 4096
      33              : static const int SUCCESS = 0;
      34              : static const char TEMPLATE[] = ".temp-XXXXXX";
      35              : 
      36              : /* Makes a single directory at path (mkdir path) */
      37           64 : int c_mkdir(const char *restrict path) {
      38              : 
      39              :     // If folder already exists return, don't relay on EEXIST as sometimes
      40              :     // EACCES happens first
      41           64 :     if (is_dir(path) == 1) {
      42              :         return SUCCESS;
      43              :     }
      44              : 
      45           27 :     if (mkdir(path, S_IRWXU) != SUCCESS) {
      46            0 :         if (errno != EEXIST) {
      47            0 :             printf("MKDIR error on '%s' Errno %d :: %s\n", path, errno,
      48              :                    strerror(errno));
      49            0 :             return -1;
      50              :         }
      51              :     }
      52              :     return SUCCESS;
      53              : }
      54              : 
      55              : /* Makes a directory at path, potentially making needed parent directories
      56              :  * (mkdir -p path) */
      57           30 : int c_mkdir_p(const char *restrict path) {
      58           30 :     char _path[PATHLEN];
      59           30 :     char *p;
      60              : 
      61              :     // If folder already exists return, don't relay on EEXIST as sometimes
      62              :     // EACCES happens first
      63           30 :     if (is_dir(path) == 1) {
      64              :         return SUCCESS;
      65              :     }
      66              : 
      67           20 :     if (strlen(path) >= PATHLEN) {
      68              :         return -1;
      69              :     }
      70              : 
      71           20 :     strcpy(_path, path);
      72              : 
      73              :     /* Iterate the string */
      74          542 :     for (p = _path + 1; *p; p++) {
      75          522 :         if (*p == '/') {
      76              :             /* Temporarily truncate */
      77           44 :             *p = '\0';
      78              : 
      79           44 :             if (c_mkdir(_path) != SUCCESS) {
      80              :                 return -1;
      81              :             }
      82              : 
      83           44 :             *p = '/';
      84              :         }
      85              :     }
      86           20 :     if (c_mkdir(_path) != SUCCESS) {
      87              :         return -1;
      88              :     }
      89              : 
      90              :     return SUCCESS;
      91              : }
      92              : 
      93          102 : int is_dir(const char *restrict path) {
      94          102 :     DIR *dir = opendir(path);
      95          102 :     if (dir) {
      96           53 :         closedir(dir);
      97           53 :         return 1;
      98              :     } else {
      99              :         return 0;
     100              :     }
     101              : }
     102              : 
     103              : /* Moves file src to dest (mv src dest)
     104              :  * if src and dest are on the same filesystem, then mv the files
     105              :  * if not, copy src to a temp file on same filesystem as dest then mv the temp
     106              :  * file to dest, this prevents the filesystem ever being in a inconsistent
     107              :  * state. dest either does not exist or does exist and is "full", thus we
     108              :  * prevent problems with other programs reading the file before its finished
     109              :  * being written.
     110              :  */
     111              : 
     112          213 : int c_mv(const char *restrict src, const char *restrict dest) {
     113          213 :     char dest_temp[PATHLEN];
     114              : 
     115          213 :     if (rename(src, dest) == SUCCESS) {
     116              :         return SUCCESS;
     117              :     }
     118              : 
     119            0 :     if (errno != EXDEV) {
     120              :         return -1;
     121              :     }
     122              : 
     123            0 :     if (strlen(dest) >= PATHLEN) {
     124              :         return -1;
     125              :     }
     126              : 
     127            0 :     strcpy(dest_temp, dest);
     128              : 
     129            0 :     size_t i = strlen(dest);
     130            0 :     while (i) {
     131            0 :         if (dest_temp[i - 1] == '/') {
     132              :             break;
     133              :         }
     134              : 
     135              :         i--;
     136              :     }
     137              : 
     138            0 :     if (strlen(TEMPLATE) >= PATHLEN - i) {
     139              :         return -1;
     140              :     }
     141              : 
     142            0 :     strcpy(dest_temp + i, TEMPLATE);
     143              : 
     144            0 :     int fd = mkstemp(dest_temp);
     145              : 
     146            0 :     if (fd == -1) {
     147              :         return -1;
     148              :     }
     149              : 
     150            0 :     close(fd);
     151              : 
     152            0 :     if (c_cp(src, dest_temp) != SUCCESS) {
     153            0 :         remove(dest_temp);
     154            0 :         return -1;
     155              :     }
     156              : 
     157            0 :     if (rename(dest_temp, dest) != SUCCESS) {
     158            0 :         remove(dest_temp);
     159            0 :         return -1;
     160              :     }
     161              : 
     162            0 :     remove(src);
     163              : 
     164            0 :     return SUCCESS;
     165              : }
     166              : 
     167              : /* copies file src to dest (cp src dest) */
     168            0 : int c_cp(const char *restrict src, const char *restrict dest) {
     169            0 :     const int BUF_SIZE = 4096;
     170            0 :     int fd_src, fd_dest;
     171            0 :     char buf[BUF_SIZE];
     172            0 :     ssize_t numRead;
     173            0 :     const int dbg = false;
     174              : 
     175            0 :     if (dbg) {
     176              :         printf("cp %s to %s\n", src, dest);
     177              :     }
     178              : 
     179            0 :     fd_src = open(src, O_RDONLY);
     180            0 :     if (fd_src < 0) {
     181              :         return -1;
     182              :     }
     183              : 
     184            0 :     fd_dest = open(dest, O_CREAT | O_WRONLY | O_TRUNC,
     185              :                    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
     186            0 :     if (fd_dest < 0) {
     187            0 :         goto error;
     188              :     }
     189              : 
     190            0 :     while ((numRead = read(fd_src, buf, BUF_SIZE)) > 0) {
     191            0 :         if (write(fd_dest, buf, numRead) != numRead) {
     192            0 :             goto error;
     193              :         }
     194              :     }
     195              : 
     196            0 :     if (numRead == -1) {
     197            0 :         goto error;
     198              :     }
     199              : 
     200            0 :     close(fd_src);
     201            0 :     close(fd_dest);
     202              : 
     203            0 :     return SUCCESS;
     204              : 
     205            0 : error:
     206            0 :     close(fd_src);
     207            0 :     if (fd_dest >= 0) {
     208            0 :         close(fd_dest);
     209              :     }
     210              :     return -2;
     211              : }
        

Generated by: LCOV version 2.0-1