]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/fileutils.c
2 * This code is in the public domain; do with it what you wish.
4 * Copyright (C) 2012 Sami Kerola <kerolasa@iki.fi>
5 * Copyright (C) 2012-2020 Karel Zak <kzak@redhat.com>
13 #include <sys/resource.h>
18 #include "fileutils.h"
19 #include "pathnames.h"
21 int mkstemp_cloexec(char *template)
24 return mkostemp(template, O_RDWR
|O_CREAT
|O_EXCL
|O_CLOEXEC
);
26 int fd
, old_flags
, errno_save
;
28 fd
= mkstemp(template);
32 old_flags
= fcntl(fd
, F_GETFD
, 0);
35 if (fcntl(fd
, F_SETFD
, old_flags
| O_CLOEXEC
) < 0)
50 /* Create open temporary file in safe way. Please notice that the
51 * file permissions are -rw------- by default. */
52 int xmkstemp(char **tmpname
, const char *dir
, const char *prefix
)
59 /* Some use cases must be capable of being moved atomically
60 * with rename(2), which is the reason why dir is here. */
61 tmpenv
= dir
? dir
: getenv("TMPDIR");
65 rc
= asprintf(&localtmp
, "%s/%s.XXXXXX", tmpenv
, prefix
);
69 old_mode
= umask(077);
70 fd
= mkstemp_cloexec(localtmp
);
80 #ifdef F_DUPFD_CLOEXEC
81 int dup_fd_cloexec(int oldfd
, int lowfd
)
83 int dup_fd_cloexec(int oldfd
, int lowfd
__attribute__((__unused__
)))
86 int fd
, flags
, errno_save
;
88 #ifdef F_DUPFD_CLOEXEC
89 fd
= fcntl(oldfd
, F_DUPFD_CLOEXEC
, lowfd
);
98 flags
= fcntl(fd
, F_GETFD
);
101 if (fcntl(fd
, F_SETFD
, flags
| FD_CLOEXEC
) < 0)
115 * portable getdtablesize()
117 unsigned int get_fd_tabsize(void)
121 #if defined(HAVE_GETDTABLESIZE)
123 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
126 getrlimit(RLIMIT_NOFILE
, &rl
);
128 #elif defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
129 m
= sysconf(_SC_OPEN_MAX
);
136 void ul_close_all_fds(unsigned int first
, unsigned int last
)
141 dir
= opendir(_PATH_PROC_FDDIR
);
143 while ((d
= xreaddir(dir
))) {
149 fd
= strtoul(d
->d_name
, &end
, 10);
151 if (errno
|| end
== d
->d_name
|| !end
|| *end
)
156 if ((unsigned int)dfd
== fd
)
158 if (fd
< first
|| last
< fd
)
164 unsigned fd
, tbsz
= get_fd_tabsize();
166 for (fd
= 0; fd
< tbsz
; fd
++) {
167 if (first
<= fd
&& fd
<= last
)
173 #ifdef TEST_PROGRAM_FILEUTILS
174 int main(int argc
, char *argv
[])
177 errx(EXIT_FAILURE
, "Usage %s --{mkstemp,close-fds,copy-file}", argv
[0]);
179 if (strcmp(argv
[1], "--mkstemp") == 0) {
181 char *tmpname
= NULL
;
183 f
= xfmkstemp(&tmpname
, NULL
, "test");
188 } else if (strcmp(argv
[1], "--close-fds") == 0) {
189 ignore_result( dup(STDIN_FILENO
) );
190 ignore_result( dup(STDIN_FILENO
) );
191 ignore_result( dup(STDIN_FILENO
) );
193 # ifdef HAVE_CLOSE_RANGE
194 if (close_range(STDERR_FILENO
+ 1, ~0U, 0) < 0)
196 ul_close_all_fds(STDERR_FILENO
+ 1, ~0U);
198 } else if (strcmp(argv
[1], "--copy-file") == 0) {
199 int ret
= ul_copy_file(STDIN_FILENO
, STDOUT_FILENO
);
200 if (ret
== UL_COPY_READ_ERROR
)
201 err(EXIT_FAILURE
, "read");
202 else if (ret
== UL_COPY_WRITE_ERROR
)
203 err(EXIT_FAILURE
, "write");
210 int ul_mkdir_p(const char *path
, mode_t mode
)
218 dir
= p
= strdup(path
);
226 char *e
= strchr(p
, '/');
230 rc
= mkdir(dir
, mode
);
231 if (rc
&& errno
!= EEXIST
)
245 /* returns basename and keeps dirname in the @path, if @path is "/" (root)
246 * then returns empty string */
247 char *stripoff_last_component(char *path
)
249 char *p
= path
? strrchr(path
, '/') : NULL
;
257 static int copy_file_simple(int from
, int to
)
262 while ((nr
= read_all(from
, buf
, sizeof(buf
))) > 0)
263 if (write_all(to
, buf
, nr
) == -1)
264 return UL_COPY_WRITE_ERROR
;
266 return UL_COPY_READ_ERROR
;
267 #ifdef HAVE_EXPLICIT_BZERO
268 explicit_bzero(buf
, sizeof(buf
));
273 /* Copies the contents of a file. Returns -1 on read error, -2 on write error. */
274 int ul_copy_file(int from
, int to
)
280 if (fstat(from
, &st
) == -1)
281 return UL_COPY_READ_ERROR
;
282 if (!S_ISREG(st
.st_mode
))
283 return copy_file_simple(from
, to
);
284 if (sendfile_all(to
, from
, NULL
, st
.st_size
) < 0)
285 return copy_file_simple(from
, to
);
286 /* ensure we either get an EOF or an error */
287 while ((nw
= sendfile_all(to
, from
, NULL
, 16*1024*1024)) != 0)
289 return copy_file_simple(from
, to
);
292 return copy_file_simple(from
, to
);
296 int ul_reopen(int fd
, int flags
)
300 char fdpath
[ sizeof(_PATH_PROC_FDDIR
) + sizeof(stringify_value(INT_MAX
)) ];
302 snprintf(fdpath
, sizeof(fdpath
), _PATH_PROC_FDDIR
"/%d", fd
);
304 ssz
= readlink(fdpath
, buf
, sizeof(buf
) - 1);
312 return open(buf
, flags
);