LCOV - code coverage report
Current view: top level - lib/util - util_file.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 177 266 66.5 %
Date: 2024-04-21 15:09:00 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * SMB parameters and setup
       4             :  * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
       5             :  *
       6             :  * Added afdgets() Jelmer Vernooij 2005
       7             :  *
       8             :  * This program is free software; you can redistribute it and/or modify it under
       9             :  * the terms of the GNU General Public License as published by the Free
      10             :  * Software Foundation; either version 3 of the License, or (at your option)
      11             :  * any later version.
      12             :  *
      13             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      14             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      16             :  * more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License along with
      19             :  * this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "replace.h"
      23             : #include "system/shmem.h"
      24             : #include "system/filesys.h"
      25             : #include <talloc.h>
      26             : #include "lib/util/samba_util.h"
      27             : #include "lib/util/util_file.h"
      28             : #include "lib/util/sys_popen.h"
      29             : #include "lib/util/sys_rw.h"
      30             : #include "lib/util/debug.h"
      31             : 
      32             : /**
      33             :  * Read one line (data until next newline or eof) and allocate it
      34             :  */
      35       10372 : _PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint)
      36             : {
      37       10372 :         char *data = NULL;
      38       10372 :         ssize_t alloc_size = 0, offset = 0, ret;
      39        1081 :         int p;
      40             : 
      41       10372 :         if (hint <= 0) hint = 0x100;
      42             : 
      43        1087 :         do {
      44       10378 :                 alloc_size += hint;
      45             : 
      46       10378 :                 data = talloc_realloc(mem_ctx, data, char, alloc_size);
      47             : 
      48       10378 :                 if (!data)
      49           0 :                         return NULL;
      50             : 
      51       10378 :                 ret = read(fd, data + offset, hint);
      52             : 
      53       10378 :                 if (ret == 0) {
      54         198 :                         return NULL;
      55             :                 }
      56             : 
      57       10156 :                 if (ret == -1) {
      58           0 :                         talloc_free(data);
      59           0 :                         return NULL;
      60             :                 }
      61             : 
      62             :                 /* Find newline */
      63      237094 :                 for (p = 0; p < ret; p++) {
      64      237087 :                         if (data[offset + p] == '\n')
      65        9093 :                                 break;
      66             :                 }
      67             : 
      68       10156 :                 if (p < ret) {
      69       10149 :                         data[offset + p] = '\0';
      70             : 
      71             :                         /* Go back to position of newline */
      72       10149 :                         lseek(fd, p - ret + 1, SEEK_CUR);
      73       10149 :                         return data;
      74             :                 }
      75             : 
      76           7 :                 offset += ret;
      77             : 
      78           7 :         } while ((size_t)ret == hint);
      79             : 
      80           1 :         data[offset] = '\0';
      81             : 
      82           1 :         return data;
      83             : }
      84             : 
      85         274 : char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f)
      86             : {
      87         274 :         char *s = s2;
      88         274 :         size_t len = 0;
      89           0 :         int c;
      90         274 :         bool start_of_line = true;
      91             : 
      92         274 :         if (feof(f)) {
      93           0 :                 return NULL;
      94             :         }
      95             : 
      96         274 :         if (maxlen < 2) {
      97           0 :                 return NULL;
      98             :         }
      99             : 
     100         274 :         if (s2 == NULL) {
     101          42 :                 maxlen = MIN(maxlen,8);
     102          42 :                 s = talloc_array(mem_ctx, char, maxlen);
     103             :         }
     104             : 
     105         274 :         if (s == NULL) {
     106           0 :                 return NULL;
     107             :         }
     108             : 
     109         274 :         *s = 0;
     110             : 
     111        4068 :         while (len < maxlen-1) {
     112        4068 :                 c = getc(f);
     113        4068 :                 switch (c)
     114             :                 {
     115           0 :                     case '\r':
     116           0 :                             break;
     117         194 :                     case '\n':
     118         194 :                             while (len > 0 && s[len-1] == ' ') {
     119           0 :                                     s[--len] = 0;
     120             :                             }
     121         194 :                             if (len > 0 && s[len-1] == '\\') {
     122           0 :                                     s[--len] = 0;
     123           0 :                                     start_of_line = true;
     124           0 :                                     break;
     125             :                             }
     126         194 :                             return s;
     127          80 :                     case EOF:
     128          80 :                             if (len <= 0 && (s2 == NULL)) {
     129          42 :                                     TALLOC_FREE(s);
     130             :                             }
     131          80 :                             return (len>0) ? s : NULL;
     132         308 :                     case ' ':
     133         308 :                             if (start_of_line) {
     134           0 :                                     break;
     135             :                             }
     136             : 
     137           0 :                             FALL_THROUGH;
     138             :                     default:
     139        3794 :                             start_of_line = false;
     140        3794 :                             s[len++] = c;
     141        3794 :                             s[len] = 0;
     142             :                 }
     143        3794 :                 if ((s2 == NULL) && (len > maxlen-3)) {
     144           0 :                         size_t m;
     145           0 :                         char *t;
     146             : 
     147           0 :                         m = maxlen * 2;
     148           0 :                         if (m < maxlen) {
     149           0 :                                 DBG_ERR("length overflow\n");
     150           0 :                                 TALLOC_FREE(s);
     151           0 :                                 return NULL;
     152             :                         }
     153           0 :                         maxlen = m;
     154             : 
     155           0 :                         t = talloc_realloc(mem_ctx, s, char, maxlen);
     156           0 :                         if (t == NULL) {
     157           0 :                                 DBG_ERR("failed to expand buffer!\n");
     158           0 :                                 TALLOC_FREE(s);
     159           0 :                                 return NULL;
     160             :                         }
     161             : 
     162           0 :                         s = t;
     163             :                 }
     164             :         }
     165             : 
     166           0 :         return s;
     167             : }
     168             : 
     169             : /**
     170             : load a file into memory from a fd.
     171             : **/
     172        1673 : _PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ctx)
     173             : {
     174          38 :         FILE *file;
     175        1673 :         char *p = NULL;
     176        1673 :         size_t size = 0;
     177        1673 :         size_t chunk = 1024;
     178          38 :         int err;
     179             : 
     180        1673 :         if (maxsize == 0) {
     181        1652 :                 maxsize = SIZE_MAX;
     182             :         }
     183             : 
     184        1673 :         file = fdopen_keepfd(fd, "r");
     185        1673 :         if (file == NULL) {
     186           0 :                 return NULL;
     187             :         }
     188             : 
     189        2262 :         while (size < maxsize) {
     190         466 :                 size_t newbufsize;
     191         466 :                 size_t nread;
     192             : 
     193        2261 :                 chunk = MIN(chunk, (maxsize - size));
     194             : 
     195        2261 :                 newbufsize = size + (chunk+1); /* chunk+1 can't overflow */
     196        2261 :                 if (newbufsize < size) {
     197           0 :                         goto fail; /* overflow */
     198             :                 }
     199             : 
     200        2261 :                 p = talloc_realloc(mem_ctx, p, char, newbufsize);
     201        2261 :                 if (p == NULL) {
     202           0 :                         goto fail;
     203             :                 }
     204             : 
     205        2261 :                 nread = fread(p+size, 1, chunk, file);
     206        2261 :                 size += nread;
     207             : 
     208        2261 :                 if (nread != chunk) {
     209        1635 :                         break;
     210             :                 }
     211             :         }
     212             : 
     213        1673 :         err = ferror(file);
     214        1673 :         if (err != 0) {
     215           0 :                 goto fail;
     216             :         }
     217             : 
     218        1673 :         p[size] = '\0';
     219             : 
     220        1673 :         if (psize != NULL) {
     221        1673 :                 *psize = size;
     222             :         }
     223             : 
     224        1673 :         fclose(file);
     225        1673 :         return p;
     226             : 
     227           0 : fail:
     228           0 :         TALLOC_FREE(p);
     229           0 :         fclose(file);
     230           0 :         return NULL;
     231             : }
     232             : 
     233             : /**
     234             : load a file into memory
     235             : **/
     236         246 : _PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx)
     237             : {
     238          40 :         int fd;
     239          40 :         char *p;
     240             : 
     241         246 :         if (!fname || !*fname) return NULL;
     242             : 
     243         246 :         fd = open(fname,O_RDONLY);
     244         246 :         if (fd == -1) return NULL;
     245             : 
     246         214 :         p = fd_load(fd, size, maxsize, mem_ctx);
     247             : 
     248         214 :         close(fd);
     249             : 
     250         214 :         return p;
     251             : }
     252             : 
     253             : /**
     254             : parse a buffer into lines
     255             : 'p' will be freed on error, and otherwise will be made a child of the returned array
     256             : **/
     257        3262 : static char **file_lines_parse_internal(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx)
     258             : {
     259          13 :         unsigned int i;
     260          13 :         char *s, **ret;
     261             : 
     262        3262 :         if (!p) return NULL;
     263             : 
     264      451925 :         for (s = p, i=0; s < p+size; s++) {
     265      448663 :                 if (s[0] == '\n') i++;
     266             :         }
     267             : 
     268        3262 :         ret = talloc_zero_array(mem_ctx, char *, i+2);
     269        3262 :         if (!ret) {
     270           0 :                 talloc_free(p);
     271           0 :                 return NULL;
     272             :         }
     273             : 
     274        3262 :         talloc_steal(ret, p);
     275             : 
     276        3262 :         ret[0] = p;
     277      451925 :         for (s = p, i=1; s < p+size; s++) {
     278      448663 :                 if (s[0] == '\n') {
     279       13138 :                         s[0] = 0;
     280       13138 :                         ret[i] = s+1;
     281       13138 :                         i++;
     282             :                 }
     283      448663 :                 if (s[0] == '\r') s[0] = 0;
     284             :         }
     285             : 
     286             :         /* remove any blank lines at the end */
     287        6535 :         while (i > 0 && ret[i-1][0] == 0) {
     288        3253 :                 i--;
     289             :         }
     290             : 
     291        3262 :         if (numlines) *numlines = i;
     292             : 
     293        3249 :         return ret;
     294             : }
     295             : 
     296             : 
     297             : /**
     298             : load a file into memory and return an array of pointers to lines in the file
     299             : must be freed with talloc_free().
     300             : **/
     301         142 : _PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
     302             : {
     303          14 :         char *p;
     304          14 :         size_t size;
     305             : 
     306         142 :         p = file_load(fname, &size, maxsize, mem_ctx);
     307         142 :         if (!p) return NULL;
     308             : 
     309         110 :         return file_lines_parse_internal(p, size, numlines, mem_ctx);
     310             : }
     311             : 
     312             : /**
     313             : load a fd into memory and return an array of pointers to lines in the file
     314             : must be freed with talloc_free(). If convert is true calls unix_to_dos on
     315             : the list.
     316             : **/
     317        1451 : _PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
     318             : {
     319           0 :         char *p;
     320           0 :         size_t size;
     321             : 
     322        1451 :         p = fd_load(fd, &size, maxsize, mem_ctx);
     323        1451 :         if (!p) return NULL;
     324             : 
     325        1451 :         return file_lines_parse_internal(p, size, numlines, mem_ctx);
     326             : }
     327             : 
     328        1701 : _PUBLIC_ char **file_lines_parse(const char *p_in,
     329             :                         size_t size,
     330             :                         int *numlines,
     331             :                         TALLOC_CTX *mem_ctx)
     332             : {
     333             :         /*
     334             :          * Copy the incoming string so it can end up
     335             :          * being owned by the returned pointer and
     336             :          * freed when that is.
     337             :          */
     338        1701 :         char *p = talloc_strdup(mem_ctx, p_in);
     339        1701 :         if (p == NULL) {
     340           0 :                 return NULL;
     341             :         }
     342        1701 :         return file_lines_parse_internal(p, size, numlines, mem_ctx);
     343             : }
     344             : 
     345      753050 : _PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
     346             :                              size_t length, mode_t mode)
     347             : {
     348           8 :         ssize_t num_written;
     349           8 :         int fd;
     350      753050 :         fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, mode);
     351      753050 :         if (fd == -1) {
     352      405979 :                 return false;
     353             :         }
     354      347071 :         num_written = write(fd, packet, length);
     355      347071 :         if (num_written == -1 || (size_t)num_written != length) {
     356           0 :                 close(fd);
     357           0 :                 return false;
     358             :         }
     359      347071 :         close(fd);
     360      347071 :         return true;
     361             : }
     362             : 
     363             : /**
     364             :   save a lump of data into a file. Mostly used for debugging
     365             : */
     366      753017 : _PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
     367             : {
     368      753017 :         return file_save_mode(fname, packet, length, 0644);
     369             : }
     370             : 
     371          10 : _PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap)
     372             : {
     373          10 :         char *p;
     374          10 :         int len, ret;
     375          10 :         va_list ap2;
     376             : 
     377          10 :         va_copy(ap2, ap);
     378          10 :         len = vasprintf(&p, format, ap2);
     379          10 :         va_end(ap2);
     380          10 :         if (len <= 0) return len;
     381          10 :         ret = write(fd, p, len);
     382          10 :         SAFE_FREE(p);
     383           0 :         return ret;
     384             : }
     385             : 
     386          10 : _PUBLIC_ int fdprintf(int fd, const char *format, ...)
     387             : {
     388          10 :         va_list ap;
     389          10 :         int ret;
     390             : 
     391          10 :         va_start(ap, format);
     392          10 :         ret = vfdprintf(fd, format, ap);
     393          10 :         va_end(ap);
     394          10 :         return ret;
     395             : }
     396             : 
     397             : 
     398             : /*
     399             :   compare two files, return true if the two files have the same content
     400             :  */
     401           0 : bool file_compare(const char *path1, const char *path2)
     402             : {
     403           0 :         FILE *f1 = NULL, *f2 = NULL;
     404           0 :         uint8_t buf1[1024], buf2[1024];
     405           0 :         bool ret = false;
     406             : 
     407           0 :         f1 = fopen(path1, "r");
     408           0 :         if (f1 == NULL) {
     409           0 :                 goto done;
     410             :         }
     411           0 :         f2 = fopen(path2, "r");
     412           0 :         if (f2 == NULL) {
     413           0 :                 goto done;
     414             :         }
     415             : 
     416           0 :         while (!feof(f1)) {
     417           0 :                 size_t n1 = fread(buf1, 1, sizeof(buf1), f1);
     418           0 :                 size_t n2 = fread(buf2, 1, sizeof(buf2), f2);
     419             : 
     420           0 :                 if (n1 != n2) {
     421           0 :                         goto done;
     422             :                 }
     423           0 :                 if (n1 == 0) {
     424           0 :                         ret = (feof(f1) && feof(f2));
     425           0 :                         goto done;
     426             :                 }
     427           0 :                 if (memcmp(buf1, buf2, n1) != 0) {
     428           0 :                         goto done;
     429             :                 }
     430           0 :                 if (n1 < sizeof(buf1)) {
     431           0 :                         bool has_error = (ferror(f1) || ferror(f2));
     432           0 :                         if (has_error) {
     433           0 :                                 goto done;
     434             :                         }
     435             :                 }
     436             :         }
     437           0 :         ret = true;
     438           0 : done:
     439           0 :         if (f2 != NULL) {
     440           0 :                 fclose(f2);
     441             :         }
     442           0 :         if (f1 != NULL) {
     443           0 :                 fclose(f1);
     444             :         }
     445           0 :         return ret;
     446             : }
     447             : 
     448             : /**
     449             :  Load from a pipe into memory.
     450             : **/
     451         930 : char *file_ploadv(char * const argl[], size_t *size)
     452             : {
     453           0 :         int fd, n;
     454         930 :         char *p = NULL;
     455           0 :         char buf[1024];
     456           0 :         size_t total;
     457             : 
     458         930 :         fd = sys_popenv(argl);
     459         930 :         if (fd == -1) {
     460           0 :                 return NULL;
     461             :         }
     462             : 
     463         930 :         total = 0;
     464             : 
     465        1864 :         while ((n = sys_read(fd, buf, sizeof(buf))) > 0) {
     466         934 :                 p = talloc_realloc(NULL, p, char, total + n + 1);
     467         934 :                 if (p == NULL) {
     468           0 :                         DBG_ERR("failed to expand buffer!\n");
     469           0 :                         close(fd);
     470           0 :                         return NULL;
     471             :                 }
     472         934 :                 memcpy(p+total, buf, n);
     473         934 :                 total += n;
     474             :         }
     475             : 
     476         930 :         if (p != NULL) {
     477         930 :                 p[total] = 0;
     478             :         }
     479             : 
     480             :         /*
     481             :          * FIXME: Perhaps ought to check that the command completed
     482             :          * successfully (returned 0); if not the data may be
     483             :          * truncated.
     484             :          */
     485         930 :         sys_pclose(fd);
     486             : 
     487         930 :         if (size) {
     488         930 :                 *size = total;
     489             :         }
     490             : 
     491         930 :         return p;
     492             : }
     493             : 
     494             : /*
     495             :  * fopen a dup'ed fd. Prevent fclose to close the fd passed in.
     496             :  *
     497             :  * Don't use on fd's that have fcntl locks, on error it will close the
     498             :  * dup'ed fd, thus killing your fcntl locks.
     499             :  */
     500        1673 : FILE *fdopen_keepfd(int fd, const char *mode)
     501             : {
     502        1673 :         FILE *f = NULL;
     503          38 :         int dup_fd;
     504             : 
     505        1673 :         dup_fd = dup(fd);
     506        1673 :         if (dup_fd == -1) {
     507           0 :                 return NULL;
     508             :         }
     509             : 
     510        1673 :         f = fdopen(dup_fd, mode);
     511        1673 :         if (f == NULL) {
     512           0 :                 int err = errno;
     513           0 :                 close(dup_fd);
     514           0 :                 errno = err;
     515           0 :                 return NULL;
     516             :         }
     517             : 
     518        1635 :         return f;
     519             : }

Generated by: LCOV version 1.14