LCOV - code coverage report
Current view: top level - test - test-fileio.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 492 501 98.2 %
Date: 2019-08-23 13:36:53 Functions: 24 24 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 310 612 50.7 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <fcntl.h>
       4                 :            : #include <stdio.h>
       5                 :            : #include <unistd.h>
       6                 :            : 
       7                 :            : #include "alloc-util.h"
       8                 :            : #include "ctype.h"
       9                 :            : #include "env-file.h"
      10                 :            : #include "env-util.h"
      11                 :            : #include "fd-util.h"
      12                 :            : #include "fileio.h"
      13                 :            : #include "fs-util.h"
      14                 :            : #include "io-util.h"
      15                 :            : #include "parse-util.h"
      16                 :            : #include "process-util.h"
      17                 :            : #include "string-util.h"
      18                 :            : #include "strv.h"
      19                 :            : #include "tests.h"
      20                 :            : #include "tmpfile-util.h"
      21                 :            : #include "util.h"
      22                 :            : 
      23                 :          4 : static void test_parse_env_file(void) {
      24                 :            :         _cleanup_(unlink_tempfilep) char
      25                 :          4 :                 t[] = "/tmp/test-fileio-in-XXXXXX",
      26                 :          4 :                 p[] = "/tmp/test-fileio-out-XXXXXX";
      27                 :            :         FILE *f;
      28                 :          4 :         _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
      29                 :          4 :                         *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL,
      30                 :          4 :                         *eleven = NULL, *twelve = NULL, *thirteen = NULL;
      31                 :          4 :         _cleanup_strv_free_ char **a = NULL, **b = NULL;
      32                 :            :         char **i;
      33                 :            :         unsigned k;
      34                 :            :         int r;
      35                 :            : 
      36         [ -  + ]:          4 :         assert_se(fmkostemp_safe(t, "w", &f) == 0);
      37                 :          4 :         fputs("one=BAR   \n"
      38                 :            :               "# comment\n"
      39                 :            :               " # comment \n"
      40                 :            :               " ; comment \n"
      41                 :            :               "  two   =   bar    \n"
      42                 :            :               "invalid line\n"
      43                 :            :               "invalid line #comment\n"
      44                 :            :               "three = \"333\n"
      45                 :            :               "xxxx\"\n"
      46                 :            :               "four = \'44\\\"44\'\n"
      47                 :            :               "five = \"55\\\"55\" \"FIVE\" cinco   \n"
      48                 :            :               "six = seis sechs\\\n"
      49                 :            :               " sis\n"
      50                 :            :               "seven=\"sevenval\" #nocomment\n"
      51                 :            :               "eight=eightval #nocomment\n"
      52                 :            :               "export nine=nineval\n"
      53                 :            :               "ten=ignored\n"
      54                 :            :               "ten=ignored\n"
      55                 :            :               "ten=\n"
      56                 :            :               "eleven=\\value\n"
      57                 :            :               "twelve=\"\\value\"\n"
      58                 :            :               "thirteen='\\value'", f);
      59                 :            : 
      60                 :          4 :         fflush(f);
      61                 :          4 :         fclose(f);
      62                 :            : 
      63                 :          4 :         r = load_env_file(NULL, t, &a);
      64         [ -  + ]:          4 :         assert_se(r >= 0);
      65                 :            : 
      66   [ +  -  +  + ]:         56 :         STRV_FOREACH(i, a)
      67         [ +  - ]:         52 :                 log_info("Got: <%s>", *i);
      68                 :            : 
      69         [ -  + ]:          4 :         assert_se(streq_ptr(a[0], "one=BAR"));
      70         [ -  + ]:          4 :         assert_se(streq_ptr(a[1], "two=bar"));
      71         [ -  + ]:          4 :         assert_se(streq_ptr(a[2], "three=333\nxxxx"));
      72         [ -  + ]:          4 :         assert_se(streq_ptr(a[3], "four=44\\\"44"));
      73         [ -  + ]:          4 :         assert_se(streq_ptr(a[4], "five=55\"55FIVEcinco"));
      74         [ -  + ]:          4 :         assert_se(streq_ptr(a[5], "six=seis sechs sis"));
      75         [ -  + ]:          4 :         assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
      76         [ -  + ]:          4 :         assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
      77         [ -  + ]:          4 :         assert_se(streq_ptr(a[8], "export nine=nineval"));
      78         [ -  + ]:          4 :         assert_se(streq_ptr(a[9], "ten="));
      79         [ -  + ]:          4 :         assert_se(streq_ptr(a[10], "eleven=value"));
      80         [ -  + ]:          4 :         assert_se(streq_ptr(a[11], "twelve=\\value"));
      81         [ -  + ]:          4 :         assert_se(streq_ptr(a[12], "thirteen=\\value"));
      82         [ -  + ]:          4 :         assert_se(a[13] == NULL);
      83                 :            : 
      84                 :          4 :         strv_env_clean(a);
      85                 :            : 
      86                 :          4 :         k = 0;
      87   [ -  +  #  # ]:          4 :         STRV_FOREACH(i, b) {
      88         [ #  # ]:          0 :                 log_info("Got2: <%s>", *i);
      89         [ #  # ]:          0 :                 assert_se(streq(*i, a[k++]));
      90                 :            :         }
      91                 :            : 
      92                 :          4 :         r = parse_env_file(
      93                 :            :                         NULL, t,
      94                 :            :                        "one", &one,
      95                 :            :                        "two", &two,
      96                 :            :                        "three", &three,
      97                 :            :                        "four", &four,
      98                 :            :                        "five", &five,
      99                 :            :                        "six", &six,
     100                 :            :                        "seven", &seven,
     101                 :            :                        "eight", &eight,
     102                 :            :                        "export nine", &nine,
     103                 :            :                        "ten", &ten,
     104                 :            :                        "eleven", &eleven,
     105                 :            :                        "twelve", &twelve,
     106                 :            :                        "thirteen", &thirteen);
     107                 :            : 
     108         [ -  + ]:          4 :         assert_se(r >= 0);
     109                 :            : 
     110         [ +  - ]:          4 :         log_info("one=[%s]", strna(one));
     111         [ +  - ]:          4 :         log_info("two=[%s]", strna(two));
     112         [ +  - ]:          4 :         log_info("three=[%s]", strna(three));
     113         [ +  - ]:          4 :         log_info("four=[%s]", strna(four));
     114         [ +  - ]:          4 :         log_info("five=[%s]", strna(five));
     115         [ +  - ]:          4 :         log_info("six=[%s]", strna(six));
     116         [ +  - ]:          4 :         log_info("seven=[%s]", strna(seven));
     117         [ +  - ]:          4 :         log_info("eight=[%s]", strna(eight));
     118         [ +  - ]:          4 :         log_info("export nine=[%s]", strna(nine));
     119         [ +  - ]:          4 :         log_info("ten=[%s]", strna(nine));
     120         [ +  - ]:          4 :         log_info("eleven=[%s]", strna(eleven));
     121         [ +  - ]:          4 :         log_info("twelve=[%s]", strna(twelve));
     122         [ +  - ]:          4 :         log_info("thirteen=[%s]", strna(thirteen));
     123                 :            : 
     124         [ -  + ]:          4 :         assert_se(streq(one, "BAR"));
     125         [ -  + ]:          4 :         assert_se(streq(two, "bar"));
     126         [ -  + ]:          4 :         assert_se(streq(three, "333\nxxxx"));
     127         [ -  + ]:          4 :         assert_se(streq(four, "44\\\"44"));
     128         [ -  + ]:          4 :         assert_se(streq(five, "55\"55FIVEcinco"));
     129         [ -  + ]:          4 :         assert_se(streq(six, "seis sechs sis"));
     130         [ -  + ]:          4 :         assert_se(streq(seven, "sevenval#nocomment"));
     131         [ -  + ]:          4 :         assert_se(streq(eight, "eightval #nocomment"));
     132         [ -  + ]:          4 :         assert_se(streq(nine, "nineval"));
     133         [ -  + ]:          4 :         assert_se(ten == NULL);
     134         [ -  + ]:          4 :         assert_se(streq(eleven, "value"));
     135         [ -  + ]:          4 :         assert_se(streq(twelve, "\\value"));
     136         [ -  + ]:          4 :         assert_se(streq(thirteen, "\\value"));
     137                 :            : 
     138                 :            :         {
     139                 :            :                 /* prepare a temporary file to write the environment to */
     140                 :          8 :                 _cleanup_close_ int fd = mkostemp_safe(p);
     141         [ -  + ]:          4 :                 assert_se(fd >= 0);
     142                 :            :         }
     143                 :            : 
     144                 :          4 :         r = write_env_file(p, a);
     145         [ -  + ]:          4 :         assert_se(r >= 0);
     146                 :            : 
     147                 :          4 :         r = load_env_file(NULL, p, &b);
     148         [ -  + ]:          4 :         assert_se(r >= 0);
     149                 :          4 : }
     150                 :            : 
     151                 :          4 : static void test_parse_multiline_env_file(void) {
     152                 :            :         _cleanup_(unlink_tempfilep) char
     153                 :          4 :                 t[] = "/tmp/test-fileio-in-XXXXXX",
     154                 :          4 :                 p[] = "/tmp/test-fileio-out-XXXXXX";
     155                 :            :         FILE *f;
     156                 :          4 :         _cleanup_strv_free_ char **a = NULL, **b = NULL;
     157                 :            :         char **i;
     158                 :            :         int r;
     159                 :            : 
     160         [ -  + ]:          4 :         assert_se(fmkostemp_safe(t, "w", &f) == 0);
     161                 :          4 :         fputs("one=BAR\\\n"
     162                 :            :               "    VAR\\\n"
     163                 :            :               "\tGAR\n"
     164                 :            :               "#comment\n"
     165                 :            :               "two=\"bar\\\n"
     166                 :            :               "    var\\\n"
     167                 :            :               "\tgar\"\n"
     168                 :            :               "#comment\n"
     169                 :            :               "tri=\"bar \\\n"
     170                 :            :               "    var \\\n"
     171                 :            :               "\tgar \"\n", f);
     172                 :            : 
     173                 :          4 :         fflush(f);
     174                 :          4 :         fclose(f);
     175                 :            : 
     176                 :          4 :         r = load_env_file(NULL, t, &a);
     177         [ -  + ]:          4 :         assert_se(r >= 0);
     178                 :            : 
     179   [ +  -  +  + ]:         16 :         STRV_FOREACH(i, a)
     180         [ +  - ]:         12 :                 log_info("Got: <%s>", *i);
     181                 :            : 
     182         [ -  + ]:          4 :         assert_se(streq_ptr(a[0], "one=BAR    VAR\tGAR"));
     183         [ -  + ]:          4 :         assert_se(streq_ptr(a[1], "two=bar    var\tgar"));
     184         [ -  + ]:          4 :         assert_se(streq_ptr(a[2], "tri=bar     var \tgar "));
     185         [ -  + ]:          4 :         assert_se(a[3] == NULL);
     186                 :            : 
     187                 :            :         {
     188                 :          8 :                 _cleanup_close_ int fd = mkostemp_safe(p);
     189         [ -  + ]:          4 :                 assert_se(fd >= 0);
     190                 :            :         }
     191                 :            : 
     192                 :          4 :         r = write_env_file(p, a);
     193         [ -  + ]:          4 :         assert_se(r >= 0);
     194                 :            : 
     195                 :          4 :         r = load_env_file(NULL, p, &b);
     196         [ -  + ]:          4 :         assert_se(r >= 0);
     197                 :          4 : }
     198                 :            : 
     199                 :          4 : static void test_merge_env_file(void) {
     200                 :          4 :         _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
     201                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     202                 :          4 :         _cleanup_strv_free_ char **a = NULL;
     203                 :            :         char **i;
     204                 :            :         int r;
     205                 :            : 
     206         [ -  + ]:          4 :         assert_se(fmkostemp_safe(t, "w", &f) == 0);
     207         [ +  - ]:          4 :         log_info("/* %s (%s) */", __func__, t);
     208                 :            : 
     209                 :          4 :         r = write_string_stream(f,
     210                 :            :                                 "one=1   \n"
     211                 :            :                                 "twelve=${one}2\n"
     212                 :            :                                 "twentyone=2${one}\n"
     213                 :            :                                 "one=2\n"
     214                 :            :                                 "twentytwo=2${one}\n"
     215                 :            :                                 "xxx_minus_three=$xxx - 3\n"
     216                 :            :                                 "xxx=0x$one$one$one\n"
     217                 :            :                                 "yyy=${one:-fallback}\n"
     218                 :            :                                 "zzz=${one:+replacement}\n"
     219                 :            :                                 "zzzz=${foobar:-${nothing}}\n"
     220                 :            :                                 "zzzzz=${nothing:+${nothing}}\n"
     221                 :            :                                 , WRITE_STRING_FILE_AVOID_NEWLINE);
     222         [ -  + ]:          4 :         assert(r >= 0);
     223                 :            : 
     224                 :          4 :         r = merge_env_file(&a, NULL, t);
     225         [ -  + ]:          4 :         assert_se(r >= 0);
     226                 :          4 :         strv_sort(a);
     227                 :            : 
     228   [ +  -  +  + ]:         44 :         STRV_FOREACH(i, a)
     229         [ +  - ]:         40 :                 log_info("Got: <%s>", *i);
     230                 :            : 
     231         [ -  + ]:          4 :         assert_se(streq(a[0], "one=2"));
     232         [ -  + ]:          4 :         assert_se(streq(a[1], "twelve=12"));
     233         [ -  + ]:          4 :         assert_se(streq(a[2], "twentyone=21"));
     234         [ -  + ]:          4 :         assert_se(streq(a[3], "twentytwo=22"));
     235         [ -  + ]:          4 :         assert_se(streq(a[4], "xxx=0x222"));
     236         [ -  + ]:          4 :         assert_se(streq(a[5], "xxx_minus_three= - 3"));
     237         [ -  + ]:          4 :         assert_se(streq(a[6], "yyy=2"));
     238         [ -  + ]:          4 :         assert_se(streq(a[7], "zzz=replacement"));
     239         [ -  + ]:          4 :         assert_se(streq(a[8], "zzzz="));
     240         [ -  + ]:          4 :         assert_se(streq(a[9], "zzzzz="));
     241         [ -  + ]:          4 :         assert_se(a[10] == NULL);
     242                 :            : 
     243                 :          4 :         r = merge_env_file(&a, NULL, t);
     244         [ -  + ]:          4 :         assert_se(r >= 0);
     245                 :          4 :         strv_sort(a);
     246                 :            : 
     247   [ +  -  +  + ]:         44 :         STRV_FOREACH(i, a)
     248         [ +  - ]:         40 :                 log_info("Got2: <%s>", *i);
     249                 :            : 
     250         [ -  + ]:          4 :         assert_se(streq(a[0], "one=2"));
     251         [ -  + ]:          4 :         assert_se(streq(a[1], "twelve=12"));
     252         [ -  + ]:          4 :         assert_se(streq(a[2], "twentyone=21"));
     253         [ -  + ]:          4 :         assert_se(streq(a[3], "twentytwo=22"));
     254         [ -  + ]:          4 :         assert_se(streq(a[4], "xxx=0x222"));
     255         [ -  + ]:          4 :         assert_se(streq(a[5], "xxx_minus_three=0x222 - 3"));
     256         [ -  + ]:          4 :         assert_se(streq(a[6], "yyy=2"));
     257         [ -  + ]:          4 :         assert_se(streq(a[7], "zzz=replacement"));
     258         [ -  + ]:          4 :         assert_se(streq(a[8], "zzzz="));
     259         [ -  + ]:          4 :         assert_se(streq(a[9], "zzzzz="));
     260         [ -  + ]:          4 :         assert_se(a[10] == NULL);
     261                 :          4 : }
     262                 :            : 
     263                 :          4 : static void test_merge_env_file_invalid(void) {
     264                 :          4 :         _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
     265                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     266                 :          4 :         _cleanup_strv_free_ char **a = NULL;
     267                 :            :         char **i;
     268                 :            :         int r;
     269                 :            : 
     270         [ -  + ]:          4 :         assert_se(fmkostemp_safe(t, "w", &f) == 0);
     271         [ +  - ]:          4 :         log_info("/* %s (%s) */", __func__, t);
     272                 :            : 
     273                 :          4 :         r = write_string_stream(f,
     274                 :            :                                 "unset one   \n"
     275                 :            :                                 "unset one=   \n"
     276                 :            :                                 "unset one=1   \n"
     277                 :            :                                 "one   \n"
     278                 :            :                                 "one =  \n"
     279                 :            :                                 "one two =\n"
     280                 :            :                                 "\x20two=\n"
     281                 :            :                                 "#comment=comment\n"
     282                 :            :                                 ";comment2=comment2\n"
     283                 :            :                                 "#\n"
     284                 :            :                                 "\n\n"                  /* empty line */
     285                 :            :                                 , WRITE_STRING_FILE_AVOID_NEWLINE);
     286         [ -  + ]:          4 :         assert(r >= 0);
     287                 :            : 
     288                 :          4 :         r = merge_env_file(&a, NULL, t);
     289         [ -  + ]:          4 :         assert_se(r >= 0);
     290                 :            : 
     291   [ -  +  #  # ]:          4 :         STRV_FOREACH(i, a)
     292         [ #  # ]:          0 :                 log_info("Got: <%s>", *i);
     293                 :            : 
     294         [ -  + ]:          4 :         assert_se(strv_isempty(a));
     295                 :          4 : }
     296                 :            : 
     297                 :          4 : static void test_executable_is_script(void) {
     298                 :          4 :         _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
     299                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     300                 :            :         char *command;
     301                 :            :         int r;
     302                 :            : 
     303         [ -  + ]:          4 :         assert_se(fmkostemp_safe(t, "w", &f) == 0);
     304                 :          4 :         fputs("#! /bin/script -a -b \ngoo goo", f);
     305                 :          4 :         fflush(f);
     306                 :            : 
     307                 :          4 :         r = executable_is_script(t, &command);
     308         [ -  + ]:          4 :         assert_se(r > 0);
     309         [ -  + ]:          4 :         assert_se(streq(command, "/bin/script"));
     310                 :          4 :         free(command);
     311                 :            : 
     312                 :          4 :         r = executable_is_script("/bin/sh", &command);
     313         [ -  + ]:          4 :         assert_se(r == 0);
     314                 :            : 
     315                 :          4 :         r = executable_is_script("/usr/bin/yum", &command);
     316   [ -  +  #  # ]:          4 :         assert_se(r > 0 || r == -ENOENT);
     317         [ +  - ]:          4 :         if (r > 0) {
     318         [ -  + ]:          4 :                 assert_se(startswith(command, "/"));
     319                 :          4 :                 free(command);
     320                 :            :         }
     321                 :          4 : }
     322                 :            : 
     323                 :          4 : static void test_status_field(void) {
     324                 :          4 :         _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
     325                 :          4 :         unsigned long long total = 0, buffers = 0;
     326                 :            :         int r;
     327                 :            : 
     328         [ -  + ]:          4 :         assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
     329                 :          4 :         puts(t);
     330         [ -  + ]:          4 :         assert_se(streq(t, "1"));
     331                 :            : 
     332                 :          4 :         r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
     333         [ +  - ]:          4 :         if (r != -ENOENT) {
     334         [ -  + ]:          4 :                 assert_se(r == 0);
     335                 :          4 :                 puts(p);
     336         [ -  + ]:          4 :                 assert_se(safe_atollu(p, &total) == 0);
     337                 :            :         }
     338                 :            : 
     339                 :          4 :         r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s);
     340         [ +  - ]:          4 :         if (r != -ENOENT) {
     341         [ -  + ]:          4 :                 assert_se(r == 0);
     342                 :          4 :                 puts(s);
     343         [ -  + ]:          4 :                 assert_se(safe_atollu(s, &buffers) == 0);
     344                 :            :         }
     345                 :            : 
     346         [ +  - ]:          4 :         if (p)
     347         [ -  + ]:          4 :                 assert_se(buffers < total);
     348                 :            : 
     349                 :            :         /* Seccomp should be a good test for field full of zeros. */
     350                 :          4 :         r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z);
     351         [ -  + ]:          4 :         if (r != -ENOENT) {
     352         [ #  # ]:          0 :                 assert_se(r == 0);
     353                 :          0 :                 puts(z);
     354         [ #  # ]:          0 :                 assert_se(safe_atollu(z, &buffers) == 0);
     355                 :            :         }
     356                 :          4 : }
     357                 :            : 
     358                 :          4 : static void test_capeff(void) {
     359                 :            :         int pid, p;
     360                 :            : 
     361         [ +  + ]:         12 :         for (pid = 0; pid < 2; pid++) {
     362         [ +  - ]:          8 :                 _cleanup_free_ char *capeff = NULL;
     363                 :            :                 int r;
     364                 :            : 
     365                 :          8 :                 r = get_process_capeff(0, &capeff);
     366         [ +  - ]:          8 :                 log_info("capeff: '%s' (r=%d)", capeff, r);
     367                 :            : 
     368   [ -  +  -  + ]:          8 :                 if (IN_SET(r, -ENOENT, -EPERM))
     369                 :          0 :                         return;
     370                 :            : 
     371         [ -  + ]:          8 :                 assert_se(r == 0);
     372         [ -  + ]:          8 :                 assert_se(*capeff);
     373                 :          8 :                 p = capeff[strspn(capeff, HEXDIGITS)];
     374   [ -  +  #  # ]:          8 :                 assert_se(!p || isspace(p));
     375                 :            :         }
     376                 :            : }
     377                 :            : 
     378                 :          4 : static void test_write_string_stream(void) {
     379                 :          4 :         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
     380                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     381                 :            :         int fd;
     382                 :            :         char buf[64];
     383                 :            : 
     384                 :          4 :         fd = mkostemp_safe(fn);
     385         [ -  + ]:          4 :         assert_se(fd >= 0);
     386                 :            : 
     387                 :          4 :         f = fdopen(fd, "r");
     388         [ -  + ]:          4 :         assert_se(f);
     389         [ -  + ]:          4 :         assert_se(write_string_stream(f, "boohoo", 0) < 0);
     390                 :          4 :         f = safe_fclose(f);
     391                 :            : 
     392                 :          4 :         f = fopen(fn, "r+");
     393         [ -  + ]:          4 :         assert_se(f);
     394                 :            : 
     395         [ -  + ]:          4 :         assert_se(write_string_stream(f, "boohoo", 0) == 0);
     396                 :          4 :         rewind(f);
     397                 :            : 
     398         [ -  + ]:          4 :         assert_se(fgets(buf, sizeof(buf), f));
     399         [ -  + ]:          4 :         assert_se(streq(buf, "boohoo\n"));
     400                 :          4 :         f = safe_fclose(f);
     401                 :            : 
     402                 :          4 :         f = fopen(fn, "w+");
     403         [ -  + ]:          4 :         assert_se(f);
     404                 :            : 
     405         [ -  + ]:          4 :         assert_se(write_string_stream(f, "boohoo", WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
     406                 :          4 :         rewind(f);
     407                 :            : 
     408         [ -  + ]:          4 :         assert_se(fgets(buf, sizeof(buf), f));
     409                 :          4 :         printf(">%s<", buf);
     410         [ -  + ]:          4 :         assert_se(streq(buf, "boohoo"));
     411                 :          4 : }
     412                 :            : 
     413                 :          4 : static void test_write_string_file(void) {
     414                 :          4 :         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
     415                 :          4 :         char buf[64] = {};
     416                 :          4 :         _cleanup_close_ int fd;
     417                 :            : 
     418                 :          4 :         fd = mkostemp_safe(fn);
     419         [ -  + ]:          4 :         assert_se(fd >= 0);
     420                 :            : 
     421         [ -  + ]:          4 :         assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
     422                 :            : 
     423         [ -  + ]:          4 :         assert_se(read(fd, buf, sizeof(buf)) == 7);
     424         [ -  + ]:          4 :         assert_se(streq(buf, "boohoo\n"));
     425                 :          4 : }
     426                 :            : 
     427                 :          4 : static void test_write_string_file_no_create(void) {
     428                 :          4 :         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
     429                 :          4 :         _cleanup_close_ int fd;
     430                 :          4 :         char buf[64] = {};
     431                 :            : 
     432                 :          4 :         fd = mkostemp_safe(fn);
     433         [ -  + ]:          4 :         assert_se(fd >= 0);
     434                 :            : 
     435         [ -  + ]:          4 :         assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
     436         [ -  + ]:          4 :         assert_se(write_string_file(fn, "boohoo", 0) == 0);
     437                 :            : 
     438         [ -  + ]:          4 :         assert_se(read(fd, buf, sizeof buf) == (ssize_t) strlen("boohoo\n"));
     439         [ -  + ]:          4 :         assert_se(streq(buf, "boohoo\n"));
     440                 :          4 : }
     441                 :            : 
     442                 :          4 : static void test_write_string_file_verify(void) {
     443                 :          4 :         _cleanup_free_ char *buf = NULL, *buf2 = NULL;
     444                 :            :         int r;
     445                 :            : 
     446         [ -  + ]:          4 :         assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
     447         [ -  + ]:          4 :         assert_se(buf2 = strjoin(buf, "\n"));
     448                 :            : 
     449                 :          4 :         r = write_string_file("/proc/cmdline", buf, 0);
     450   [ +  -  -  + ]:          4 :         assert_se(IN_SET(r, -EACCES, -EIO));
     451                 :          4 :         r = write_string_file("/proc/cmdline", buf2, 0);
     452   [ +  -  -  + ]:          4 :         assert_se(IN_SET(r, -EACCES, -EIO));
     453                 :            : 
     454         [ -  + ]:          4 :         assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
     455         [ -  + ]:          4 :         assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
     456                 :            : 
     457                 :          4 :         r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE);
     458   [ +  -  -  + ]:          4 :         assert_se(IN_SET(r, -EACCES, -EIO));
     459         [ -  + ]:          4 :         assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
     460                 :          4 : }
     461                 :            : 
     462                 :          4 : static void test_load_env_file_pairs(void) {
     463                 :          4 :         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
     464                 :            :         int fd, r;
     465                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     466                 :          4 :         _cleanup_strv_free_ char **l = NULL;
     467                 :            :         char **k, **v;
     468                 :            : 
     469                 :          4 :         fd = mkostemp_safe(fn);
     470         [ -  + ]:          4 :         assert_se(fd >= 0);
     471                 :            : 
     472                 :          4 :         r = write_string_file(fn,
     473                 :            :                         "NAME=\"Arch Linux\"\n"
     474                 :            :                         "ID=arch\n"
     475                 :            :                         "PRETTY_NAME=\"Arch Linux\"\n"
     476                 :            :                         "ANSI_COLOR=\"0;36\"\n"
     477                 :            :                         "HOME_URL=\"https://www.archlinux.org/\"\n"
     478                 :            :                         "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
     479                 :            :                         "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n",
     480                 :            :                         WRITE_STRING_FILE_CREATE);
     481         [ -  + ]:          4 :         assert_se(r == 0);
     482                 :            : 
     483                 :          4 :         f = fdopen(fd, "r");
     484         [ -  + ]:          4 :         assert_se(f);
     485                 :            : 
     486                 :          4 :         r = load_env_file_pairs(f, fn, &l);
     487         [ -  + ]:          4 :         assert_se(r >= 0);
     488                 :            : 
     489         [ -  + ]:          4 :         assert_se(strv_length(l) == 14);
     490   [ +  -  +  +  :         32 :         STRV_FOREACH_PAIR(k, v, l) {
                   +  - ]
     491         [ -  + ]:         28 :                 assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
     492                 :         28 :                 printf("%s=%s\n", *k, *v);
     493   [ +  +  -  + ]:         28 :                 if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
     494   [ +  +  -  + ]:         28 :                 if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
     495   [ +  +  -  + ]:         28 :                 if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
     496   [ +  +  -  + ]:         28 :                 if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
     497   [ +  +  -  + ]:         28 :                 if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
     498   [ +  +  -  + ]:         28 :                 if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
     499   [ +  +  -  + ]:         28 :                 if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
     500                 :            :         }
     501                 :          4 : }
     502                 :            : 
     503                 :          4 : static void test_search_and_fopen(void) {
     504                 :          4 :         const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
     505                 :            : 
     506                 :          4 :         char name[] = "/tmp/test-search_and_fopen.XXXXXX";
     507                 :            :         int fd, r;
     508                 :            :         FILE *f;
     509                 :            : 
     510                 :          4 :         fd = mkostemp_safe(name);
     511         [ -  + ]:          4 :         assert_se(fd >= 0);
     512                 :          4 :         close(fd);
     513                 :            : 
     514                 :          4 :         r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
     515         [ -  + ]:          4 :         assert_se(r >= 0);
     516                 :          4 :         fclose(f);
     517                 :            : 
     518                 :          4 :         r = search_and_fopen(name, "r", NULL, dirs, &f);
     519         [ -  + ]:          4 :         assert_se(r >= 0);
     520                 :          4 :         fclose(f);
     521                 :            : 
     522                 :          4 :         r = search_and_fopen(basename(name), "r", "/", dirs, &f);
     523         [ -  + ]:          4 :         assert_se(r >= 0);
     524                 :          4 :         fclose(f);
     525                 :            : 
     526                 :          4 :         r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
     527         [ -  + ]:          4 :         assert_se(r < 0);
     528                 :          4 :         r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
     529         [ -  + ]:          4 :         assert_se(r < 0);
     530                 :            : 
     531                 :          4 :         r = unlink(name);
     532         [ -  + ]:          4 :         assert_se(r == 0);
     533                 :            : 
     534                 :          4 :         r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
     535         [ -  + ]:          4 :         assert_se(r < 0);
     536                 :          4 : }
     537                 :            : 
     538                 :          4 : static void test_search_and_fopen_nulstr(void) {
     539                 :          4 :         const char dirs[] = "/tmp/foo/bar\0/tmp\0";
     540                 :            : 
     541                 :          4 :         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
     542                 :            :         int fd, r;
     543                 :            :         FILE *f;
     544                 :            : 
     545                 :          4 :         fd = mkostemp_safe(name);
     546         [ -  + ]:          4 :         assert_se(fd >= 0);
     547                 :          4 :         close(fd);
     548                 :            : 
     549                 :          4 :         r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
     550         [ -  + ]:          4 :         assert_se(r >= 0);
     551                 :          4 :         fclose(f);
     552                 :            : 
     553                 :          4 :         r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
     554         [ -  + ]:          4 :         assert_se(r >= 0);
     555                 :          4 :         fclose(f);
     556                 :            : 
     557                 :          4 :         r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
     558         [ -  + ]:          4 :         assert_se(r < 0);
     559                 :          4 :         r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
     560         [ -  + ]:          4 :         assert_se(r < 0);
     561                 :            : 
     562                 :          4 :         r = unlink(name);
     563         [ -  + ]:          4 :         assert_se(r == 0);
     564                 :            : 
     565                 :          4 :         r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
     566         [ -  + ]:          4 :         assert_se(r < 0);
     567                 :          4 : }
     568                 :            : 
     569                 :          4 : static void test_writing_tmpfile(void) {
     570                 :          4 :         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
     571                 :          4 :         _cleanup_free_ char *contents = NULL;
     572                 :            :         size_t size;
     573                 :          4 :         _cleanup_close_ int fd = -1;
     574                 :            :         struct iovec iov[3];
     575                 :            :         int r;
     576                 :            : 
     577                 :          4 :         iov[0] = IOVEC_MAKE_STRING("abc\n");
     578                 :          4 :         iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n");
     579                 :          4 :         iov[2] = IOVEC_MAKE_STRING("");
     580                 :            : 
     581                 :          4 :         fd = mkostemp_safe(name);
     582                 :          4 :         printf("tmpfile: %s", name);
     583                 :            : 
     584                 :          4 :         r = writev(fd, iov, 3);
     585         [ -  + ]:          4 :         assert_se(r >= 0);
     586                 :            : 
     587                 :          4 :         r = read_full_file(name, &contents, &size);
     588         [ -  + ]:          4 :         assert_se(r == 0);
     589                 :          4 :         printf("contents: %s", contents);
     590         [ -  + ]:          4 :         assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
     591                 :          4 : }
     592                 :            : 
     593                 :          4 : static void test_tempfn(void) {
     594                 :          4 :         char *ret = NULL, *p;
     595                 :            : 
     596         [ -  + ]:          4 :         assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
     597         [ -  + ]:          4 :         assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
     598                 :          4 :         free(ret);
     599                 :            : 
     600         [ -  + ]:          4 :         assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
     601         [ -  + ]:          4 :         assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
     602                 :          4 :         free(ret);
     603                 :            : 
     604         [ -  + ]:          4 :         assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
     605         [ -  + ]:          4 :         assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
     606         [ -  + ]:          4 :         assert_se(strlen(p) == 16);
     607         [ -  + ]:          4 :         assert_se(in_charset(p, "0123456789abcdef"));
     608                 :          4 :         free(ret);
     609                 :            : 
     610         [ -  + ]:          4 :         assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
     611         [ -  + ]:          4 :         assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
     612         [ -  + ]:          4 :         assert_se(strlen(p) == 16);
     613         [ -  + ]:          4 :         assert_se(in_charset(p, "0123456789abcdef"));
     614                 :          4 :         free(ret);
     615                 :            : 
     616         [ -  + ]:          4 :         assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
     617         [ -  + ]:          4 :         assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
     618         [ -  + ]:          4 :         assert_se(strlen(p) == 16);
     619         [ -  + ]:          4 :         assert_se(in_charset(p, "0123456789abcdef"));
     620                 :          4 :         free(ret);
     621                 :            : 
     622         [ -  + ]:          4 :         assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
     623         [ -  + ]:          4 :         assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
     624         [ -  + ]:          4 :         assert_se(strlen(p) == 16);
     625         [ -  + ]:          4 :         assert_se(in_charset(p, "0123456789abcdef"));
     626                 :          4 :         free(ret);
     627                 :          4 : }
     628                 :            : 
     629                 :            : static const char chars[] =
     630                 :            :         "Aąę„”\n루\377";
     631                 :            : 
     632                 :            : #pragma GCC diagnostic push
     633                 :            : #pragma GCC diagnostic ignored "-Wtype-limits"
     634                 :            : 
     635                 :          4 : static void test_fgetc(void) {
     636                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     637                 :            :         char c;
     638                 :            : 
     639                 :          4 :         f = fmemopen_unlocked((void*) chars, sizeof(chars), "re");
     640         [ -  + ]:          4 :         assert_se(f);
     641                 :            : 
     642         [ +  + ]:         72 :         for (unsigned i = 0; i < sizeof(chars); i++) {
     643         [ -  + ]:         68 :                 assert_se(safe_fgetc(f, &c) == 1);
     644         [ -  + ]:         68 :                 assert_se(c == chars[i]);
     645                 :            : 
     646                 :            :                 /* EOF is -1, and hence we can't push value 255 in this way if char is signed */
     647   [ +  +  -  + ]:         68 :                 assert_se(ungetc(c, f) != EOF || c == EOF);
     648   [ +  +  -  + ]:         68 :                 assert_se(c == EOF || safe_fgetc(f, &c) == 1);
     649         [ -  + ]:         68 :                 assert_se(c == chars[i]);
     650                 :            : 
     651                 :            :                 /* But it works when we push it properly cast */
     652         [ -  + ]:         68 :                 assert_se(ungetc((unsigned char) c, f) != EOF);
     653         [ -  + ]:         68 :                 assert_se(safe_fgetc(f, &c) == 1);
     654         [ -  + ]:         68 :                 assert_se(c == chars[i]);
     655                 :            :         }
     656                 :            : 
     657         [ -  + ]:          4 :         assert_se(safe_fgetc(f, &c) == 0);
     658                 :          4 : }
     659                 :            : 
     660                 :            : #pragma GCC diagnostic pop
     661                 :            : 
     662                 :            : static const char buffer[] =
     663                 :            :         "Some test data\n"
     664                 :            :         "루Non-ascii chars: ąę„”\n"
     665                 :            :         "terminators\r\n"
     666                 :            :         "and even more\n\r"
     667                 :            :         "now the same with a NUL\n\0"
     668                 :            :         "and more\r\0"
     669                 :            :         "and even more\r\n\0"
     670                 :            :         "and yet even more\n\r\0"
     671                 :            :         "With newlines, and a NUL byte\0"
     672                 :            :         "\n"
     673                 :            :         "an empty line\n"
     674                 :            :         "an ignored line\n"
     675                 :            :         "and a very long line that is supposed to be truncated, because it is so long\n";
     676                 :            : 
     677                 :          8 : static void test_read_line_one_file(FILE *f) {
     678                 :          8 :         _cleanup_free_ char *line = NULL;
     679                 :            : 
     680   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data"));
     681                 :          8 :         line = mfree(line);
     682                 :            : 
     683   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) > 0 && streq(line, "루Non-ascii chars: ąę„”"));
     684                 :          8 :         line = mfree(line);
     685                 :            : 
     686   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 13 && streq(line, "terminators"));
     687                 :          8 :         line = mfree(line);
     688                 :            : 
     689   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "and even more"));
     690                 :          8 :         line = mfree(line);
     691                 :            : 
     692   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 25 && streq(line, "now the same with a NUL"));
     693                 :          8 :         line = mfree(line);
     694                 :            : 
     695   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 10 && streq(line, "and more"));
     696                 :          8 :         line = mfree(line);
     697                 :            : 
     698   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 16 && streq(line, "and even more"));
     699                 :          8 :         line = mfree(line);
     700                 :            : 
     701   [ +  -  -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, &line) == 20 && streq(line, "and yet even more"));
     702                 :          8 :         line = mfree(line);
     703                 :            : 
     704   [ +  -  -  + ]:          8 :         assert_se(read_line(f, 1024, &line) == 30 && streq(line, "With newlines, and a NUL byte"));
     705                 :          8 :         line = mfree(line);
     706                 :            : 
     707   [ +  -  -  + ]:          8 :         assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
     708                 :          8 :         line = mfree(line);
     709                 :            : 
     710   [ +  -  -  + ]:          8 :         assert_se(read_line(f, 1024, &line) == 14 && streq(line, "an empty line"));
     711                 :          8 :         line = mfree(line);
     712                 :            : 
     713         [ -  + ]:          8 :         assert_se(read_line(f, (size_t) -1, NULL) == 16);
     714                 :            : 
     715         [ -  + ]:          8 :         assert_se(read_line(f, 16, &line) == -ENOBUFS);
     716                 :          8 :         line = mfree(line);
     717                 :            : 
     718                 :            :         /* read_line() stopped when it hit the limit, that means when we continue reading we'll read at the first
     719                 :            :          * character after the previous limit. Let's make use of that to continue our test. */
     720   [ +  -  -  + ]:          8 :         assert_se(read_line(f, 1024, &line) == 62 && streq(line, "line that is supposed to be truncated, because it is so long"));
     721                 :          8 :         line = mfree(line);
     722                 :            : 
     723   [ +  -  -  + ]:          8 :         assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
     724                 :          8 : }
     725                 :            : 
     726                 :          4 : static void test_read_line(void) {
     727                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     728                 :            : 
     729                 :          4 :         f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "re");
     730         [ -  + ]:          4 :         assert_se(f);
     731                 :            : 
     732                 :          4 :         test_read_line_one_file(f);
     733                 :          4 : }
     734                 :            : 
     735                 :          4 : static void test_read_line2(void) {
     736                 :          4 :         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fileio.XXXXXX";
     737                 :            :         int fd;
     738                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     739                 :            : 
     740                 :          4 :         fd = mkostemp_safe(name);
     741         [ -  + ]:          4 :         assert_se(fd >= 0);
     742         [ -  + ]:          4 :         assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
     743                 :            : 
     744         [ -  + ]:          4 :         assert_se(lseek(fd, 0, SEEK_SET) == 0);
     745         [ -  + ]:          4 :         assert_se(f = fdopen(fd, "r"));
     746                 :            : 
     747                 :          4 :         test_read_line_one_file(f);
     748                 :          4 : }
     749                 :            : 
     750                 :          4 : static void test_read_line3(void) {
     751         [ +  - ]:          4 :         _cleanup_fclose_ FILE *f = NULL;
     752         [ +  - ]:          4 :         _cleanup_free_ char *line = NULL;
     753                 :            :         int r;
     754                 :            : 
     755                 :          4 :         f = fopen("/proc/cmdline", "re");
     756   [ -  +  #  #  :          4 :         if (!f && IN_SET(errno, ENOENT, EPERM))
                   #  # ]
     757                 :          0 :                 return;
     758         [ -  + ]:          4 :         assert_se(f);
     759                 :            : 
     760                 :          4 :         r = read_line(f, LINE_MAX, &line);
     761         [ -  + ]:          4 :         assert_se(r >= 0);
     762         [ -  + ]:          4 :         if (r == 0)
     763   [ #  #  #  # ]:          0 :                 assert_se(line && isempty(line));
     764                 :            :         else
     765         [ -  + ]:          4 :                 assert_se((size_t) r == strlen(line) + 1);
     766         [ -  + ]:          4 :         assert_se(read_line(f, LINE_MAX, NULL) == 0);
     767                 :            : }
     768                 :            : 
     769                 :          4 : static void test_read_line4(void) {
     770                 :            :         static const struct {
     771                 :            :                 size_t length;
     772                 :            :                 const char *string;
     773                 :            :         } eof_endings[] = {
     774                 :            :                 /* Each of these will be followed by EOF and should generate the one same single string */
     775                 :            :                 { 3, "foo" },
     776                 :            :                 { 4, "foo\n" },
     777                 :            :                 { 4, "foo\r" },
     778                 :            :                 { 4, "foo\0" },
     779                 :            :                 { 5, "foo\n\0" },
     780                 :            :                 { 5, "foo\r\0" },
     781                 :            :                 { 5, "foo\r\n" },
     782                 :            :                 { 5, "foo\n\r" },
     783                 :            :                 { 6, "foo\r\n\0" },
     784                 :            :                 { 6, "foo\n\r\0" },
     785                 :            :         };
     786                 :            : 
     787                 :            :         size_t i;
     788                 :            :         int r;
     789                 :            : 
     790         [ +  + ]:         44 :         for (i = 0; i < ELEMENTSOF(eof_endings); i++) {
     791                 :         40 :                 _cleanup_fclose_ FILE *f = NULL;
     792                 :         40 :                 _cleanup_free_ char *s = NULL;
     793                 :            : 
     794         [ -  + ]:         40 :                 assert_se(f = fmemopen_unlocked((void*) eof_endings[i].string, eof_endings[i].length, "r"));
     795                 :            : 
     796                 :         40 :                 r = read_line(f, (size_t) -1, &s);
     797         [ -  + ]:         40 :                 assert_se((size_t) r == eof_endings[i].length);
     798         [ -  + ]:         40 :                 assert_se(streq_ptr(s, "foo"));
     799                 :            : 
     800         [ -  + ]:         40 :                 assert_se(read_line(f, (size_t) -1, NULL) == 0); /* Ensure we hit EOF */
     801                 :            :         }
     802                 :          4 : }
     803                 :            : 
     804                 :          4 : static void test_read_nul_string(void) {
     805                 :            :         static const char test[] = "string nr. 1\0"
     806                 :            :                 "string nr. 2\n\0"
     807                 :            :                 "\377empty string follows\0"
     808                 :            :                 "\0"
     809                 :            :                 "final string\n is empty\0"
     810                 :            :                 "\0";
     811                 :            : 
     812                 :          4 :         _cleanup_fclose_ FILE *f = NULL;
     813                 :          4 :         _cleanup_free_ char *s = NULL;
     814                 :            : 
     815         [ -  + ]:          4 :         assert_se(f = fmemopen_unlocked((void*) test, sizeof(test)-1, "r"));
     816                 :            : 
     817   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 13 && streq_ptr(s, "string nr. 1"));
     818                 :          4 :         s = mfree(s);
     819                 :            : 
     820   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 14 && streq_ptr(s, "string nr. 2\n"));
     821                 :          4 :         s = mfree(s);
     822                 :            : 
     823   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 22 && streq_ptr(s, "\377empty string follows"));
     824                 :          4 :         s = mfree(s);
     825                 :            : 
     826   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));
     827                 :          4 :         s = mfree(s);
     828                 :            : 
     829   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 23 && streq_ptr(s, "final string\n is empty"));
     830                 :          4 :         s = mfree(s);
     831                 :            : 
     832   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));
     833                 :          4 :         s = mfree(s);
     834                 :            : 
     835   [ +  -  -  + ]:          4 :         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 0 && streq_ptr(s, ""));
     836                 :          4 : }
     837                 :            : 
     838                 :          4 : int main(int argc, char *argv[]) {
     839                 :          4 :         test_setup_logging(LOG_DEBUG);
     840                 :            : 
     841                 :          4 :         test_parse_env_file();
     842                 :          4 :         test_parse_multiline_env_file();
     843                 :          4 :         test_merge_env_file();
     844                 :          4 :         test_merge_env_file_invalid();
     845                 :          4 :         test_executable_is_script();
     846                 :          4 :         test_status_field();
     847                 :          4 :         test_capeff();
     848                 :          4 :         test_write_string_stream();
     849                 :          4 :         test_write_string_file();
     850                 :          4 :         test_write_string_file_no_create();
     851                 :          4 :         test_write_string_file_verify();
     852                 :          4 :         test_load_env_file_pairs();
     853                 :          4 :         test_search_and_fopen();
     854                 :          4 :         test_search_and_fopen_nulstr();
     855                 :          4 :         test_writing_tmpfile();
     856                 :          4 :         test_tempfn();
     857                 :          4 :         test_fgetc();
     858                 :          4 :         test_read_line();
     859                 :          4 :         test_read_line2();
     860                 :          4 :         test_read_line3();
     861                 :          4 :         test_read_line4();
     862                 :          4 :         test_read_nul_string();
     863                 :            : 
     864                 :          4 :         return 0;
     865                 :            : }

Generated by: LCOV version 1.14