]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/file_utils.c
3 * Copyright © 2019 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2019 Canonical Ltd.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <linux/magic.h>
29 #include <sys/sendfile.h>
30 #include <sys/types.h>
33 #include "file_utils.h"
35 #include "memory_utils.h"
36 #include "string_utils.h"
39 int lxc_write_to_file(const char *filename
, const void *buf
, size_t count
,
40 bool add_newline
, mode_t mode
)
45 fd
= open(filename
, O_WRONLY
| O_TRUNC
| O_CREAT
| O_CLOEXEC
, mode
);
49 ret
= lxc_write_nointr(fd
, buf
, count
);
53 if ((size_t)ret
!= count
)
57 ret
= lxc_write_nointr(fd
, "\n", 1);
72 int lxc_read_from_file(const char *filename
, void *buf
, size_t count
)
74 int fd
= -1, saved_errno
;
77 fd
= open(filename
, O_RDONLY
| O_CLOEXEC
);
85 while ((ret
= lxc_read_nointr(fd
, buf2
, 100)) > 0)
91 memset(buf
, 0, count
);
92 ret
= lxc_read_nointr(fd
, buf
, count
);
101 ssize_t
lxc_write_nointr(int fd
, const void *buf
, size_t count
)
105 ret
= write(fd
, buf
, count
);
106 if (ret
< 0 && errno
== EINTR
)
112 ssize_t
lxc_send_nointr(int sockfd
, void *buf
, size_t len
, int flags
)
116 ret
= send(sockfd
, buf
, len
, flags
);
117 if (ret
< 0 && errno
== EINTR
)
123 ssize_t
lxc_read_nointr(int fd
, void *buf
, size_t count
)
127 ret
= read(fd
, buf
, count
);
128 if (ret
< 0 && errno
== EINTR
)
134 ssize_t
lxc_recv_nointr(int sockfd
, void *buf
, size_t len
, int flags
)
138 ret
= recv(sockfd
, buf
, len
, flags
);
139 if (ret
< 0 && errno
== EINTR
)
145 ssize_t
lxc_recvmsg_nointr_iov(int sockfd
, struct iovec
*iov
, size_t iovlen
,
151 memset(&msg
, 0, sizeof(msg
));
153 msg
.msg_iovlen
= iovlen
;
156 ret
= recvmsg(sockfd
, &msg
, flags
);
157 if (ret
< 0 && errno
== EINTR
)
163 ssize_t
lxc_read_nointr_expect(int fd
, void *buf
, size_t count
, const void *expected_buf
)
167 ret
= lxc_read_nointr(fd
, buf
, count
);
171 if ((size_t)ret
!= count
)
174 if (expected_buf
&& memcmp(buf
, expected_buf
, count
) != 0) {
182 ssize_t
lxc_read_file_expect(const char *path
, void *buf
, size_t count
, const void *expected_buf
)
184 __do_close_prot_errno
int fd
= -EBADF
;
186 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
190 return lxc_read_nointr_expect(fd
, buf
, count
, expected_buf
);
193 bool file_exists(const char *f
)
197 return stat(f
, &statbuf
) == 0;
200 int print_to_file(const char *file
, const char *content
)
205 f
= fopen(file
, "w");
209 if (fprintf(f
, "%s", content
) != strlen(content
))
216 int is_dir(const char *path
)
221 ret
= stat(path
, &statbuf
);
222 if (ret
== 0 && S_ISDIR(statbuf
.st_mode
))
229 * Return the number of lines in file @fn, or -1 on error
231 int lxc_count_file_lines(const char *fn
)
238 f
= fopen_cloexec(fn
, "r");
242 while (getline(&line
, &sz
, f
) != -1) {
251 int lxc_make_tmpfile(char *template, bool rm
)
253 __do_close_prot_errno
int fd
= -EBADF
;
258 fd
= mkstemp(template);
263 if (lxc_set_cloexec(fd
))
269 ret
= unlink(template);
276 bool is_fs_type(const struct statfs
*fs
, fs_type_magic magic_val
)
278 return (fs
->f_type
== (fs_type_magic
)magic_val
);
281 bool has_fs_type(const char *path
, fs_type_magic magic_val
)
286 ret
= statfs(path
, &sb
);
290 return is_fs_type(&sb
, magic_val
);
293 bool fhas_fs_type(int fd
, fs_type_magic magic_val
)
298 ret
= fstatfs(fd
, &sb
);
302 return is_fs_type(&sb
, magic_val
);
305 FILE *fopen_cloexec(const char *path
, const char *mode
)
313 if (!strncmp(mode
, "r+", 2)) {
316 } else if (!strncmp(mode
, "r", 1)) {
317 open_mode
= O_RDONLY
;
319 } else if (!strncmp(mode
, "w+", 2)) {
320 open_mode
= O_RDWR
| O_TRUNC
| O_CREAT
;
322 } else if (!strncmp(mode
, "w", 1)) {
323 open_mode
= O_WRONLY
| O_TRUNC
| O_CREAT
;
325 } else if (!strncmp(mode
, "a+", 2)) {
326 open_mode
= O_RDWR
| O_CREAT
| O_APPEND
;
328 } else if (!strncmp(mode
, "a", 1)) {
329 open_mode
= O_WRONLY
| O_CREAT
| O_APPEND
;
332 for (; mode
[step
]; step
++)
333 if (mode
[step
] == 'x')
335 open_mode
|= O_CLOEXEC
;
337 fd
= open(path
, open_mode
, 0660);
341 ret
= fdopen(fd
, mode
);
349 ssize_t
lxc_sendfile_nointr(int out_fd
, int in_fd
, off_t
*offset
, size_t count
)
354 ret
= sendfile(out_fd
, in_fd
, offset
, count
);
365 char *file_to_buf(char *path
, size_t *length
)
374 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
383 n
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
389 copy
= must_realloc(old
, (*length
+ n
) * sizeof(*old
));
390 memcpy(copy
+ *length
, buf
, n
);
404 int fd_to_fd(int from
, int to
)
407 uint8_t buf
[PATH_MAX
];
409 ssize_t bytes_to_write
;
412 bytes_read
= lxc_read_nointr(from
, buf
, sizeof buf
);
418 bytes_to_write
= (size_t)bytes_read
;
420 ssize_t bytes_written
;
422 bytes_written
= lxc_write_nointr(to
, p
, bytes_to_write
);
423 if (bytes_written
< 0)
426 bytes_to_write
-= bytes_written
;
428 } while (bytes_to_write
> 0);