]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/fileutils.c
whereis: use xstrncpy()
[thirdparty/util-linux.git] / lib / fileutils.c
CommitLineData
6b79eb38
SK
1/*
2 * Copyright (C) 2012 Sami Kerola <kerolasa@iki.fi>
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <sys/stat.h>
8#include <unistd.h>
be92327e
KZ
9#include <sys/time.h>
10#include <sys/resource.h>
6b79eb38
SK
11
12#include "c.h"
7961acce 13#include "fileutils.h"
6b79eb38
SK
14#include "pathnames.h"
15
4d751c00
RM
16int mkstemp_cloexec(char *template)
17{
18#ifdef HAVE_MKOSTEMP
19 return mkostemp(template, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
20#else
21 int fd, old_flags, errno_save;
22
23 fd = mkstemp(template);
24 if (fd < 0)
25 return fd;
26
27 old_flags = fcntl(fd, F_GETFD, 0);
28 if (old_flags < 0)
29 goto unwind;
30 if (fcntl(fd, F_SETFD, old_flags | O_CLOEXEC) < 0)
31 goto unwind;
32
33 return fd;
34
35unwind:
36 errno_save = errno;
37 unlink(template);
38 close(fd);
39 errno = errno_save;
40
41 return -1;
42#endif
43}
44
6b79eb38
SK
45/* Create open temporary file in safe way. Please notice that the
46 * file permissions are -rw------- by default. */
bde91c85 47int xmkstemp(char **tmpname, const char *dir, const char *prefix)
6b79eb38
SK
48{
49 char *localtmp;
bde91c85 50 const char *tmpenv;
6b79eb38 51 mode_t old_mode;
f272b32c 52 int fd, rc;
6b79eb38 53
3c4fed09
DR
54 /* Some use cases must be capable of being moved atomically
55 * with rename(2), which is the reason why dir is here. */
bde91c85
KZ
56 tmpenv = dir ? dir : getenv("TMPDIR");
57 if (!tmpenv)
58 tmpenv = _PATH_TMP;
f272b32c 59
bde91c85 60 rc = asprintf(&localtmp, "%s/%s.XXXXXX", tmpenv, prefix);
f272b32c
KZ
61 if (rc < 0)
62 return -1;
63
6b79eb38 64 old_mode = umask(077);
4d751c00 65 fd = mkstemp_cloexec(localtmp);
6b79eb38 66 umask(old_mode);
7961acce
SK
67 if (fd == -1) {
68 free(localtmp);
69 localtmp = NULL;
70 }
6b79eb38 71 *tmpname = localtmp;
7961acce 72 return fd;
6b79eb38
SK
73}
74
8e86d93d
GJ
75int dup_fd_cloexec(int oldfd, int lowfd)
76{
77 int fd, flags, errno_save;
78
79#ifdef F_DUPFD_CLOEXEC
80 fd = fcntl(oldfd, F_DUPFD_CLOEXEC, lowfd);
81 if (fd >= 0)
82 return fd;
83#endif
84
85 fd = dup(oldfd);
86 if (fd < 0)
87 return fd;
88
89 flags = fcntl(fd, F_GETFD);
90 if (flags < 0)
91 goto unwind;
92 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
93 goto unwind;
94
95 return fd;
96
97unwind:
98 errno_save = errno;
99 close(fd);
100 errno = errno_save;
101
102 return -1;
103}
104
be92327e
KZ
105/*
106 * portable getdtablesize()
107 */
108int get_fd_tabsize(void)
109{
110 int m;
111
112#if defined(HAVE_GETDTABLESIZE)
113 m = getdtablesize();
114#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
115 struct rlimit rl;
116
117 getrlimit(RLIMIT_NOFILE, &rl);
118 m = rl.rlim_cur;
119#elif defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
120 m = sysconf(_SC_OPEN_MAX);
121#else
122 m = OPEN_MAX;
123#endif
124 return m;
125}
126
e8f7acb0 127#ifdef TEST_PROGRAM_FILEUTILS
6b79eb38
SK
128int main(void)
129{
130 FILE *f;
131 char *tmpname;
bde91c85 132 f = xfmkstemp(&tmpname, NULL, "test");
6b79eb38
SK
133 unlink(tmpname);
134 free(tmpname);
135 fclose(f);
136 return EXIT_FAILURE;
137}
138#endif
934530c7
KZ
139
140
141int mkdir_p(const char *path, mode_t mode)
142{
143 char *p, *dir;
144 int rc = 0;
145
146 if (!path || !*path)
147 return -EINVAL;
148
149 dir = p = strdup(path);
150 if (!dir)
151 return -ENOMEM;
152
153 if (*p == '/')
154 p++;
155
156 while (p && *p) {
157 char *e = strchr(p, '/');
158 if (e)
159 *e = '\0';
160 if (*p) {
161 rc = mkdir(dir, mode);
162 if (rc && errno != EEXIST)
163 break;
164 rc = 0;
165 }
166 if (!e)
167 break;
168 *e = '/';
169 p = e + 1;
170 }
171
172 free(dir);
173 return rc;
174}
d4eaabc8
KZ
175
176/* returns basename and keeps dirname in the @path, if @path is "/" (root)
177 * then returns empty string */
178char *stripoff_last_component(char *path)
179{
180 char *p = path ? strrchr(path, '/') : NULL;
181
182 if (!p)
183 return NULL;
184 *p = '\0';
185 return p + 1;
186}