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

Generated by: LCOV version 1.13