2f114934fd78c654a43a9b5563f6929bc7422ec6
[lttng-tools.git] / src / common / utils.c
1 /*
2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _GNU_SOURCE
19 #include <assert.h>
20 #include <ctype.h>
21 #include <fcntl.h>
22 #include <limits.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <common/common.h>
27
28 #include "utils.h"
29
30 /*
31 * Return the realpath(3) of the path even if the last directory token does not
32 * exist. For example, with /tmp/test1/test2, if test2/ does not exist but the
33 * /tmp/test1 does, the real path is returned. In normal time, realpath(3)
34 * fails if the end point directory does not exist.
35 */
36 __attribute__((visibility("hidden")))
37 char *utils_expand_path(const char *path)
38 {
39 const char *end_path = path;
40 char *next, *cut_path = NULL, *expanded_path = NULL;
41
42 /* Safety net */
43 if (path == NULL) {
44 goto error;
45 }
46
47 /* Find last token delimited by '/' */
48 while ((next = strpbrk(end_path + 1, "/"))) {
49 end_path = next;
50 }
51
52 /* Cut last token from original path */
53 cut_path = strndup(path, end_path - path);
54
55 expanded_path = zmalloc(PATH_MAX);
56 if (expanded_path == NULL) {
57 PERROR("zmalloc expand path");
58 goto error;
59 }
60
61 expanded_path = realpath((char *)cut_path, expanded_path);
62 if (expanded_path == NULL) {
63 switch (errno) {
64 case ENOENT:
65 ERR("%s: No such file or directory", cut_path);
66 break;
67 default:
68 PERROR("realpath utils expand path");
69 break;
70 }
71 goto error;
72 }
73
74 /* Add end part to expanded path */
75 strncat(expanded_path, end_path, PATH_MAX - strlen(expanded_path) - 1);
76
77 free(cut_path);
78 return expanded_path;
79
80 error:
81 free(expanded_path);
82 free(cut_path);
83 return NULL;
84 }
85
86 /*
87 * Create a pipe in dst.
88 */
89 __attribute__((visibility("hidden")))
90 int utils_create_pipe(int *dst)
91 {
92 int ret;
93
94 if (dst == NULL) {
95 return -1;
96 }
97
98 ret = pipe(dst);
99 if (ret < 0) {
100 PERROR("create pipe");
101 }
102
103 return ret;
104 }
105
106 /*
107 * Create pipe and set CLOEXEC flag to both fd.
108 *
109 * Make sure the pipe opened by this function are closed at some point. Use
110 * utils_close_pipe().
111 */
112 __attribute__((visibility("hidden")))
113 int utils_create_pipe_cloexec(int *dst)
114 {
115 int ret, i;
116
117 if (dst == NULL) {
118 return -1;
119 }
120
121 ret = utils_create_pipe(dst);
122 if (ret < 0) {
123 goto error;
124 }
125
126 for (i = 0; i < 2; i++) {
127 ret = fcntl(dst[i], F_SETFD, FD_CLOEXEC);
128 if (ret < 0) {
129 PERROR("fcntl pipe cloexec");
130 goto error;
131 }
132 }
133
134 error:
135 return ret;
136 }
137
138 /*
139 * Close both read and write side of the pipe.
140 */
141 __attribute__((visibility("hidden")))
142 void utils_close_pipe(int *src)
143 {
144 int i, ret;
145
146 if (src == NULL) {
147 return;
148 }
149
150 for (i = 0; i < 2; i++) {
151 /* Safety check */
152 if (src[i] < 0) {
153 continue;
154 }
155
156 ret = close(src[i]);
157 if (ret) {
158 PERROR("close pipe");
159 }
160 }
161 }
162
163 /*
164 * Create a new string using two strings range.
165 */
166 __attribute__((visibility("hidden")))
167 char *utils_strdupdelim(const char *begin, const char *end)
168 {
169 char *str;
170
171 str = zmalloc(end - begin + 1);
172 if (str == NULL) {
173 PERROR("zmalloc strdupdelim");
174 goto error;
175 }
176
177 memcpy(str, begin, end - begin);
178 str[end - begin] = '\0';
179
180 error:
181 return str;
182 }
183
184 /*
185 * Set CLOEXEC flag to the give file descriptor.
186 */
187 __attribute__((visibility("hidden")))
188 int utils_set_fd_cloexec(int fd)
189 {
190 int ret;
191
192 if (fd < 0) {
193 ret = -EINVAL;
194 goto end;
195 }
196
197 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
198 if (ret < 0) {
199 PERROR("fcntl cloexec");
200 ret = -errno;
201 }
202
203 end:
204 return ret;
205 }
206
207 /*
208 * Create pid file to the given path and filename.
209 */
210 __attribute__((visibility("hidden")))
211 int utils_create_pid_file(pid_t pid, const char *filepath)
212 {
213 int ret;
214 FILE *fp;
215
216 assert(filepath);
217
218 fp = fopen(filepath, "w");
219 if (fp == NULL) {
220 PERROR("open pid file %s", filepath);
221 ret = -1;
222 goto error;
223 }
224
225 ret = fprintf(fp, "%d\n", pid);
226 if (ret < 0) {
227 PERROR("fprintf pid file");
228 }
229
230 fclose(fp);
231 DBG("Pid %d written in file %s", pid, filepath);
232 error:
233 return ret;
234 }
This page took 0.054208 seconds and 3 git commands to generate.