Merge pull request #12217 from keszybz/unlocked-operations

Refactor how we do unlocked file operations
This commit is contained in:
Lennart Poettering
2019-04-12 13:51:53 +02:00
committed by GitHub
52 changed files with 294 additions and 326 deletions
+11 -16
View File
@@ -6,7 +6,6 @@
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -1016,11 +1015,11 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
}
fs = procfs_file_alloca(pid, "cgroup");
f = fopen(fs, "re");
if (!f)
return errno == ENOENT ? -ESRCH : -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(fs, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
for (;;) {
_cleanup_free_ char *line = NULL;
@@ -2442,17 +2441,13 @@ int cg_kernel_controllers(Set **ret) {
if (!controllers)
return -ENOMEM;
f = fopen("/proc/cgroups", "re");
if (!f) {
if (errno == ENOENT) {
*ret = NULL;
return 0;
}
return -errno;
r = fopen_unlocked("/proc/cgroups", "re", &f);
if (r == -ENOENT) {
*ret = NULL;
return 0;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
if (r < 0)
return r;
/* Ignore the header line */
(void) read_line(f, (size_t) -1, NULL);
-3
View File
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio_ext.h>
#include "alloc-util.h"
#include "env-file.h"
#include "env-util.h"
@@ -545,7 +543,6 @@ int write_env_file(const char *fname, char **l) {
if (r < 0)
return r;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
STRV_FOREACH(i, l)
+62 -25
View File
@@ -29,6 +29,52 @@
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
int fopen_unlocked(const char *path, const char *options, FILE **ret) {
assert(ret);
FILE *f = fopen(path, options);
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
*ret = f;
return 0;
}
int fdopen_unlocked(int fd, const char *options, FILE **ret) {
assert(ret);
FILE *f = fdopen(fd, options);
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
*ret = f;
return 0;
}
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
FILE *f = open_memstream(ptr, sizeloc);
if (!f)
return NULL;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
return f;
}
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) {
FILE *f = fmemopen(buf, size, mode);
if (!f)
return NULL;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
return f;
}
int write_string_stream_ts(
FILE *f,
const char *line,
@@ -95,7 +141,6 @@ static int write_string_file_atomic(
if (r < 0)
return r;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
r = write_string_stream_ts(f, line, flags, ts);
@@ -141,11 +186,9 @@ int write_string_file_ts(
assert(!ts);
if (flags & WRITE_STRING_FILE_CREATE) {
f = fopen(fn, "we");
if (!f) {
r = -errno;
r = fopen_unlocked(fn, "we", &f);
if (r < 0)
goto fail;
}
} else {
int fd;
@@ -157,16 +200,13 @@ int write_string_file_ts(
goto fail;
}
f = fdopen(fd, "w");
if (!f) {
r = -errno;
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
safe_close(fd);
goto fail;
}
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
setvbuf(f, NULL, _IONBF, 0);
@@ -213,15 +253,14 @@ int write_string_filef(
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(fn);
assert(line);
f = fopen(fn, "re");
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(fn, "re", &f);
if (r < 0)
return r;
return read_line(f, LONG_LINE_MAX, line);
}
@@ -230,6 +269,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *buf = NULL;
size_t l, k;
int r;
assert(fn);
assert(blob);
@@ -243,11 +283,9 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
if (!buf)
return -ENOMEM;
f = fopen(fn, "re");
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(fn, "re", &f);
if (r < 0)
return r;
/* We try to read one byte more than we need, so that we know whether we hit eof */
errno = 0;
@@ -390,15 +428,14 @@ finalize:
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(filename);
assert(contents);
f = fopen(filename, "re");
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(filename, "re", &f);
if (r < 0)
return r;
return read_full_stream_full(f, filename, flags, contents, size);
}
+5
View File
@@ -33,6 +33,11 @@ typedef enum {
READ_FULL_FILE_UNBASE64 = 1 << 1,
} ReadFullFileFlags;
int fopen_unlocked(const char *path, const char *options, FILE **ret);
int fdopen_unlocked(int fd, const char *options, FILE **ret);
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc);
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode);
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
return write_string_stream_ts(f, line, flags, NULL);
+3 -6
View File
@@ -2,7 +2,6 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio_ext.h>
#include <sys/mount.h>
#include "alloc-util.h"
@@ -378,11 +377,9 @@ int dev_is_devtmpfs(void) {
if (r < 0)
return r;
proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
if (!proc_self_mountinfo)
return -errno;
(void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER);
r = fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo);
if (r < 0)
return r;
for (;;) {
_cleanup_free_ char *line = NULL;
+21 -36
View File
@@ -8,7 +8,6 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -106,7 +105,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
char *k;
_cleanup_free_ char *ans = NULL;
const char *p;
int c;
int c, r;
assert(line);
assert(pid >= 0);
@@ -121,15 +120,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
* comm_fallback is false). Returns 0 and sets *line otherwise. */
p = procfs_file_alloca(pid, "cmdline");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(p, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
if (max_length == 0) {
/* This is supposed to be a safety guard against runaway command lines. */
@@ -513,14 +508,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
return -EINVAL;
p = procfs_file_alloca(pid, "status");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(p, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
for (;;) {
_cleanup_free_ char *line = NULL;
@@ -602,14 +594,11 @@ int get_process_environ(pid_t pid, char **env) {
p = procfs_file_alloca(pid, "environ");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(p, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
for (;;) {
char c;
@@ -895,15 +884,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
path = procfs_file_alloca(pid, "environ");
f = fopen(path, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(path, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
l = strlen(field);
for (;;) {
+6 -10
View File
@@ -4,7 +4,6 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
@@ -761,23 +760,20 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
* 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
* 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
*
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
* other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
* most basic formatting noise, but nothing else.
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
* are any other special characters. Truncated ANSI sequences are left-as is too. This call is
* supposed to suppress the most basic formatting noise, but nothing else.
*
* Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
isz = _isz ? *_isz : strlen(*ibuf);
f = open_memstream(&obuf, &osz);
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we
* created f here and it doesn't leave our scope. */
f = open_memstream_unlocked(&obuf, &osz);
if (!f)
return NULL;
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here
* and it doesn't leave our scope. */
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
switch (state) {
+9 -4
View File
@@ -1,9 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
#include <sys/mman.h>
#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "macro.h"
@@ -37,12 +39,15 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
return -errno;
}
f = fdopen(fd, "w");
if (!f) {
unlink_noerrno(t);
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
* context and never shared externally, hence locking is not necessary. */
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
unlink(t);
free(t);
safe_close(fd);
return -errno;
return r;
}
*_f = f;