2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2013-04-03 19:04:03 +02:00
|
|
|
|
|
|
|
#include <fcntl.h>
|
2015-11-16 22:09:36 +01:00
|
|
|
#include <stdio.h>
|
2013-04-03 19:04:03 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2013-09-19 23:22:59 +02:00
|
|
|
#include "ctype.h"
|
2018-11-30 22:08:41 +01:00
|
|
|
#include "env-file.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "env-util.h"
|
|
|
|
#include "fd-util.h"
|
|
|
|
#include "fileio.h"
|
2018-05-16 11:35:41 +02:00
|
|
|
#include "fs-util.h"
|
2016-03-02 23:50:21 +01:00
|
|
|
#include "io-util.h"
|
2015-10-26 16:18:16 +01:00
|
|
|
#include "parse-util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "process-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "strv.h"
|
2018-09-13 14:31:13 +02:00
|
|
|
#include "tests.h"
|
2018-11-30 21:05:27 +01:00
|
|
|
#include "tmpfile-util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "util.h"
|
2013-04-03 19:04:03 +02:00
|
|
|
|
|
|
|
static void test_parse_env_file(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char
|
|
|
|
t[] = "/tmp/test-fileio-in-XXXXXX",
|
2013-07-30 01:49:55 +02:00
|
|
|
p[] = "/tmp/test-fileio-out-XXXXXX";
|
2013-04-03 19:04:03 +02:00
|
|
|
FILE *f;
|
2013-04-17 15:25:02 +02:00
|
|
|
_cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
|
|
|
|
*six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL;
|
2013-04-03 19:56:39 +02:00
|
|
|
_cleanup_strv_free_ char **a = NULL, **b = NULL;
|
2013-04-03 19:04:03 +02:00
|
|
|
char **i;
|
2013-04-03 19:56:39 +02:00
|
|
|
unsigned k;
|
2018-10-23 10:50:09 +02:00
|
|
|
int r;
|
2013-04-03 19:04:03 +02:00
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
2013-04-03 19:04:03 +02:00
|
|
|
fputs("one=BAR \n"
|
|
|
|
"# comment\n"
|
|
|
|
" # comment \n"
|
2013-04-18 10:15:25 +02:00
|
|
|
" ; comment \n"
|
2013-04-03 19:04:03 +02:00
|
|
|
" two = bar \n"
|
|
|
|
"invalid line\n"
|
2013-04-18 10:15:25 +02:00
|
|
|
"invalid line #comment\n"
|
2013-04-03 19:04:03 +02:00
|
|
|
"three = \"333\n"
|
|
|
|
"xxxx\"\n"
|
|
|
|
"four = \'44\\\"44\'\n"
|
|
|
|
"five = \'55\\\'55\' \"FIVE\" cinco \n"
|
|
|
|
"six = seis sechs\\\n"
|
|
|
|
" sis\n"
|
2013-04-18 10:15:25 +02:00
|
|
|
"seven=\"sevenval\" #nocomment\n"
|
|
|
|
"eight=eightval #nocomment\n"
|
2013-04-17 15:25:02 +02:00
|
|
|
"export nine=nineval\n"
|
env-util,fileio: immediately replace variables in load_env_file_push()
strv_env_replace was calling env_match(), which in effect allowed multiple
values for the same key to be inserted into the environment block. That's
pointless, because APIs to access variables only return a single value (the
latest entry), so it's better to keep the block clean, i.e. with just a single
entry for each key.
Add a new helper function that simply tests if the part before '=' is equal in
two strings and use that in strv_env_replace.
In load_env_file_push, use strv_env_replace to immediately replace the previous
assignment with a matching name.
Afaict, none of the callers are materially affected by this change, but it
seems like some pointless work was being done, if the same value was set
multiple times. We'd go through parsing and assigning the value for each
entry. With this change, we handle just the last one.
2017-02-11 05:08:53 +01:00
|
|
|
"ten=ignored\n"
|
|
|
|
"ten=ignored\n"
|
2013-04-17 15:25:02 +02:00
|
|
|
"ten=", f);
|
2013-04-03 19:04:03 +02:00
|
|
|
|
|
|
|
fflush(f);
|
|
|
|
fclose(f);
|
|
|
|
|
2018-11-12 14:04:47 +01:00
|
|
|
r = load_env_file(NULL, t, &a);
|
2013-04-17 15:25:02 +02:00
|
|
|
assert_se(r >= 0);
|
|
|
|
|
|
|
|
STRV_FOREACH(i, a)
|
|
|
|
log_info("Got: <%s>", *i);
|
|
|
|
|
2013-12-12 23:08:47 +01:00
|
|
|
assert_se(streq_ptr(a[0], "one=BAR"));
|
|
|
|
assert_se(streq_ptr(a[1], "two=bar"));
|
|
|
|
assert_se(streq_ptr(a[2], "three=333\nxxxx"));
|
|
|
|
assert_se(streq_ptr(a[3], "four=44\"44"));
|
|
|
|
assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco"));
|
|
|
|
assert_se(streq_ptr(a[5], "six=seis sechs sis"));
|
|
|
|
assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
|
|
|
|
assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
|
|
|
|
assert_se(streq_ptr(a[8], "export nine=nineval"));
|
|
|
|
assert_se(streq_ptr(a[9], "ten="));
|
2013-04-17 15:25:02 +02:00
|
|
|
assert_se(a[10] == NULL);
|
|
|
|
|
2014-12-23 19:04:56 +01:00
|
|
|
strv_env_clean(a);
|
2013-04-17 15:25:02 +02:00
|
|
|
|
|
|
|
k = 0;
|
|
|
|
STRV_FOREACH(i, b) {
|
|
|
|
log_info("Got2: <%s>", *i);
|
|
|
|
assert_se(streq(*i, a[k++]));
|
|
|
|
}
|
|
|
|
|
2013-04-03 19:04:03 +02:00
|
|
|
r = parse_env_file(
|
2018-11-12 14:04:47 +01:00
|
|
|
NULL, t,
|
2013-04-03 19:04:03 +02:00
|
|
|
"one", &one,
|
|
|
|
"two", &two,
|
|
|
|
"three", &three,
|
|
|
|
"four", &four,
|
|
|
|
"five", &five,
|
|
|
|
"six", &six,
|
|
|
|
"seven", &seven,
|
2013-04-17 11:02:56 +02:00
|
|
|
"eight", &eight,
|
2013-04-17 15:25:02 +02:00
|
|
|
"export nine", &nine,
|
2018-11-12 14:18:03 +01:00
|
|
|
"ten", &ten);
|
2013-04-03 19:04:03 +02:00
|
|
|
|
|
|
|
assert_se(r >= 0);
|
|
|
|
|
|
|
|
log_info("one=[%s]", strna(one));
|
|
|
|
log_info("two=[%s]", strna(two));
|
|
|
|
log_info("three=[%s]", strna(three));
|
|
|
|
log_info("four=[%s]", strna(four));
|
|
|
|
log_info("five=[%s]", strna(five));
|
|
|
|
log_info("six=[%s]", strna(six));
|
|
|
|
log_info("seven=[%s]", strna(seven));
|
2013-04-17 11:02:56 +02:00
|
|
|
log_info("eight=[%s]", strna(eight));
|
2013-04-17 15:25:02 +02:00
|
|
|
log_info("export nine=[%s]", strna(nine));
|
|
|
|
log_info("ten=[%s]", strna(nine));
|
2013-04-03 19:04:03 +02:00
|
|
|
|
|
|
|
assert_se(streq(one, "BAR"));
|
|
|
|
assert_se(streq(two, "bar"));
|
|
|
|
assert_se(streq(three, "333\nxxxx"));
|
|
|
|
assert_se(streq(four, "44\"44"));
|
|
|
|
assert_se(streq(five, "55\'55FIVEcinco"));
|
|
|
|
assert_se(streq(six, "seis sechs sis"));
|
2013-04-18 10:15:25 +02:00
|
|
|
assert_se(streq(seven, "sevenval#nocomment"));
|
|
|
|
assert_se(streq(eight, "eightval #nocomment"));
|
2013-04-17 15:25:02 +02:00
|
|
|
assert_se(streq(nine, "nineval"));
|
|
|
|
assert_se(ten == NULL);
|
2013-04-03 19:04:03 +02:00
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
{
|
|
|
|
/* prepare a temporary file to write the environment to */
|
|
|
|
_cleanup_close_ int fd = mkostemp_safe(p);
|
|
|
|
assert_se(fd >= 0);
|
|
|
|
}
|
|
|
|
|
2013-07-30 01:49:55 +02:00
|
|
|
r = write_env_file(p, a);
|
2013-04-18 10:15:25 +02:00
|
|
|
assert_se(r >= 0);
|
|
|
|
|
2018-11-12 14:04:47 +01:00
|
|
|
r = load_env_file(NULL, p, &b);
|
2013-04-18 10:15:25 +02:00
|
|
|
assert_se(r >= 0);
|
2013-04-03 19:04:03 +02:00
|
|
|
}
|
|
|
|
|
2013-09-12 03:50:16 +02:00
|
|
|
static void test_parse_multiline_env_file(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char
|
|
|
|
t[] = "/tmp/test-fileio-in-XXXXXX",
|
2013-09-12 03:50:16 +02:00
|
|
|
p[] = "/tmp/test-fileio-out-XXXXXX";
|
|
|
|
FILE *f;
|
|
|
|
_cleanup_strv_free_ char **a = NULL, **b = NULL;
|
|
|
|
char **i;
|
2018-10-23 10:50:09 +02:00
|
|
|
int r;
|
2013-09-12 03:50:16 +02:00
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
2013-09-12 03:50:16 +02:00
|
|
|
fputs("one=BAR\\\n"
|
|
|
|
" VAR\\\n"
|
|
|
|
"\tGAR\n"
|
|
|
|
"#comment\n"
|
|
|
|
"two=\"bar\\\n"
|
|
|
|
" var\\\n"
|
|
|
|
"\tgar\"\n"
|
|
|
|
"#comment\n"
|
|
|
|
"tri=\"bar \\\n"
|
|
|
|
" var \\\n"
|
|
|
|
"\tgar \"\n", f);
|
|
|
|
|
|
|
|
fflush(f);
|
|
|
|
fclose(f);
|
|
|
|
|
2018-11-12 14:04:47 +01:00
|
|
|
r = load_env_file(NULL, t, &a);
|
2013-09-12 03:50:16 +02:00
|
|
|
assert_se(r >= 0);
|
|
|
|
|
|
|
|
STRV_FOREACH(i, a)
|
|
|
|
log_info("Got: <%s>", *i);
|
|
|
|
|
2013-12-12 23:08:47 +01:00
|
|
|
assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR"));
|
|
|
|
assert_se(streq_ptr(a[1], "two=bar var\tgar"));
|
|
|
|
assert_se(streq_ptr(a[2], "tri=bar var \tgar "));
|
2013-09-12 03:50:16 +02:00
|
|
|
assert_se(a[3] == NULL);
|
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
{
|
|
|
|
_cleanup_close_ int fd = mkostemp_safe(p);
|
|
|
|
assert_se(fd >= 0);
|
|
|
|
}
|
|
|
|
|
2013-09-12 03:50:16 +02:00
|
|
|
r = write_env_file(p, a);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
|
2018-11-12 14:04:47 +01:00
|
|
|
r = load_env_file(NULL, p, &b);
|
2013-09-12 03:50:16 +02:00
|
|
|
assert_se(r >= 0);
|
|
|
|
}
|
|
|
|
|
2016-08-04 18:00:00 +02:00
|
|
|
static void test_merge_env_file(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
|
2017-09-24 08:59:49 +02:00
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
2016-08-04 18:00:00 +02:00
|
|
|
_cleanup_strv_free_ char **a = NULL;
|
|
|
|
char **i;
|
2018-10-23 10:50:09 +02:00
|
|
|
int r;
|
2016-08-04 18:00:00 +02:00
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
2016-08-04 18:00:00 +02:00
|
|
|
log_info("/* %s (%s) */", __func__, t);
|
|
|
|
|
|
|
|
r = write_string_stream(f,
|
|
|
|
"one=1 \n"
|
|
|
|
"twelve=${one}2\n"
|
|
|
|
"twentyone=2${one}\n"
|
|
|
|
"one=2\n"
|
2017-02-11 20:05:10 +01:00
|
|
|
"twentytwo=2${one}\n"
|
|
|
|
"xxx_minus_three=$xxx - 3\n"
|
|
|
|
"xxx=0x$one$one$one\n"
|
2016-08-09 16:20:22 +02:00
|
|
|
"yyy=${one:-fallback}\n"
|
|
|
|
"zzz=${one:+replacement}\n"
|
|
|
|
"zzzz=${foobar:-${nothing}}\n"
|
|
|
|
"zzzzz=${nothing:+${nothing}}\n"
|
2017-09-22 20:55:34 +02:00
|
|
|
, WRITE_STRING_FILE_AVOID_NEWLINE);
|
2016-08-04 18:00:00 +02:00
|
|
|
assert(r >= 0);
|
|
|
|
|
|
|
|
r = merge_env_file(&a, NULL, t);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
strv_sort(a);
|
|
|
|
|
|
|
|
STRV_FOREACH(i, a)
|
|
|
|
log_info("Got: <%s>", *i);
|
|
|
|
|
|
|
|
assert_se(streq(a[0], "one=2"));
|
|
|
|
assert_se(streq(a[1], "twelve=12"));
|
|
|
|
assert_se(streq(a[2], "twentyone=21"));
|
|
|
|
assert_se(streq(a[3], "twentytwo=22"));
|
2017-02-11 20:05:10 +01:00
|
|
|
assert_se(streq(a[4], "xxx=0x222"));
|
|
|
|
assert_se(streq(a[5], "xxx_minus_three= - 3"));
|
2016-08-09 16:20:22 +02:00
|
|
|
assert_se(streq(a[6], "yyy=2"));
|
|
|
|
assert_se(streq(a[7], "zzz=replacement"));
|
|
|
|
assert_se(streq(a[8], "zzzz="));
|
|
|
|
assert_se(streq(a[9], "zzzzz="));
|
|
|
|
assert_se(a[10] == NULL);
|
2016-08-04 18:00:00 +02:00
|
|
|
|
|
|
|
r = merge_env_file(&a, NULL, t);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
strv_sort(a);
|
|
|
|
|
|
|
|
STRV_FOREACH(i, a)
|
|
|
|
log_info("Got2: <%s>", *i);
|
|
|
|
|
|
|
|
assert_se(streq(a[0], "one=2"));
|
|
|
|
assert_se(streq(a[1], "twelve=12"));
|
|
|
|
assert_se(streq(a[2], "twentyone=21"));
|
|
|
|
assert_se(streq(a[3], "twentytwo=22"));
|
2017-02-11 20:05:10 +01:00
|
|
|
assert_se(streq(a[4], "xxx=0x222"));
|
|
|
|
assert_se(streq(a[5], "xxx_minus_three=0x222 - 3"));
|
2016-08-09 16:20:22 +02:00
|
|
|
assert_se(streq(a[6], "yyy=2"));
|
|
|
|
assert_se(streq(a[7], "zzz=replacement"));
|
|
|
|
assert_se(streq(a[8], "zzzz="));
|
|
|
|
assert_se(streq(a[9], "zzzzz="));
|
|
|
|
assert_se(a[10] == NULL);
|
2016-08-04 18:00:00 +02:00
|
|
|
}
|
2013-09-12 03:50:16 +02:00
|
|
|
|
2017-02-18 04:56:28 +01:00
|
|
|
static void test_merge_env_file_invalid(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
|
2017-09-24 08:59:49 +02:00
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
2017-02-18 04:56:28 +01:00
|
|
|
_cleanup_strv_free_ char **a = NULL;
|
|
|
|
char **i;
|
2018-10-23 10:50:09 +02:00
|
|
|
int r;
|
2017-02-18 04:56:28 +01:00
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
2017-02-18 04:56:28 +01:00
|
|
|
log_info("/* %s (%s) */", __func__, t);
|
|
|
|
|
|
|
|
r = write_string_stream(f,
|
|
|
|
"unset one \n"
|
|
|
|
"unset one= \n"
|
|
|
|
"unset one=1 \n"
|
|
|
|
"one \n"
|
|
|
|
"one = \n"
|
|
|
|
"one two =\n"
|
|
|
|
"\x20two=\n"
|
|
|
|
"#comment=comment\n"
|
|
|
|
";comment2=comment2\n"
|
|
|
|
"#\n"
|
|
|
|
"\n\n" /* empty line */
|
2017-09-22 20:55:34 +02:00
|
|
|
, WRITE_STRING_FILE_AVOID_NEWLINE);
|
2017-02-18 04:56:28 +01:00
|
|
|
assert(r >= 0);
|
|
|
|
|
|
|
|
r = merge_env_file(&a, NULL, t);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
|
|
|
|
STRV_FOREACH(i, a)
|
|
|
|
log_info("Got: <%s>", *i);
|
|
|
|
|
|
|
|
assert_se(strv_isempty(a));
|
|
|
|
}
|
|
|
|
|
2013-07-19 10:02:50 +02:00
|
|
|
static void test_executable_is_script(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
2013-07-19 10:02:50 +02:00
|
|
|
char *command;
|
2018-10-23 10:50:09 +02:00
|
|
|
int r;
|
2013-07-19 10:02:50 +02:00
|
|
|
|
2018-10-23 10:50:09 +02:00
|
|
|
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
2013-07-19 10:02:50 +02:00
|
|
|
fputs("#! /bin/script -a -b \ngoo goo", f);
|
|
|
|
fflush(f);
|
|
|
|
|
|
|
|
r = executable_is_script(t, &command);
|
|
|
|
assert_se(r > 0);
|
|
|
|
assert_se(streq(command, "/bin/script"));
|
|
|
|
free(command);
|
|
|
|
|
|
|
|
r = executable_is_script("/bin/sh", &command);
|
|
|
|
assert_se(r == 0);
|
|
|
|
|
|
|
|
r = executable_is_script("/usr/bin/yum", &command);
|
|
|
|
assert_se(r > 0 || r == -ENOENT);
|
|
|
|
if (r > 0) {
|
|
|
|
assert_se(startswith(command, "/"));
|
|
|
|
free(command);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-14 01:41:52 +02:00
|
|
|
static void test_status_field(void) {
|
2013-09-19 23:22:59 +02:00
|
|
|
_cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
|
|
|
|
unsigned long long total = 0, buffers = 0;
|
2013-09-15 14:40:16 +02:00
|
|
|
int r;
|
2013-09-14 01:41:52 +02:00
|
|
|
|
2015-09-30 14:57:55 +02:00
|
|
|
assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
|
2013-09-14 01:41:52 +02:00
|
|
|
puts(t);
|
|
|
|
assert_se(streq(t, "1"));
|
|
|
|
|
2015-09-30 14:57:55 +02:00
|
|
|
r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
|
2013-09-19 23:22:59 +02:00
|
|
|
if (r != -ENOENT) {
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(r == 0);
|
2013-09-19 23:22:59 +02:00
|
|
|
puts(p);
|
|
|
|
assert_se(safe_atollu(p, &total) == 0);
|
|
|
|
}
|
2013-09-14 01:41:52 +02:00
|
|
|
|
2015-09-30 14:57:55 +02:00
|
|
|
r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s);
|
2013-09-19 23:22:59 +02:00
|
|
|
if (r != -ENOENT) {
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(r == 0);
|
2013-09-19 23:22:59 +02:00
|
|
|
puts(s);
|
|
|
|
assert_se(safe_atollu(s, &buffers) == 0);
|
|
|
|
}
|
2013-09-14 01:41:52 +02:00
|
|
|
|
2014-09-30 23:37:10 +02:00
|
|
|
if (p)
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(buffers < total);
|
2013-09-19 23:22:59 +02:00
|
|
|
|
|
|
|
/* Seccomp should be a good test for field full of zeros. */
|
2015-09-30 14:57:55 +02:00
|
|
|
r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z);
|
2013-09-19 23:22:59 +02:00
|
|
|
if (r != -ENOENT) {
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(r == 0);
|
2013-09-19 23:22:59 +02:00
|
|
|
puts(z);
|
|
|
|
assert_se(safe_atollu(z, &buffers) == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_capeff(void) {
|
|
|
|
int pid, p;
|
|
|
|
|
|
|
|
for (pid = 0; pid < 2; pid++) {
|
|
|
|
_cleanup_free_ char *capeff = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = get_process_capeff(0, &capeff);
|
|
|
|
log_info("capeff: '%s' (r=%d)", capeff, r);
|
|
|
|
|
2017-10-04 16:01:32 +02:00
|
|
|
if (IN_SET(r, -ENOENT, -EPERM))
|
2013-09-19 23:22:59 +02:00
|
|
|
return;
|
|
|
|
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(r == 0);
|
|
|
|
assert_se(*capeff);
|
2016-05-17 15:44:32 +02:00
|
|
|
p = capeff[strspn(capeff, HEXDIGITS)];
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(!p || isspace(p));
|
2013-09-19 23:22:59 +02:00
|
|
|
}
|
2013-09-14 01:41:52 +02:00
|
|
|
}
|
|
|
|
|
2014-08-16 14:19:07 +02:00
|
|
|
static void test_write_string_stream(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
2014-08-16 14:19:07 +02:00
|
|
|
int fd;
|
|
|
|
char buf[64];
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(fn);
|
2014-08-16 14:19:07 +02:00
|
|
|
assert_se(fd >= 0);
|
|
|
|
|
|
|
|
f = fdopen(fd, "r");
|
|
|
|
assert_se(f);
|
2017-09-22 20:55:34 +02:00
|
|
|
assert_se(write_string_stream(f, "boohoo", 0) < 0);
|
2018-03-05 22:23:33 +01:00
|
|
|
f = safe_fclose(f);
|
2014-08-16 14:19:07 +02:00
|
|
|
|
2018-03-05 22:23:33 +01:00
|
|
|
f = fopen(fn, "r+");
|
2014-08-16 14:19:07 +02:00
|
|
|
assert_se(f);
|
|
|
|
|
2017-09-22 20:55:34 +02:00
|
|
|
assert_se(write_string_stream(f, "boohoo", 0) == 0);
|
2014-08-16 14:19:07 +02:00
|
|
|
rewind(f);
|
|
|
|
|
|
|
|
assert_se(fgets(buf, sizeof(buf), f));
|
|
|
|
assert_se(streq(buf, "boohoo\n"));
|
2018-03-05 22:23:33 +01:00
|
|
|
f = safe_fclose(f);
|
2014-08-16 14:19:07 +02:00
|
|
|
|
2018-03-05 22:23:33 +01:00
|
|
|
f = fopen(fn, "w+");
|
2015-07-06 23:31:44 +02:00
|
|
|
assert_se(f);
|
|
|
|
|
2017-09-22 20:55:34 +02:00
|
|
|
assert_se(write_string_stream(f, "boohoo", WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
|
2015-07-06 23:31:44 +02:00
|
|
|
rewind(f);
|
|
|
|
|
|
|
|
assert_se(fgets(buf, sizeof(buf), f));
|
|
|
|
printf(">%s<", buf);
|
|
|
|
assert_se(streq(buf, "boohoo"));
|
2014-08-16 14:19:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_write_string_file(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
|
2014-09-18 12:09:10 +02:00
|
|
|
char buf[64] = {};
|
|
|
|
_cleanup_close_ int fd;
|
2014-08-16 14:19:07 +02:00
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(fn);
|
2014-08-16 14:19:07 +02:00
|
|
|
assert_se(fd >= 0);
|
|
|
|
|
2015-07-07 01:19:25 +02:00
|
|
|
assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
|
2014-08-16 14:19:07 +02:00
|
|
|
|
2014-09-16 21:59:50 +02:00
|
|
|
assert_se(read(fd, buf, sizeof(buf)) == 7);
|
2014-08-16 14:19:07 +02:00
|
|
|
assert_se(streq(buf, "boohoo\n"));
|
|
|
|
}
|
|
|
|
|
2014-09-02 18:55:31 +02:00
|
|
|
static void test_write_string_file_no_create(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
|
2014-09-02 18:55:31 +02:00
|
|
|
_cleanup_close_ int fd;
|
|
|
|
char buf[64] = {0};
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(fn);
|
2014-09-02 18:55:31 +02:00
|
|
|
assert_se(fd >= 0);
|
|
|
|
|
2015-07-07 01:19:25 +02:00
|
|
|
assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
|
|
|
|
assert_se(write_string_file(fn, "boohoo", 0) == 0);
|
2014-09-02 18:55:31 +02:00
|
|
|
|
2017-12-14 19:02:29 +01:00
|
|
|
assert_se(read(fd, buf, sizeof(buf)) == STRLEN("boohoo\n"));
|
2014-09-02 18:55:31 +02:00
|
|
|
assert_se(streq(buf, "boohoo\n"));
|
|
|
|
}
|
|
|
|
|
2015-11-13 00:54:56 +01:00
|
|
|
static void test_write_string_file_verify(void) {
|
|
|
|
_cleanup_free_ char *buf = NULL, *buf2 = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
|
2018-05-14 09:12:12 +02:00
|
|
|
assert_se(buf2 = strjoin(buf, "\n"));
|
2015-11-13 00:54:56 +01:00
|
|
|
|
|
|
|
r = write_string_file("/proc/cmdline", buf, 0);
|
2017-10-04 16:01:32 +02:00
|
|
|
assert_se(IN_SET(r, -EACCES, -EIO));
|
2015-11-13 00:54:56 +01:00
|
|
|
r = write_string_file("/proc/cmdline", buf2, 0);
|
2017-10-04 16:01:32 +02:00
|
|
|
assert_se(IN_SET(r, -EACCES, -EIO));
|
2015-11-13 00:54:56 +01:00
|
|
|
|
|
|
|
assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
|
|
|
|
assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
|
|
|
|
|
|
|
|
r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE);
|
2017-10-04 16:01:32 +02:00
|
|
|
assert_se(IN_SET(r, -EACCES, -EIO));
|
2015-11-13 00:54:56 +01:00
|
|
|
assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
|
|
|
|
}
|
|
|
|
|
2014-09-02 18:55:31 +02:00
|
|
|
static void test_load_env_file_pairs(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
|
|
|
|
int fd, r;
|
2014-09-02 18:55:31 +02:00
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
_cleanup_strv_free_ char **l = NULL;
|
|
|
|
char **k, **v;
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(fn);
|
2014-09-02 18:55:31 +02:00
|
|
|
assert_se(fd >= 0);
|
|
|
|
|
|
|
|
r = write_string_file(fn,
|
|
|
|
"NAME=\"Arch Linux\"\n"
|
|
|
|
"ID=arch\n"
|
|
|
|
"PRETTY_NAME=\"Arch Linux\"\n"
|
|
|
|
"ANSI_COLOR=\"0;36\"\n"
|
|
|
|
"HOME_URL=\"https://www.archlinux.org/\"\n"
|
|
|
|
"SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
|
2015-07-07 01:19:25 +02:00
|
|
|
"BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n",
|
|
|
|
WRITE_STRING_FILE_CREATE);
|
2014-09-02 18:55:31 +02:00
|
|
|
assert_se(r == 0);
|
|
|
|
|
|
|
|
f = fdopen(fd, "r");
|
|
|
|
assert_se(f);
|
|
|
|
|
2018-11-12 14:04:47 +01:00
|
|
|
r = load_env_file_pairs(f, fn, &l);
|
2014-09-02 18:55:31 +02:00
|
|
|
assert_se(r >= 0);
|
|
|
|
|
|
|
|
assert_se(strv_length(l) == 14);
|
|
|
|
STRV_FOREACH_PAIR(k, v, l) {
|
|
|
|
assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
|
|
|
|
printf("%s=%s\n", *k, *v);
|
|
|
|
if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
|
|
|
|
if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
|
|
|
|
if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
|
|
|
|
if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
|
|
|
|
if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
|
|
|
|
if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
|
|
|
|
if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-02 23:50:21 +01:00
|
|
|
static void test_search_and_fopen(void) {
|
|
|
|
const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
|
2018-05-16 11:35:41 +02:00
|
|
|
|
2016-03-02 23:50:21 +01:00
|
|
|
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
2018-05-16 11:35:41 +02:00
|
|
|
int fd, r;
|
2016-03-02 23:50:21 +01:00
|
|
|
FILE *f;
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(name);
|
2016-03-02 23:50:21 +01:00
|
|
|
assert_se(fd >= 0);
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
r = search_and_fopen(name, "r", NULL, dirs, &f);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
r = search_and_fopen(basename(name), "r", "/", dirs, &f);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
|
|
|
|
assert_se(r < 0);
|
|
|
|
r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
|
|
|
|
assert_se(r < 0);
|
|
|
|
|
|
|
|
r = unlink(name);
|
|
|
|
assert_se(r == 0);
|
|
|
|
|
|
|
|
r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
|
|
|
|
assert_se(r < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_search_and_fopen_nulstr(void) {
|
|
|
|
const char dirs[] = "/tmp/foo/bar\0/tmp\0";
|
2018-05-16 11:35:41 +02:00
|
|
|
|
|
|
|
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
|
|
|
int fd, r;
|
2016-03-02 23:50:21 +01:00
|
|
|
FILE *f;
|
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(name);
|
2016-03-02 23:50:21 +01:00
|
|
|
assert_se(fd >= 0);
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
|
|
|
|
assert_se(r < 0);
|
|
|
|
r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
|
|
|
|
assert_se(r < 0);
|
|
|
|
|
|
|
|
r = unlink(name);
|
|
|
|
assert_se(r == 0);
|
|
|
|
|
|
|
|
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
|
|
|
|
assert_se(r < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_writing_tmpfile(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
|
2016-03-02 23:50:21 +01:00
|
|
|
_cleanup_free_ char *contents = NULL;
|
|
|
|
size_t size;
|
2018-03-05 23:05:46 +01:00
|
|
|
_cleanup_close_ int fd = -1;
|
2016-03-02 23:50:21 +01:00
|
|
|
struct iovec iov[3];
|
2018-05-16 11:35:41 +02:00
|
|
|
int r;
|
2016-03-02 23:50:21 +01:00
|
|
|
|
2017-09-21 13:52:34 +02:00
|
|
|
iov[0] = IOVEC_MAKE_STRING("abc\n");
|
|
|
|
iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n");
|
|
|
|
iov[2] = IOVEC_MAKE_STRING("");
|
2016-03-02 23:50:21 +01:00
|
|
|
|
2016-09-13 08:20:38 +02:00
|
|
|
fd = mkostemp_safe(name);
|
2016-03-02 23:50:21 +01:00
|
|
|
printf("tmpfile: %s", name);
|
|
|
|
|
|
|
|
r = writev(fd, iov, 3);
|
|
|
|
assert_se(r >= 0);
|
|
|
|
|
|
|
|
r = read_full_file(name, &contents, &size);
|
|
|
|
assert_se(r == 0);
|
|
|
|
printf("contents: %s", contents);
|
|
|
|
assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_tempfn(void) {
|
|
|
|
char *ret = NULL, *p;
|
|
|
|
|
|
|
|
assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
|
|
|
|
assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
|
|
|
|
free(ret);
|
|
|
|
|
|
|
|
assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
|
|
|
|
assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
|
|
|
|
free(ret);
|
|
|
|
|
|
|
|
assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
|
|
|
|
assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
|
|
|
|
assert_se(strlen(p) == 16);
|
|
|
|
assert_se(in_charset(p, "0123456789abcdef"));
|
|
|
|
free(ret);
|
|
|
|
|
|
|
|
assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
|
|
|
|
assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
|
|
|
|
assert_se(strlen(p) == 16);
|
|
|
|
assert_se(in_charset(p, "0123456789abcdef"));
|
|
|
|
free(ret);
|
|
|
|
|
|
|
|
assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
|
|
|
|
assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
|
|
|
|
assert_se(strlen(p) == 16);
|
|
|
|
assert_se(in_charset(p, "0123456789abcdef"));
|
|
|
|
free(ret);
|
|
|
|
|
|
|
|
assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
|
|
|
|
assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
|
|
|
|
assert_se(strlen(p) == 16);
|
|
|
|
assert_se(in_charset(p, "0123456789abcdef"));
|
|
|
|
free(ret);
|
|
|
|
}
|
|
|
|
|
2017-09-24 09:10:48 +02:00
|
|
|
static const char buffer[] =
|
|
|
|
"Some test data\n"
|
2018-12-12 13:41:25 +01:00
|
|
|
"Some weird line\r"
|
|
|
|
"terminators\r\n"
|
|
|
|
"and even more\n\r"
|
|
|
|
"now the same with a NUL\n\0"
|
|
|
|
"and more\r\0"
|
|
|
|
"and even more\r\n\0"
|
|
|
|
"and yet even more\n\r\0"
|
2017-09-24 09:10:48 +02:00
|
|
|
"With newlines, and a NUL byte\0"
|
|
|
|
"\n"
|
|
|
|
"an empty line\n"
|
|
|
|
"an ignored line\n"
|
|
|
|
"and a very long line that is supposed to be truncated, because it is so long\n";
|
|
|
|
|
|
|
|
static void test_read_line_one_file(FILE *f) {
|
2017-09-22 17:55:53 +02:00
|
|
|
_cleanup_free_ char *line = NULL;
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
2018-12-12 13:41:25 +01:00
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 16 && streq(line, "Some weird line"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 13 && streq(line, "terminators"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "and even more"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 25 && streq(line, "now the same with a NUL"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 10 && streq(line, "and more"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 16 && streq(line, "and even more"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, &line) == 20 && streq(line, "and yet even more"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
2017-09-22 17:55:53 +02:00
|
|
|
assert_se(read_line(f, 1024, &line) == 30 && streq(line, "With newlines, and a NUL byte"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, 1024, &line) == 14 && streq(line, "an empty line"));
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, NULL) == 16);
|
|
|
|
|
|
|
|
assert_se(read_line(f, 16, &line) == -ENOBUFS);
|
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
/* read_line() stopped when it hit the limit, that means when we continue reading we'll read at the first
|
|
|
|
* character after the previous limit. Let's make use of tha to continue our test. */
|
2018-12-12 13:41:25 +01:00
|
|
|
assert_se(read_line(f, 1024, &line) == 62 && streq(line, "line that is supposed to be truncated, because it is so long"));
|
2017-09-22 17:55:53 +02:00
|
|
|
line = mfree(line);
|
|
|
|
|
|
|
|
assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
|
|
|
|
}
|
|
|
|
|
2017-09-24 09:10:48 +02:00
|
|
|
static void test_read_line(void) {
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
|
|
|
|
f = fmemopen((void*) buffer, sizeof(buffer), "re");
|
|
|
|
assert_se(f);
|
|
|
|
|
|
|
|
test_read_line_one_file(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_read_line2(void) {
|
2018-05-16 11:35:41 +02:00
|
|
|
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fileio.XXXXXX";
|
2017-09-24 09:10:48 +02:00
|
|
|
int fd;
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
|
|
|
|
fd = mkostemp_safe(name);
|
|
|
|
assert_se(fd >= 0);
|
|
|
|
assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
|
|
|
|
|
|
|
|
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
|
|
|
assert_se(f = fdopen(fd, "r"));
|
|
|
|
|
|
|
|
test_read_line_one_file(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_read_line3(void) {
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
_cleanup_free_ char *line = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
f = fopen("/proc/cmdline", "re");
|
|
|
|
if (!f && IN_SET(errno, ENOENT, EPERM))
|
|
|
|
return;
|
|
|
|
assert_se(f);
|
|
|
|
|
|
|
|
r = read_line(f, LINE_MAX, &line);
|
|
|
|
assert_se((size_t) r == strlen(line) + 1);
|
|
|
|
assert_se(read_line(f, LINE_MAX, NULL) == 0);
|
|
|
|
}
|
|
|
|
|
2018-12-14 12:57:32 +01:00
|
|
|
static void test_read_line4(void) {
|
|
|
|
static const struct {
|
|
|
|
size_t length;
|
|
|
|
const char *string;
|
|
|
|
} eof_endings[] = {
|
|
|
|
/* Each of these will be followed by EOF and should generate the one same single string */
|
|
|
|
{ 3, "foo" },
|
|
|
|
{ 4, "foo\n" },
|
|
|
|
{ 4, "foo\r" },
|
|
|
|
{ 4, "foo\0" },
|
|
|
|
{ 5, "foo\n\0" },
|
|
|
|
{ 5, "foo\r\0" },
|
|
|
|
{ 5, "foo\r\n" },
|
|
|
|
{ 5, "foo\n\r" },
|
|
|
|
{ 6, "foo\r\n\0" },
|
|
|
|
{ 6, "foo\n\r\0" },
|
|
|
|
};
|
|
|
|
|
|
|
|
size_t i;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
for (i = 0; i < ELEMENTSOF(eof_endings); i++) {
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
_cleanup_free_ char *s = NULL;
|
|
|
|
|
|
|
|
assert_se(f = fmemopen((void*) eof_endings[i].string, eof_endings[i].length, "r"));
|
|
|
|
|
|
|
|
r = read_line(f, (size_t) -1, &s);
|
|
|
|
assert_se((size_t) r == eof_endings[i].length);
|
|
|
|
assert_se(streq_ptr(s, "foo"));
|
|
|
|
|
|
|
|
assert_se(read_line(f, (size_t) -1, NULL) == 0); /* Ensure we hit EOF */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-17 11:52:51 +01:00
|
|
|
static void test_read_nul_string(void) {
|
|
|
|
static const char test[] = "string nr. 1\0"
|
|
|
|
"string nr. 2\n\0"
|
|
|
|
"empty string follows\0"
|
|
|
|
"\0"
|
|
|
|
"final string\n is empty\0"
|
|
|
|
"\0";
|
|
|
|
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
_cleanup_free_ char *s = NULL;
|
|
|
|
|
|
|
|
assert_se(f = fmemopen((void*) test, sizeof(test)-1, "r"));
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 13 && streq_ptr(s, "string nr. 1"));
|
|
|
|
s = mfree(s);
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 14 && streq_ptr(s, "string nr. 2\n"));
|
|
|
|
s = mfree(s);
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 21 && streq_ptr(s, "empty string follows"));
|
|
|
|
s = mfree(s);
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));
|
|
|
|
s = mfree(s);
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 23 && streq_ptr(s, "final string\n is empty"));
|
|
|
|
s = mfree(s);
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));
|
|
|
|
s = mfree(s);
|
|
|
|
|
|
|
|
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 0 && streq_ptr(s, ""));
|
|
|
|
}
|
|
|
|
|
2013-04-03 19:04:03 +02:00
|
|
|
int main(int argc, char *argv[]) {
|
2018-09-13 14:31:13 +02:00
|
|
|
test_setup_logging(LOG_DEBUG);
|
2013-09-19 23:22:59 +02:00
|
|
|
|
2013-04-03 19:04:03 +02:00
|
|
|
test_parse_env_file();
|
2013-09-12 03:50:16 +02:00
|
|
|
test_parse_multiline_env_file();
|
2016-08-04 18:00:00 +02:00
|
|
|
test_merge_env_file();
|
2017-02-18 04:56:28 +01:00
|
|
|
test_merge_env_file_invalid();
|
2013-07-19 10:02:50 +02:00
|
|
|
test_executable_is_script();
|
2013-09-14 01:41:52 +02:00
|
|
|
test_status_field();
|
2013-09-19 23:22:59 +02:00
|
|
|
test_capeff();
|
2014-08-16 14:19:07 +02:00
|
|
|
test_write_string_stream();
|
|
|
|
test_write_string_file();
|
2014-09-02 18:55:31 +02:00
|
|
|
test_write_string_file_no_create();
|
2015-11-13 00:54:56 +01:00
|
|
|
test_write_string_file_verify();
|
2014-09-02 18:55:31 +02:00
|
|
|
test_load_env_file_pairs();
|
2016-03-02 23:50:21 +01:00
|
|
|
test_search_and_fopen();
|
|
|
|
test_search_and_fopen_nulstr();
|
|
|
|
test_writing_tmpfile();
|
|
|
|
test_tempfn();
|
2017-09-22 17:55:53 +02:00
|
|
|
test_read_line();
|
2017-09-24 09:10:48 +02:00
|
|
|
test_read_line2();
|
|
|
|
test_read_line3();
|
2018-12-14 12:57:32 +01:00
|
|
|
test_read_line4();
|
2018-12-17 11:52:51 +01:00
|
|
|
test_read_nul_string();
|
2013-09-19 23:22:59 +02:00
|
|
|
|
2013-04-03 19:04:03 +02:00
|
|
|
return 0;
|
|
|
|
}
|