mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 15:21:37 +03:00
fileio: add an openat() flavour for fopen()
This adds xfopenat() which is to fopen() what xopendirat() is to opendir(), i.e. the "at" counterpart to fopen(). (Similar to the xopendir() case, we prefix this with "x", in case libc gains this natively eventually.)
This commit is contained in:
parent
6d8f06368b
commit
0a38e6b9a3
@ -680,6 +680,81 @@ DIR *xopendirat(int fd, const char *name, int flags) {
|
||||
return d;
|
||||
}
|
||||
|
||||
static int mode_to_flags(const char *mode) {
|
||||
const char *p;
|
||||
int flags;
|
||||
|
||||
if ((p = startswith(mode, "r+")))
|
||||
flags = O_RDWR;
|
||||
else if ((p = startswith(mode, "r")))
|
||||
flags = O_RDONLY;
|
||||
else if ((p = startswith(mode, "w+")))
|
||||
flags = O_RDWR|O_CREAT|O_TRUNC;
|
||||
else if ((p = startswith(mode, "w")))
|
||||
flags = O_WRONLY|O_CREAT|O_TRUNC;
|
||||
else if ((p = startswith(mode, "a+")))
|
||||
flags = O_RDWR|O_CREAT|O_APPEND;
|
||||
else if ((p = startswith(mode, "a")))
|
||||
flags = O_WRONLY|O_CREAT|O_APPEND;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
for (; *p != 0; p++) {
|
||||
|
||||
switch (*p) {
|
||||
|
||||
case 'e':
|
||||
flags |= O_CLOEXEC;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
flags |= O_EXCL;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
/* ignore this here, fdopen() might care later though */
|
||||
break;
|
||||
|
||||
case 'c': /* not sure what to do about this one */
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret) {
|
||||
FILE *f;
|
||||
|
||||
/* A combination of fopen() with openat() */
|
||||
|
||||
if (dir_fd == AT_FDCWD && flags == 0) {
|
||||
f = fopen(path, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
} else {
|
||||
int fd, mode_flags;
|
||||
|
||||
mode_flags = mode_to_flags(mode);
|
||||
if (mode_flags < 0)
|
||||
return mode_flags;
|
||||
|
||||
fd = openat(dir_fd, path, mode_flags | flags);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
f = fdopen(fd, mode);
|
||||
if (!f) {
|
||||
safe_close(fd);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
|
||||
char **i;
|
||||
|
||||
|
@ -69,6 +69,7 @@ int executable_is_script(const char *path, char **interpreter);
|
||||
int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field);
|
||||
|
||||
DIR *xopendirat(int dirfd, const char *name, int flags);
|
||||
int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret);
|
||||
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
|
||||
|
Loading…
Reference in New Issue
Block a user