1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include <linux/magic.h>
11 #include <sys/sendfile.h>
13 #include <sys/types.h>
17 #include "file_utils.h"
19 #include "memory_utils.h"
20 #include "string_utils.h"
21 #include "syscall_wrappers.h"
24 int lxc_open_dirfd(const char *dir
)
26 return open_at(-EBADF
, dir
, PROTECT_OPATH_DIRECTORY
, PROTECT_LOOKUP_ABSOLUTE
& ~RESOLVE_NO_XDEV
, 0);
29 int lxc_readat(int dirfd
, const char *filename
, void *buf
, size_t count
)
31 __do_close
int fd
= -EBADF
;
34 fd
= open_at(dirfd
, filename
, PROTECT_OPEN
, PROTECT_LOOKUP_BENEATH
, 0);
38 ret
= lxc_read_nointr(fd
, buf
, count
);
45 int lxc_writeat(int dirfd
, const char *filename
, const void *buf
, size_t count
)
47 __do_close
int fd
= -EBADF
;
50 fd
= open_at(dirfd
, filename
, PROTECT_OPEN_W_WITH_TRAILING_SYMLINKS
, PROTECT_LOOKUP_BENEATH
, 0);
54 ret
= lxc_write_nointr(fd
, buf
, count
);
55 if (ret
< 0 || (size_t)ret
!= count
)
61 int lxc_write_openat(const char *dir
, const char *filename
, const void *buf
,
64 __do_close
int dirfd
= -EBADF
;
66 dirfd
= open(dir
, PROTECT_OPEN
);
70 return lxc_writeat(dirfd
, filename
, buf
, count
);
73 int lxc_write_to_file(const char *filename
, const void *buf
, size_t count
,
74 bool add_newline
, mode_t mode
)
76 __do_close
int fd
= -EBADF
;
79 fd
= open(filename
, O_WRONLY
| O_TRUNC
| O_CREAT
| O_CLOEXEC
, mode
);
83 ret
= lxc_write_nointr(fd
, buf
, count
);
87 if ((size_t)ret
!= count
)
91 ret
= lxc_write_nointr(fd
, "\n", 1);
99 int lxc_read_from_file(const char *filename
, void *buf
, size_t count
)
101 __do_close
int fd
= -EBADF
;
104 fd
= open(filename
, O_RDONLY
| O_CLOEXEC
);
108 if (!buf
|| !count
) {
112 while ((ret
= lxc_read_nointr(fd
, buf2
, 100)) > 0)
118 memset(buf
, 0, count
);
119 ret
= lxc_read_nointr(fd
, buf
, count
);
125 ssize_t
lxc_read_try_buf_at(int dfd
, const char *path
, void *buf
, size_t count
)
127 __do_close
int fd
= -EBADF
;
130 fd
= open_at(dfd
, path
, PROTECT_OPEN
, PROTECT_LOOKUP_BENEATH
, 0);
134 if (!buf
|| !count
) {
138 while ((ret
= lxc_read_nointr(fd
, buf2
, 100)) > 0)
144 memset(buf
, 0, count
);
145 ret
= lxc_read_nointr(fd
, buf
, count
);
151 ssize_t
lxc_write_nointr(int fd
, const void *buf
, size_t count
)
156 ret
= write(fd
, buf
, count
);
157 } while (ret
< 0 && errno
== EINTR
);
162 ssize_t
lxc_pwrite_nointr(int fd
, const void *buf
, size_t count
, off_t offset
)
167 ret
= pwrite(fd
, buf
, count
, offset
);
168 } while (ret
< 0 && errno
== EINTR
);
173 ssize_t
lxc_send_nointr(int sockfd
, void *buf
, size_t len
, int flags
)
178 ret
= send(sockfd
, buf
, len
, flags
);
179 } while (ret
< 0 && errno
== EINTR
);
184 ssize_t
lxc_read_nointr(int fd
, void *buf
, size_t count
)
189 ret
= read(fd
, buf
, count
);
190 } while (ret
< 0 && errno
== EINTR
);
195 ssize_t
lxc_recv_nointr(int sockfd
, void *buf
, size_t len
, int flags
)
200 ret
= recv(sockfd
, buf
, len
, flags
);
201 } while (ret
< 0 && errno
== EINTR
);
206 ssize_t
lxc_recvmsg_nointr_iov(int sockfd
, struct iovec
*iov
, size_t iovlen
,
210 struct msghdr msg
= {
212 .msg_iovlen
= iovlen
,
216 ret
= recvmsg(sockfd
, &msg
, flags
);
217 } while (ret
< 0 && errno
== EINTR
);
222 ssize_t
lxc_read_nointr_expect(int fd
, void *buf
, size_t count
,
223 const void *expected_buf
)
227 ret
= lxc_read_nointr(fd
, buf
, count
);
231 if ((size_t)ret
!= count
)
234 if (expected_buf
&& memcmp(buf
, expected_buf
, count
) != 0)
235 return ret_set_errno(-1, EINVAL
);
240 ssize_t
lxc_read_file_expect(const char *path
, void *buf
, size_t count
,
241 const void *expected_buf
)
243 __do_close
int fd
= -EBADF
;
245 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
249 return lxc_read_nointr_expect(fd
, buf
, count
, expected_buf
);
252 bool file_exists(const char *f
)
256 return stat(f
, &statbuf
) == 0;
259 int print_to_file(const char *file
, const char *content
)
261 __do_fclose
FILE *f
= NULL
;
264 f
= fopen(file
, "we");
268 if (fprintf(f
, "%s", content
) != strlen(content
))
274 int is_dir(const char *path
)
279 ret
= stat(path
, &statbuf
);
280 if (ret
== 0 && S_ISDIR(statbuf
.st_mode
))
287 * Return the number of lines in file @fn, or -1 on error
289 int lxc_count_file_lines(const char *fn
)
291 __do_free
char *line
= NULL
;
292 __do_fclose
FILE *f
= NULL
;
296 f
= fopen_cloexec(fn
, "r");
300 while (getline(&line
, &sz
, f
) != -1)
306 int lxc_make_tmpfile(char *template, bool rm
)
308 __do_close
int fd
= -EBADF
;
313 fd
= mkstemp(template);
318 if (lxc_set_cloexec(fd
))
324 ret
= unlink(template);
331 bool is_fs_type(const struct statfs
*fs
, fs_type_magic magic_val
)
333 return (fs
->f_type
== (fs_type_magic
)magic_val
);
336 bool has_fs_type(const char *path
, fs_type_magic magic_val
)
341 ret
= statfs(path
, &sb
);
345 return is_fs_type(&sb
, magic_val
);
348 bool fhas_fs_type(int fd
, fs_type_magic magic_val
)
353 ret
= fstatfs(fd
, &sb
);
357 return is_fs_type(&sb
, magic_val
);
360 FILE *fopen_cloexec(const char *path
, const char *mode
)
362 __do_close
int fd
= -EBADF
;
363 int open_mode
= 0, step
= 0;
366 if (strnequal(mode
, "r+", 2)) {
369 } else if (strnequal(mode
, "r", 1)) {
370 open_mode
= O_RDONLY
;
372 } else if (strnequal(mode
, "w+", 2)) {
373 open_mode
= O_RDWR
| O_TRUNC
| O_CREAT
;
375 } else if (strnequal(mode
, "w", 1)) {
376 open_mode
= O_WRONLY
| O_TRUNC
| O_CREAT
;
378 } else if (strnequal(mode
, "a+", 2)) {
379 open_mode
= O_RDWR
| O_CREAT
| O_APPEND
;
381 } else if (strnequal(mode
, "a", 1)) {
382 open_mode
= O_WRONLY
| O_CREAT
| O_APPEND
;
385 for (; mode
[step
]; step
++)
386 if (mode
[step
] == 'x')
389 fd
= open(path
, open_mode
| O_CLOEXEC
, 0660);
393 f
= fdopen(fd
, mode
);
399 ssize_t
lxc_sendfile_nointr(int out_fd
, int in_fd
, off_t
*offset
, size_t count
)
404 ret
= sendfile(out_fd
, in_fd
, offset
, count
);
405 } while (ret
< 0 && errno
== EINTR
);
410 ssize_t
__fd_to_fd(int from
, int to
)
412 ssize_t total_bytes
= 0;
415 uint8_t buf
[PATH_MAX
];
417 ssize_t bytes_to_write
;
420 bytes_read
= lxc_read_nointr(from
, buf
, sizeof buf
);
426 bytes_to_write
= (size_t)bytes_read
;
427 total_bytes
+= bytes_read
;
429 ssize_t bytes_written
;
431 bytes_written
= lxc_write_nointr(to
, p
, bytes_to_write
);
432 if (bytes_written
< 0)
435 bytes_to_write
-= bytes_written
;
437 } while (bytes_to_write
> 0);
443 int fd_to_buf(int fd
, char **buf
, size_t *length
)
445 __do_free
char *copy
= NULL
;
456 bytes_read
= lxc_read_nointr(fd
, chunk
, sizeof(chunk
));
463 copy
= realloc(old
, (*length
+ bytes_read
) * sizeof(*old
));
465 return ret_errno(ENOMEM
);
467 memcpy(copy
+ *length
, chunk
, bytes_read
);
468 *length
+= bytes_read
;
471 *buf
= move_ptr(copy
);
475 char *file_to_buf(const char *path
, size_t *length
)
477 __do_close
int fd
= -EBADF
;
483 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
487 if (fd_to_buf(fd
, &buf
, length
) < 0)
493 FILE *fopen_cached(const char *path
, const char *mode
, void **caller_freed_buffer
)
496 __do_free
char *buf
= NULL
;
500 buf
= file_to_buf(path
, &len
);
504 f
= fmemopen(buf
, len
, mode
);
507 *caller_freed_buffer
= move_ptr(buf
);
510 return fopen(path
, mode
);
514 FILE *fdopen_cached(int fd
, const char *mode
, void **caller_freed_buffer
)
518 __do_free
char *buf
= NULL
;
521 if (fd_to_buf(fd
, &buf
, &len
) < 0)
524 f
= fmemopen(buf
, len
, mode
);
528 *caller_freed_buffer
= move_ptr(buf
);
532 __do_close
int dupfd
= -EBADF
;
538 f
= fdopen(dupfd
, "re");
542 /* Transfer ownership of fd. */
548 int fd_cloexec(int fd
, bool cloexec
)
552 oflags
= fcntl(fd
, F_GETFD
, 0);
557 nflags
= oflags
| FD_CLOEXEC
;
559 nflags
= oflags
& ~FD_CLOEXEC
;
561 if (nflags
== oflags
)
564 if (fcntl(fd
, F_SETFD
, nflags
) < 0)
570 FILE *fdopen_at(int dfd
, const char *path
, const char *mode
,
571 unsigned int o_flags
, unsigned int resolve_flags
)
573 __do_close
int fd
= -EBADF
;
574 __do_fclose
FILE *f
= NULL
;
576 if (is_empty_string(path
))
577 fd
= dup_cloexec(dfd
);
579 fd
= open_at(dfd
, path
, o_flags
, resolve_flags
, 0);
583 f
= fdopen(fd
, "re");
587 /* Transfer ownership of fd. */
593 int timens_offset_write(clockid_t clk_id
, int64_t s_offset
, int64_t ns_offset
)
595 __do_close
int fd
= -EBADF
;
598 char buf
[INTTYPE_TO_STRLEN(int) +
599 STRLITERALLEN(" ") + INTTYPE_TO_STRLEN(int64_t) +
600 STRLITERALLEN(" ") + INTTYPE_TO_STRLEN(int64_t) + 1];
602 if (clk_id
== CLOCK_MONOTONIC_COARSE
|| clk_id
== CLOCK_MONOTONIC_RAW
)
603 clk_id
= CLOCK_MONOTONIC
;
605 fd
= open("/proc/self/timens_offsets", O_WRONLY
| O_CLOEXEC
);
609 len
= strnprintf(buf
, sizeof(buf
), "%d %" PRId64
" %" PRId64
, clk_id
, s_offset
, ns_offset
);
611 return ret_errno(EFBIG
);
613 ret
= lxc_write_nointr(fd
, buf
, len
);
614 if (ret
< 0 || (size_t)ret
!= len
)
620 bool exists_dir_at(int dir_fd
, const char *path
)
625 ret
= fstatat(dir_fd
, path
, &sb
, 0);
629 ret
= S_ISDIR(sb
.st_mode
);
638 bool exists_file_at(int dir_fd
, const char *path
)
643 ret
= fstatat(dir_fd
, path
, &sb
, 0);
649 int open_at(int dfd
, const char *path
, unsigned int o_flags
,
650 unsigned int resolve_flags
, mode_t mode
)
652 __do_close
int fd
= -EBADF
;
653 struct lxc_open_how how
= {
656 .resolve
= resolve_flags
,
659 fd
= openat2(dfd
, path
, &how
, sizeof(how
));
666 fd
= openat(dfd
, path
, o_flags
, mode
);
673 int open_at_same(int fd_same
, int dfd
, const char *path
, unsigned int o_flags
,
674 unsigned int resolve_flags
, mode_t mode
)
676 __do_close
int fd
= -EBADF
;
678 fd
= open_at(dfd
, path
, o_flags
, resolve_flags
, mode
);
682 if (!same_file_lax(fd_same
, fd
))
683 return ret_errno(EINVAL
);
688 int fd_make_nonblocking(int fd
)
692 flags
= fcntl(fd
, F_GETFL
);
696 flags
&= ~O_NONBLOCK
;
697 return fcntl(fd
, F_SETFL
, flags
);
700 #define BATCH_SIZE 50
701 static void batch_realloc(char **mem
, size_t oldlen
, size_t newlen
)
703 int newbatches
= (newlen
/ BATCH_SIZE
) + 1;
704 int oldbatches
= (oldlen
/ BATCH_SIZE
) + 1;
706 if (!*mem
|| newbatches
> oldbatches
)
707 *mem
= must_realloc(*mem
, newbatches
* BATCH_SIZE
);
710 static void append_line(char **dest
, size_t oldlen
, char *new, size_t newlen
)
712 size_t full
= oldlen
+ newlen
;
714 batch_realloc(dest
, oldlen
, full
+ 1);
716 memcpy(*dest
+ oldlen
, new, newlen
+ 1);
719 /* Slurp in a whole file */
720 char *read_file_at(int dfd
, const char *fnam
,
721 unsigned int o_flags
, unsigned resolve_flags
)
723 __do_close
int fd
= -EBADF
;
724 __do_free
char *buf
= NULL
, *line
= NULL
;
725 __do_fclose
FILE *f
= NULL
;
726 size_t len
= 0, fulllen
= 0;
729 fd
= open_at(dfd
, fnam
, o_flags
, resolve_flags
, 0);
733 f
= fdopen(fd
, "re");
736 /* Transfer ownership to fdopen(). */
739 while ((linelen
= getline(&line
, &len
, f
)) != -1) {
740 append_line(&buf
, fulllen
, line
, linelen
);
744 return move_ptr(buf
);
747 bool same_file_lax(int fda
, int fdb
)
749 struct stat st_fda
, st_fdb
;
755 if (fstat(fda
, &st_fda
) < 0)
758 if (fstat(fdb
, &st_fdb
) < 0)
762 if ((st_fda
.st_mode
& S_IFMT
) != (st_fdb
.st_mode
& S_IFMT
))
766 return (st_fda
.st_dev
== st_fdb
.st_dev
) &&
767 (st_fda
.st_ino
== st_fdb
.st_ino
);
770 bool same_device(int fda
, const char *patha
, int fdb
, const char *pathb
)
774 struct stat st_fda
, st_fdb
;
779 if (is_empty_string(patha
))
780 ret
= fstat(fda
, &st_fda
);
782 ret
= fstatat(fda
, patha
, &st_fda
, 0);
786 if (is_empty_string(pathb
))
787 ret
= fstat(fdb
, &st_fdb
);
789 ret
= fstatat(fdb
, pathb
, &st_fdb
, 0);
794 modea
= (st_fda
.st_mode
& S_IFMT
);
795 modeb
= (st_fdb
.st_mode
& S_IFMT
);
796 if (modea
!= modeb
|| !IN_SET(modea
, S_IFCHR
, S_IFBLK
))
799 return (st_fda
.st_rdev
== st_fdb
.st_rdev
);