]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/file_utils.c
Merge pull request #3956 from brauner/2021-08-27.list
[mirror_lxc.git] / src / lxc / file_utils.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <linux/magic.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/sendfile.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <time.h>
15
16 #include "config.h"
17 #include "file_utils.h"
18 #include "macro.h"
19 #include "memory_utils.h"
20 #include "string_utils.h"
21 #include "syscall_wrappers.h"
22 #include "utils.h"
23
24 int lxc_open_dirfd(const char *dir)
25 {
26 return open_at(-EBADF, dir, PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_XDEV, 0);
27 }
28
29 int lxc_readat(int dirfd, const char *filename, void *buf, size_t count)
30 {
31 __do_close int fd = -EBADF;
32 ssize_t ret;
33
34 fd = open_at(dirfd, filename, PROTECT_OPEN, PROTECT_LOOKUP_BENEATH, 0);
35 if (fd < 0)
36 return -errno;
37
38 ret = lxc_read_nointr(fd, buf, count);
39 if (ret < 0)
40 return -errno;
41
42 return ret;
43 }
44
45 int lxc_writeat(int dirfd, const char *filename, const void *buf, size_t count)
46 {
47 __do_close int fd = -EBADF;
48 ssize_t ret;
49
50 fd = open_at(dirfd, filename, PROTECT_OPEN_W_WITH_TRAILING_SYMLINKS, PROTECT_LOOKUP_BENEATH, 0);
51 if (fd < 0)
52 return -1;
53
54 ret = lxc_write_nointr(fd, buf, count);
55 if (ret < 0 || (size_t)ret != count)
56 return -1;
57
58 return 0;
59 }
60
61 int lxc_write_openat(const char *dir, const char *filename, const void *buf,
62 size_t count)
63 {
64 __do_close int dirfd = -EBADF;
65
66 dirfd = open(dir, PROTECT_OPEN);
67 if (dirfd < 0)
68 return -errno;
69
70 return lxc_writeat(dirfd, filename, buf, count);
71 }
72
73 int lxc_write_to_file(const char *filename, const void *buf, size_t count,
74 bool add_newline, mode_t mode)
75 {
76 __do_close int fd = -EBADF;
77 ssize_t ret;
78
79 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
80 if (fd < 0)
81 return -1;
82
83 ret = lxc_write_nointr(fd, buf, count);
84 if (ret < 0)
85 return -1;
86
87 if ((size_t)ret != count)
88 return -1;
89
90 if (add_newline) {
91 ret = lxc_write_nointr(fd, "\n", 1);
92 if (ret != 1)
93 return -1;
94 }
95
96 return 0;
97 }
98
99 int lxc_read_from_file(const char *filename, void *buf, size_t count)
100 {
101 __do_close int fd = -EBADF;
102 ssize_t ret;
103
104 fd = open(filename, O_RDONLY | O_CLOEXEC);
105 if (fd < 0)
106 return -1;
107
108 if (!buf || !count) {
109 char buf2[100];
110 size_t count2 = 0;
111
112 while ((ret = lxc_read_nointr(fd, buf2, 100)) > 0)
113 count2 += ret;
114
115 if (ret >= 0)
116 ret = count2;
117 } else {
118 memset(buf, 0, count);
119 ret = lxc_read_nointr(fd, buf, count);
120 }
121
122 return ret;
123 }
124
125 ssize_t lxc_read_try_buf_at(int dfd, const char *path, void *buf, size_t count)
126 {
127 __do_close int fd = -EBADF;
128 ssize_t ret;
129
130 fd = open_at(dfd, path, PROTECT_OPEN, PROTECT_LOOKUP_BENEATH, 0);
131 if (fd < 0)
132 return -errno;
133
134 if (!buf || !count) {
135 char buf2[100];
136 size_t count2 = 0;
137
138 while ((ret = lxc_read_nointr(fd, buf2, 100)) > 0)
139 count2 += ret;
140
141 if (ret >= 0)
142 ret = count2;
143 } else {
144 memset(buf, 0, count);
145 ret = lxc_read_nointr(fd, buf, count);
146 }
147
148 return ret;
149 }
150
151 ssize_t lxc_write_nointr(int fd, const void *buf, size_t count)
152 {
153 ssize_t ret;
154
155 do {
156 ret = write(fd, buf, count);
157 } while (ret < 0 && errno == EINTR);
158
159 return ret;
160 }
161
162 ssize_t lxc_pwrite_nointr(int fd, const void *buf, size_t count, off_t offset)
163 {
164 ssize_t ret;
165
166 do {
167 ret = pwrite(fd, buf, count, offset);
168 } while (ret < 0 && errno == EINTR);
169
170 return ret;
171 }
172
173 ssize_t lxc_send_nointr(int sockfd, void *buf, size_t len, int flags)
174 {
175 ssize_t ret;
176
177 do {
178 ret = send(sockfd, buf, len, flags);
179 } while (ret < 0 && errno == EINTR);
180
181 return ret;
182 }
183
184 ssize_t lxc_read_nointr(int fd, void *buf, size_t count)
185 {
186 ssize_t ret;
187
188 do {
189 ret = read(fd, buf, count);
190 } while (ret < 0 && errno == EINTR);
191
192 return ret;
193 }
194
195 ssize_t lxc_recv_nointr(int sockfd, void *buf, size_t len, int flags)
196 {
197 ssize_t ret;
198
199 do {
200 ret = recv(sockfd, buf, len, flags);
201 } while (ret < 0 && errno == EINTR);
202
203 return ret;
204 }
205
206 ssize_t lxc_recvmsg_nointr_iov(int sockfd, struct iovec *iov, size_t iovlen,
207 int flags)
208 {
209 ssize_t ret;
210 struct msghdr msg = {
211 .msg_iov = iov,
212 .msg_iovlen = iovlen,
213 };
214
215 do {
216 ret = recvmsg(sockfd, &msg, flags);
217 } while (ret < 0 && errno == EINTR);
218
219 return ret;
220 }
221
222 ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count,
223 const void *expected_buf)
224 {
225 ssize_t ret;
226
227 ret = lxc_read_nointr(fd, buf, count);
228 if (ret < 0)
229 return ret;
230
231 if ((size_t)ret != count)
232 return -1;
233
234 if (expected_buf && memcmp(buf, expected_buf, count) != 0)
235 return ret_set_errno(-1, EINVAL);
236
237 return 0;
238 }
239
240 ssize_t lxc_read_file_expect(const char *path, void *buf, size_t count,
241 const void *expected_buf)
242 {
243 __do_close int fd = -EBADF;
244
245 fd = open(path, O_RDONLY | O_CLOEXEC);
246 if (fd < 0)
247 return -1;
248
249 return lxc_read_nointr_expect(fd, buf, count, expected_buf);
250 }
251
252 bool file_exists(const char *f)
253 {
254 struct stat statbuf;
255
256 return stat(f, &statbuf) == 0;
257 }
258
259 int print_to_file(const char *file, const char *content)
260 {
261 __do_fclose FILE *f = NULL;
262 int ret = 0;
263
264 f = fopen(file, "we");
265 if (!f)
266 return -1;
267
268 if (fprintf(f, "%s", content) != strlen(content))
269 ret = -1;
270
271 return ret;
272 }
273
274 int is_dir(const char *path)
275 {
276 int ret;
277 struct stat statbuf;
278
279 ret = stat(path, &statbuf);
280 if (ret == 0 && S_ISDIR(statbuf.st_mode))
281 return 1;
282
283 return 0;
284 }
285
286 /*
287 * Return the number of lines in file @fn, or -1 on error
288 */
289 int lxc_count_file_lines(const char *fn)
290 {
291 __do_free char *line = NULL;
292 __do_fclose FILE *f = NULL;
293 size_t sz = 0;
294 int n = 0;
295
296 f = fopen_cloexec(fn, "r");
297 if (!f)
298 return -1;
299
300 while (getline(&line, &sz, f) != -1)
301 n++;
302
303 return n;
304 }
305
306 int lxc_make_tmpfile(char *template, bool rm)
307 {
308 __do_close int fd = -EBADF;
309 int ret;
310 mode_t msk;
311
312 msk = umask(0022);
313 fd = mkstemp(template);
314 umask(msk);
315 if (fd < 0)
316 return -1;
317
318 if (lxc_set_cloexec(fd))
319 return -1;
320
321 if (!rm)
322 return move_fd(fd);
323
324 ret = unlink(template);
325 if (ret < 0)
326 return -1;
327
328 return move_fd(fd);
329 }
330
331 bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val)
332 {
333 return (fs->f_type == (fs_type_magic)magic_val);
334 }
335
336 bool has_fs_type(const char *path, fs_type_magic magic_val)
337 {
338 int ret;
339 struct statfs sb;
340
341 ret = statfs(path, &sb);
342 if (ret < 0)
343 return false;
344
345 return is_fs_type(&sb, magic_val);
346 }
347
348 bool fhas_fs_type(int fd, fs_type_magic magic_val)
349 {
350 int ret;
351 struct statfs sb;
352
353 ret = fstatfs(fd, &sb);
354 if (ret < 0)
355 return false;
356
357 return is_fs_type(&sb, magic_val);
358 }
359
360 FILE *fopen_cloexec(const char *path, const char *mode)
361 {
362 __do_close int fd = -EBADF;
363 int open_mode = 0, step = 0;
364 FILE *f;
365
366 if (strnequal(mode, "r+", 2)) {
367 open_mode = O_RDWR;
368 step = 2;
369 } else if (strnequal(mode, "r", 1)) {
370 open_mode = O_RDONLY;
371 step = 1;
372 } else if (strnequal(mode, "w+", 2)) {
373 open_mode = O_RDWR | O_TRUNC | O_CREAT;
374 step = 2;
375 } else if (strnequal(mode, "w", 1)) {
376 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
377 step = 1;
378 } else if (strnequal(mode, "a+", 2)) {
379 open_mode = O_RDWR | O_CREAT | O_APPEND;
380 step = 2;
381 } else if (strnequal(mode, "a", 1)) {
382 open_mode = O_WRONLY | O_CREAT | O_APPEND;
383 step = 1;
384 }
385 for (; mode[step]; step++)
386 if (mode[step] == 'x')
387 open_mode |= O_EXCL;
388
389 fd = open(path, open_mode | O_CLOEXEC, 0660);
390 if (fd < 0)
391 return NULL;
392
393 f = fdopen(fd, mode);
394 if (f)
395 move_fd(fd);
396 return f;
397 }
398
399 ssize_t lxc_sendfile_nointr(int out_fd, int in_fd, off_t *offset, size_t count)
400 {
401 ssize_t ret;
402
403 do {
404 ret = sendfile(out_fd, in_fd, offset, count);
405 } while (ret < 0 && errno == EINTR);
406
407 return ret;
408 }
409
410 ssize_t __fd_to_fd(int from, int to)
411 {
412 ssize_t total_bytes = 0;
413
414 for (;;) {
415 uint8_t buf[PATH_MAX];
416 uint8_t *p = buf;
417 ssize_t bytes_to_write;
418 ssize_t bytes_read;
419
420 bytes_read = lxc_read_nointr(from, buf, sizeof buf);
421 if (bytes_read < 0)
422 return -1;
423 if (bytes_read == 0)
424 break;
425
426 bytes_to_write = (size_t)bytes_read;
427 total_bytes += bytes_read;
428 do {
429 ssize_t bytes_written;
430
431 bytes_written = lxc_write_nointr(to, p, bytes_to_write);
432 if (bytes_written < 0)
433 return -1;
434
435 bytes_to_write -= bytes_written;
436 p += bytes_written;
437 } while (bytes_to_write > 0);
438 }
439
440 return total_bytes;
441 }
442
443 int fd_to_buf(int fd, char **buf, size_t *length)
444 {
445 __do_free char *copy = NULL;
446
447 if (!length)
448 return 0;
449
450 *length = 0;
451 for (;;) {
452 ssize_t bytes_read;
453 char chunk[4096];
454 char *old = copy;
455
456 bytes_read = lxc_read_nointr(fd, chunk, sizeof(chunk));
457 if (bytes_read < 0)
458 return -errno;
459
460 if (!bytes_read)
461 break;
462
463 copy = realloc(old, (*length + bytes_read) * sizeof(*old));
464 if (!copy)
465 return ret_errno(ENOMEM);
466
467 memcpy(copy + *length, chunk, bytes_read);
468 *length += bytes_read;
469 }
470
471 *buf = move_ptr(copy);
472 return 0;
473 }
474
475 char *file_to_buf(const char *path, size_t *length)
476 {
477 __do_close int fd = -EBADF;
478 char *buf = NULL;
479
480 if (!length)
481 return NULL;
482
483 fd = open(path, O_RDONLY | O_CLOEXEC);
484 if (fd < 0)
485 return NULL;
486
487 if (fd_to_buf(fd, &buf, length) < 0)
488 return NULL;
489
490 return buf;
491 }
492
493 FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer)
494 {
495 #ifdef HAVE_FMEMOPEN
496 __do_free char *buf = NULL;
497 size_t len = 0;
498 FILE *f;
499
500 buf = file_to_buf(path, &len);
501 if (!buf)
502 return NULL;
503
504 f = fmemopen(buf, len, mode);
505 if (!f)
506 return NULL;
507 *caller_freed_buffer = move_ptr(buf);
508 return f;
509 #else
510 return fopen(path, mode);
511 #endif
512 }
513
514 FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer)
515 {
516 FILE *f;
517 #ifdef HAVE_FMEMOPEN
518 __do_free char *buf = NULL;
519 size_t len = 0;
520
521 if (fd_to_buf(fd, &buf, &len) < 0)
522 return NULL;
523
524 f = fmemopen(buf, len, mode);
525 if (!f)
526 return NULL;
527
528 *caller_freed_buffer = move_ptr(buf);
529
530 #else
531
532 __do_close int dupfd = -EBADF;
533
534 dupfd = dup(fd);
535 if (dupfd < 0)
536 return NULL;
537
538 f = fdopen(dupfd, "re");
539 if (!f)
540 return NULL;
541
542 /* Transfer ownership of fd. */
543 move_fd(dupfd);
544 #endif
545 return f;
546 }
547
548 int fd_cloexec(int fd, bool cloexec)
549 {
550 int oflags, nflags;
551
552 oflags = fcntl(fd, F_GETFD, 0);
553 if (oflags < 0)
554 return -errno;
555
556 if (cloexec)
557 nflags = oflags | FD_CLOEXEC;
558 else
559 nflags = oflags & ~FD_CLOEXEC;
560
561 if (nflags == oflags)
562 return 0;
563
564 if (fcntl(fd, F_SETFD, nflags) < 0)
565 return -errno;
566
567 return 0;
568 }
569
570 FILE *fdopen_at(int dfd, const char *path, const char *mode,
571 unsigned int o_flags, unsigned int resolve_flags)
572 {
573 __do_close int fd = -EBADF;
574 __do_fclose FILE *f = NULL;
575
576 if (is_empty_string(path))
577 fd = dup_cloexec(dfd);
578 else
579 fd = open_at(dfd, path, o_flags, resolve_flags, 0);
580 if (fd < 0)
581 return NULL;
582
583 f = fdopen(fd, "re");
584 if (!f)
585 return NULL;
586
587 /* Transfer ownership of fd. */
588 move_fd(fd);
589
590 return move_ptr(f);
591 }
592
593 int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset)
594 {
595 __do_close int fd = -EBADF;
596 int ret;
597 ssize_t len;
598 char buf[INTTYPE_TO_STRLEN(int) +
599 STRLITERALLEN(" ") + INTTYPE_TO_STRLEN(int64_t) +
600 STRLITERALLEN(" ") + INTTYPE_TO_STRLEN(int64_t) + 1];
601
602 if (clk_id == CLOCK_MONOTONIC_COARSE || clk_id == CLOCK_MONOTONIC_RAW)
603 clk_id = CLOCK_MONOTONIC;
604
605 fd = open("/proc/self/timens_offsets", O_WRONLY | O_CLOEXEC);
606 if (fd < 0)
607 return -errno;
608
609 len = strnprintf(buf, sizeof(buf), "%d %" PRId64 " %" PRId64, clk_id, s_offset, ns_offset);
610 if (len < 0)
611 return ret_errno(EFBIG);
612
613 ret = lxc_write_nointr(fd, buf, len);
614 if (ret < 0 || (size_t)ret != len)
615 return -EIO;
616
617 return 0;
618 }
619
620 bool exists_dir_at(int dir_fd, const char *path)
621 {
622 int ret;
623 struct stat sb;
624
625 ret = fstatat(dir_fd, path, &sb, 0);
626 if (ret < 0)
627 return false;
628
629 ret = S_ISDIR(sb.st_mode);
630 if (ret)
631 errno = EEXIST;
632 else
633 errno = ENOTDIR;
634
635 return ret;
636 }
637
638 bool exists_file_at(int dir_fd, const char *path)
639 {
640 int ret;
641 struct stat sb;
642
643 ret = fstatat(dir_fd, path, &sb, 0);
644 if (ret == 0)
645 errno = EEXIST;
646 return ret == 0;
647 }
648
649 int open_at(int dfd, const char *path, unsigned int o_flags,
650 unsigned int resolve_flags, mode_t mode)
651 {
652 __do_close int fd = -EBADF;
653 struct lxc_open_how how = {
654 .flags = o_flags,
655 .mode = mode,
656 .resolve = resolve_flags,
657 };
658
659 fd = openat2(dfd, path, &how, sizeof(how));
660 if (fd >= 0)
661 return move_fd(fd);
662
663 if (errno != ENOSYS)
664 return -errno;
665
666 fd = openat(dfd, path, o_flags, mode);
667 if (fd < 0)
668 return -errno;
669
670 return move_fd(fd);
671 }
672
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)
675 {
676 __do_close int fd = -EBADF;
677
678 fd = open_at(dfd, path, o_flags, resolve_flags, mode);
679 if (fd < 0)
680 return -errno;
681
682 if (!same_file_lax(fd_same, fd))
683 return ret_errno(EINVAL);
684
685 return move_fd(fd);
686 }
687
688 int fd_make_nonblocking(int fd)
689 {
690 int flags;
691
692 flags = fcntl(fd, F_GETFL);
693 if (flags < 0)
694 return -1;
695
696 flags &= ~O_NONBLOCK;
697 return fcntl(fd, F_SETFL, flags);
698 }
699
700 #define BATCH_SIZE 50
701 static void batch_realloc(char **mem, size_t oldlen, size_t newlen)
702 {
703 int newbatches = (newlen / BATCH_SIZE) + 1;
704 int oldbatches = (oldlen / BATCH_SIZE) + 1;
705
706 if (!*mem || newbatches > oldbatches)
707 *mem = must_realloc(*mem, newbatches * BATCH_SIZE);
708 }
709
710 static void append_line(char **dest, size_t oldlen, char *new, size_t newlen)
711 {
712 size_t full = oldlen + newlen;
713
714 batch_realloc(dest, oldlen, full + 1);
715
716 memcpy(*dest + oldlen, new, newlen + 1);
717 }
718
719 /* Slurp in a whole file */
720 char *read_file_at(int dfd, const char *fnam,
721 unsigned int o_flags, unsigned resolve_flags)
722 {
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;
727 int linelen;
728
729 fd = open_at(dfd, fnam, o_flags, resolve_flags, 0);
730 if (fd < 0)
731 return NULL;
732
733 f = fdopen(fd, "re");
734 if (!f)
735 return NULL;
736 /* Transfer ownership to fdopen(). */
737 move_fd(fd);
738
739 while ((linelen = getline(&line, &len, f)) != -1) {
740 append_line(&buf, fulllen, line, linelen);
741 fulllen += linelen;
742 }
743
744 return move_ptr(buf);
745 }
746
747 bool same_file_lax(int fda, int fdb)
748 {
749 struct stat st_fda, st_fdb;
750
751
752 if (fda == fdb)
753 return true;
754
755 if (fstat(fda, &st_fda) < 0)
756 return false;
757
758 if (fstat(fdb, &st_fdb) < 0)
759 return false;
760
761 errno = EINVAL;
762 if ((st_fda.st_mode & S_IFMT) != (st_fdb.st_mode & S_IFMT))
763 return false;
764
765 errno = EINVAL;
766 return (st_fda.st_dev == st_fdb.st_dev) &&
767 (st_fda.st_ino == st_fdb.st_ino);
768 }
769
770 bool same_device(int fda, const char *patha, int fdb, const char *pathb)
771 {
772 int ret;
773 mode_t modea, modeb;
774 struct stat st_fda, st_fdb;
775
776 if (fda == fdb)
777 return true;
778
779 if (is_empty_string(patha))
780 ret = fstat(fda, &st_fda);
781 else
782 ret = fstatat(fda, patha, &st_fda, 0);
783 if (ret)
784 return false;
785
786 if (is_empty_string(pathb))
787 ret = fstat(fdb, &st_fdb);
788 else
789 ret = fstatat(fdb, pathb, &st_fdb, 0);
790 if (ret)
791 return false;
792
793 errno = EINVAL;
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))
797 return false;
798
799 return (st_fda.st_rdev == st_fdb.st_rdev);
800 }