LCOV - code coverage report
Current view: top level - lib/util - util_file.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 172 258 66.7 %
Date: 2024-02-29 22:57:05 Functions: 13 14 92.9 %

          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/sys_popen.h"
      28             : #include "lib/util/sys_rw.h"
      29             : #include "lib/util/debug.h"
      30             : 
      31             : /**
      32             :  * Read one line (data until next newline or eof) and allocate it
      33             :  */
      34       10388 : _PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint)
      35             : {
      36       10388 :         char *data = NULL;
      37       10388 :         ssize_t alloc_size = 0, offset = 0, ret;
      38        1081 :         int p;
      39             : 
      40       10388 :         if (hint <= 0) hint = 0x100;
      41             : 
      42        1087 :         do {
      43       10394 :                 alloc_size += hint;
      44             : 
      45       10394 :                 data = talloc_realloc(mem_ctx, data, char, alloc_size);
      46             : 
      47       10394 :                 if (!data)
      48           0 :                         return NULL;
      49             : 
      50       10394 :                 ret = read(fd, data + offset, hint);
      51             : 
      52       10394 :                 if (ret == 0) {
      53         198 :                         return NULL;
      54             :                 }
      55             : 
      56       10172 :                 if (ret == -1) {
      57           0 :                         talloc_free(data);
      58           0 :                         return NULL;
      59             :                 }
      60             : 
      61             :                 /* Find newline */
      62      237318 :                 for (p = 0; p < ret; p++) {
      63      237311 :                         if (data[offset + p] == '\n')
      64        9109 :                                 break;
      65             :                 }
      66             : 
      67       10172 :                 if (p < ret) {
      68       10165 :                         data[offset + p] = '\0';
      69             : 
      70             :                         /* Go back to position of newline */
      71       10165 :                         lseek(fd, p - ret + 1, SEEK_CUR);
      72       10165 :                         return data;
      73             :                 }
      74             : 
      75           7 :                 offset += ret;
      76             : 
      77           7 :         } while ((size_t)ret == hint);
      78             : 
      79           1 :         data[offset] = '\0';
      80             : 
      81           1 :         return data;
      82             : }
      83             : 
      84         274 : char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f)
      85             : {
      86         274 :         char *s = s2;
      87         274 :         size_t len = 0;
      88           0 :         int c;
      89         274 :         bool start_of_line = true;
      90             : 
      91         274 :         if (feof(f)) {
      92           0 :                 return NULL;
      93             :         }
      94             : 
      95         274 :         if (maxlen < 2) {
      96           0 :                 return NULL;
      97             :         }
      98             : 
      99         274 :         if (s2 == NULL) {
     100          42 :                 maxlen = MIN(maxlen,8);
     101          42 :                 s = talloc_array(mem_ctx, char, maxlen);
     102             :         }
     103             : 
     104         274 :         if (s == NULL) {
     105           0 :                 return NULL;
     106             :         }
     107             : 
     108         274 :         *s = 0;
     109             : 
     110        4068 :         while (len < maxlen-1) {
     111        4068 :                 c = getc(f);
     112        4068 :                 switch (c)
     113             :                 {
     114           0 :                     case '\r':
     115           0 :                             break;
     116         194 :                     case '\n':
     117         194 :                             while (len > 0 && s[len-1] == ' ') {
     118           0 :                                     s[--len] = 0;
     119             :                             }
     120         194 :                             if (len > 0 && s[len-1] == '\\') {
     121           0 :                                     s[--len] = 0;
     122           0 :                                     start_of_line = true;
     123           0 :                                     break;
     124             :                             }
     125         194 :                             return s;
     126          80 :                     case EOF:
     127          80 :                             if (len <= 0 && (s2 == NULL)) {
     128          42 :                                     TALLOC_FREE(s);
     129             :                             }
     130          80 :                             return (len>0) ? s : NULL;
     131         308 :                     case ' ':
     132         308 :                             if (start_of_line) {
     133           0 :                                     break;
     134             :                             }
     135             : 
     136           0 :                             FALL_THROUGH;
     137             :                     default:
     138        3794 :                             start_of_line = false;
     139        3794 :                             s[len++] = c;
     140        3794 :                             s[len] = 0;
     141             :                 }
     142        3794 :                 if ((s2 == NULL) && (len > maxlen-3)) {
     143           0 :                         size_t m;
     144           0 :                         char *t;
     145             : 
     146           0 :                         m = maxlen * 2;
     147           0 :                         if (m < maxlen) {
     148           0 :                                 DBG_ERR("length overflow\n");
     149           0 :                                 TALLOC_FREE(s);
     150           0 :                                 return NULL;
     151             :                         }
     152           0 :                         maxlen = m;
     153             : 
     154           0 :                         t = talloc_realloc(mem_ctx, s, char, maxlen);
     155           0 :                         if (t == NULL) {
     156           0 :                                 DBG_ERR("failed to expand buffer!\n");
     157           0 :                                 TALLOC_FREE(s);
     158           0 :                                 return NULL;
     159             :                         }
     160             : 
     161           0 :                         s = t;
     162             :                 }
     163             :         }
     164             : 
     165           0 :         return s;
     166             : }
     167             : 
     168             : /**
     169             : load a file into memory from a fd.
     170             : **/
     171        1677 : _PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ctx)
     172             : {
     173          38 :         FILE *file;
     174        1677 :         char *p = NULL;
     175        1677 :         size_t size = 0;
     176        1677 :         size_t chunk = 1024;
     177          38 :         int err;
     178          38 :         int fd_dup;
     179             : 
     180        1677 :         if (maxsize == 0) {
     181        1656 :                 maxsize = SIZE_MAX;
     182             :         }
     183             : 
     184        1677 :         fd_dup = dup(fd);
     185        1677 :         if (fd_dup == -1) {
     186           0 :                 return NULL;
     187             :         }
     188             : 
     189        1677 :         file = fdopen(fd_dup, "r");
     190        1677 :         if (file == NULL) {
     191           0 :                 close(fd_dup);
     192           0 :                 return NULL;
     193             :         }
     194             : 
     195        2266 :         while (size < maxsize) {
     196         466 :                 size_t newbufsize;
     197         466 :                 size_t nread;
     198             : 
     199        2265 :                 chunk = MIN(chunk, (maxsize - size));
     200             : 
     201        2265 :                 newbufsize = size + (chunk+1); /* chunk+1 can't overflow */
     202        2265 :                 if (newbufsize < size) {
     203           0 :                         goto fail; /* overflow */
     204             :                 }
     205             : 
     206        2265 :                 p = talloc_realloc(mem_ctx, p, char, newbufsize);
     207        2265 :                 if (p == NULL) {
     208           0 :                         goto fail;
     209             :                 }
     210             : 
     211        2265 :                 nread = fread(p+size, 1, chunk, file);
     212        2265 :                 size += nread;
     213             : 
     214        2265 :                 if (nread != chunk) {
     215        1639 :                         break;
     216             :                 }
     217             :         }
     218             : 
     219        1677 :         err = ferror(file);
     220        1677 :         if (err != 0) {
     221           0 :                 goto fail;
     222             :         }
     223             : 
     224        1677 :         p[size] = '\0';
     225             : 
     226        1677 :         if (psize != NULL) {
     227        1677 :                 *psize = size;
     228             :         }
     229             : 
     230        1677 :         fclose(file);
     231        1677 :         return p;
     232             : 
     233           0 : fail:
     234           0 :         TALLOC_FREE(p);
     235           0 :         fclose(file);
     236           0 :         return NULL;
     237             : }
     238             : 
     239             : /**
     240             : load a file into memory
     241             : **/
     242         246 : _PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx)
     243             : {
     244          40 :         int fd;
     245          40 :         char *p;
     246             : 
     247         246 :         if (!fname || !*fname) return NULL;
     248             : 
     249         246 :         fd = open(fname,O_RDONLY);
     250         246 :         if (fd == -1) return NULL;
     251             : 
     252         212 :         p = fd_load(fd, size, maxsize, mem_ctx);
     253             : 
     254         212 :         close(fd);
     255             : 
     256         212 :         return p;
     257             : }
     258             : 
     259             : /**
     260             : parse a buffer into lines
     261             : 'p' will be freed on error, and otherwise will be made a child of the returned array
     262             : **/
     263        3258 : static char **file_lines_parse_internal(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx)
     264             : {
     265          13 :         unsigned int i;
     266          13 :         char *s, **ret;
     267             : 
     268        3258 :         if (!p) return NULL;
     269             : 
     270      451852 :         for (s = p, i=0; s < p+size; s++) {
     271      448594 :                 if (s[0] == '\n') i++;
     272             :         }
     273             : 
     274        3258 :         ret = talloc_zero_array(mem_ctx, char *, i+2);
     275        3258 :         if (!ret) {
     276           0 :                 talloc_free(p);
     277           0 :                 return NULL;
     278             :         }
     279             : 
     280        3258 :         talloc_steal(ret, p);
     281             : 
     282        3258 :         ret[0] = p;
     283      451852 :         for (s = p, i=1; s < p+size; s++) {
     284      448594 :                 if (s[0] == '\n') {
     285       13123 :                         s[0] = 0;
     286       13123 :                         ret[i] = s+1;
     287       13123 :                         i++;
     288             :                 }
     289      448594 :                 if (s[0] == '\r') s[0] = 0;
     290             :         }
     291             : 
     292             :         /* remove any blank lines at the end */
     293        6527 :         while (i > 0 && ret[i-1][0] == 0) {
     294        3249 :                 i--;
     295             :         }
     296             : 
     297        3258 :         if (numlines) *numlines = i;
     298             : 
     299        3245 :         return ret;
     300             : }
     301             : 
     302             : 
     303             : /**
     304             : load a file into memory and return an array of pointers to lines in the file
     305             : must be freed with talloc_free().
     306             : **/
     307         142 : _PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
     308             : {
     309          14 :         char *p;
     310          14 :         size_t size;
     311             : 
     312         142 :         p = file_load(fname, &size, maxsize, mem_ctx);
     313         142 :         if (!p) return NULL;
     314             : 
     315         108 :         return file_lines_parse_internal(p, size, numlines, mem_ctx);
     316             : }
     317             : 
     318             : /**
     319             : load a fd into memory and return an array of pointers to lines in the file
     320             : must be freed with talloc_free(). If convert is true calls unix_to_dos on
     321             : the list.
     322             : **/
     323        1457 : _PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
     324             : {
     325           0 :         char *p;
     326           0 :         size_t size;
     327             : 
     328        1457 :         p = fd_load(fd, &size, maxsize, mem_ctx);
     329        1457 :         if (!p) return NULL;
     330             : 
     331        1457 :         return file_lines_parse_internal(p, size, numlines, mem_ctx);
     332             : }
     333             : 
     334        1693 : _PUBLIC_ char **file_lines_parse(const char *p_in,
     335             :                         size_t size,
     336             :                         int *numlines,
     337             :                         TALLOC_CTX *mem_ctx)
     338             : {
     339             :         /*
     340             :          * Copy the incoming string so it can end up
     341             :          * being owned by the returned pointer and
     342             :          * freed when that is.
     343             :          */
     344        1693 :         char *p = talloc_strdup(mem_ctx, p_in);
     345        1693 :         if (p == NULL) {
     346           0 :                 return NULL;
     347             :         }
     348        1693 :         return file_lines_parse_internal(p, size, numlines, mem_ctx);
     349             : }
     350             : 
     351      753600 : _PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
     352             :                              size_t length, mode_t mode)
     353             : {
     354           8 :         ssize_t num_written;
     355           8 :         int fd;
     356      753600 :         fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, mode);
     357      753600 :         if (fd == -1) {
     358      406254 :                 return false;
     359             :         }
     360      347346 :         num_written = write(fd, packet, length);
     361      347346 :         if (num_written == -1 || (size_t)num_written != length) {
     362           0 :                 close(fd);
     363           0 :                 return false;
     364             :         }
     365      347346 :         close(fd);
     366      347346 :         return true;
     367             : }
     368             : 
     369             : /**
     370             :   save a lump of data into a file. Mostly used for debugging
     371             : */
     372      753567 : _PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
     373             : {
     374      753567 :         return file_save_mode(fname, packet, length, 0644);
     375             : }
     376             : 
     377          10 : _PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap)
     378             : {
     379          10 :         char *p;
     380          10 :         int len, ret;
     381          10 :         va_list ap2;
     382             : 
     383          10 :         va_copy(ap2, ap);
     384          10 :         len = vasprintf(&p, format, ap2);
     385          10 :         va_end(ap2);
     386          10 :         if (len <= 0) return len;
     387          10 :         ret = write(fd, p, len);
     388          10 :         SAFE_FREE(p);
     389           0 :         return ret;
     390             : }
     391             : 
     392          10 : _PUBLIC_ int fdprintf(int fd, const char *format, ...)
     393             : {
     394          10 :         va_list ap;
     395          10 :         int ret;
     396             : 
     397          10 :         va_start(ap, format);
     398          10 :         ret = vfdprintf(fd, format, ap);
     399          10 :         va_end(ap);
     400          10 :         return ret;
     401             : }
     402             : 
     403             : 
     404             : /*
     405             :   compare two files, return true if the two files have the same content
     406             :  */
     407           0 : bool file_compare(const char *path1, const char *path2)
     408             : {
     409           0 :         FILE *f1 = NULL, *f2 = NULL;
     410           0 :         uint8_t buf1[1024], buf2[1024];
     411           0 :         bool ret = false;
     412             : 
     413           0 :         f1 = fopen(path1, "r");
     414           0 :         if (f1 == NULL) {
     415           0 :                 goto done;
     416             :         }
     417           0 :         f2 = fopen(path2, "r");
     418           0 :         if (f2 == NULL) {
     419           0 :                 goto done;
     420             :         }
     421             : 
     422           0 :         while (!feof(f1)) {
     423           0 :                 size_t n1 = fread(buf1, 1, sizeof(buf1), f1);
     424           0 :                 size_t n2 = fread(buf2, 1, sizeof(buf2), f2);
     425             : 
     426           0 :                 if (n1 != n2) {
     427           0 :                         goto done;
     428             :                 }
     429           0 :                 if (n1 == 0) {
     430           0 :                         ret = (feof(f1) && feof(f2));
     431           0 :                         goto done;
     432             :                 }
     433           0 :                 if (memcmp(buf1, buf2, n1) != 0) {
     434           0 :                         goto done;
     435             :                 }
     436           0 :                 if (n1 < sizeof(buf1)) {
     437           0 :                         bool has_error = (ferror(f1) || ferror(f2));
     438           0 :                         if (has_error) {
     439           0 :                                 goto done;
     440             :                         }
     441             :                 }
     442             :         }
     443           0 :         ret = true;
     444           0 : done:
     445           0 :         if (f2 != NULL) {
     446           0 :                 fclose(f2);
     447             :         }
     448           0 :         if (f1 != NULL) {
     449           0 :                 fclose(f1);
     450             :         }
     451           0 :         return ret;
     452             : }
     453             : 
     454             : /**
     455             :  Load from a pipe into memory.
     456             : **/
     457         930 : char *file_ploadv(char * const argl[], size_t *size)
     458             : {
     459           0 :         int fd, n;
     460         930 :         char *p = NULL;
     461           0 :         char buf[1024];
     462           0 :         size_t total;
     463             : 
     464         930 :         fd = sys_popenv(argl);
     465         930 :         if (fd == -1) {
     466           0 :                 return NULL;
     467             :         }
     468             : 
     469         930 :         total = 0;
     470             : 
     471        1864 :         while ((n = sys_read(fd, buf, sizeof(buf))) > 0) {
     472         934 :                 p = talloc_realloc(NULL, p, char, total + n + 1);
     473         934 :                 if (p == NULL) {
     474           0 :                         DBG_ERR("failed to expand buffer!\n");
     475           0 :                         close(fd);
     476           0 :                         return NULL;
     477             :                 }
     478         934 :                 memcpy(p+total, buf, n);
     479         934 :                 total += n;
     480             :         }
     481             : 
     482         930 :         if (p != NULL) {
     483         930 :                 p[total] = 0;
     484             :         }
     485             : 
     486             :         /*
     487             :          * FIXME: Perhaps ought to check that the command completed
     488             :          * successfully (returned 0); if not the data may be
     489             :          * truncated.
     490             :          */
     491         930 :         sys_pclose(fd);
     492             : 
     493         930 :         if (size) {
     494         930 :                 *size = total;
     495             :         }
     496             : 
     497         930 :         return p;
     498             : }

Generated by: LCOV version 1.14