1 // SPDX-License-Identifier: GPL-2.0
2 #include "util/copyfile.h"
3 #include "util/namespaces.h"
4 #include <internal/lib.h>
14 static int slow_copyfile(const char *from
, const char *to
, struct nsinfo
*nsi
)
19 FILE *from_fp
, *to_fp
;
22 nsinfo__mountns_enter(nsi
, &nsc
);
23 from_fp
= fopen(from
, "r");
24 nsinfo__mountns_exit(&nsc
);
28 to_fp
= fopen(to
, "w");
32 while (getline(&line
, &n
, from_fp
) > 0)
33 if (fputs(line
, to_fp
) == EOF
)
45 int copyfile_offset(int ifd
, loff_t off_in
, int ofd
, loff_t off_out
, u64 size
)
50 pgoff
= off_in
& ~(page_size
- 1);
53 ptr
= mmap(NULL
, off_in
+ size
, PROT_READ
, MAP_PRIVATE
, ifd
, pgoff
);
54 if (ptr
== MAP_FAILED
)
58 ssize_t ret
= pwrite(ofd
, ptr
+ off_in
, size
, off_out
);
59 if (ret
< 0 && errno
== EINTR
)
68 munmap(ptr
, off_in
+ size
);
73 static int copyfile_mode_ns(const char *from
, const char *to
, mode_t mode
,
79 char *tmp
= NULL
, *ptr
= NULL
;
82 nsinfo__mountns_enter(nsi
, &nsc
);
83 err
= stat(from
, &st
);
84 nsinfo__mountns_exit(&nsc
);
89 /* extra 'x' at the end is to reserve space for '.' */
90 if (asprintf(&tmp
, "%s.XXXXXXx", to
) < 0) {
94 ptr
= strrchr(tmp
, '/');
97 ptr
= memmove(ptr
+ 1, ptr
, strlen(ptr
) - 1);
104 if (st
.st_size
== 0) { /* /proc? do it slowly... */
105 err
= slow_copyfile(from
, tmp
, nsi
);
106 if (!err
&& fchmod(tofd
, mode
))
111 if (fchmod(tofd
, mode
))
114 nsinfo__mountns_enter(nsi
, &nsc
);
115 fromfd
= open(from
, O_RDONLY
);
116 nsinfo__mountns_exit(&nsc
);
120 err
= copyfile_offset(fromfd
, 0, tofd
, 0, st
.st_size
);
133 int copyfile_ns(const char *from
, const char *to
, struct nsinfo
*nsi
)
135 return copyfile_mode_ns(from
, to
, 0755, nsi
);
138 int copyfile_mode(const char *from
, const char *to
, mode_t mode
)
140 return copyfile_mode_ns(from
, to
, mode
, NULL
);
143 int copyfile(const char *from
, const char *to
)
145 return copyfile_mode(from
, to
, 0755);