2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
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.
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
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.
25 #include <sys/types.h>
30 #include <common/common.h>
31 #include <common/runas.h>
36 * Return the realpath(3) of the path even if the last directory token does not
37 * exist. For example, with /tmp/test1/test2, if test2/ does not exist but the
38 * /tmp/test1 does, the real path is returned. In normal time, realpath(3)
39 * fails if the end point directory does not exist.
42 char *utils_expand_path(const char *path
)
44 const char *end_path
= path
;
45 char *next
, *cut_path
= NULL
, *expanded_path
= NULL
;
52 /* Find last token delimited by '/' */
53 while ((next
= strpbrk(end_path
+ 1, "/"))) {
57 /* Cut last token from original path */
58 cut_path
= strndup(path
, end_path
- path
);
60 expanded_path
= zmalloc(PATH_MAX
);
61 if (expanded_path
== NULL
) {
62 PERROR("zmalloc expand path");
66 expanded_path
= realpath((char *)cut_path
, expanded_path
);
67 if (expanded_path
== NULL
) {
70 ERR("%s: No such file or directory", cut_path
);
73 PERROR("realpath utils expand path");
79 /* Add end part to expanded path */
80 strncat(expanded_path
, end_path
, PATH_MAX
- strlen(expanded_path
) - 1);
92 * Create a pipe in dst.
95 int utils_create_pipe(int *dst
)
105 PERROR("create pipe");
112 * Create pipe and set CLOEXEC flag to both fd.
114 * Make sure the pipe opened by this function are closed at some point. Use
115 * utils_close_pipe().
118 int utils_create_pipe_cloexec(int *dst
)
126 ret
= utils_create_pipe(dst
);
131 for (i
= 0; i
< 2; i
++) {
132 ret
= fcntl(dst
[i
], F_SETFD
, FD_CLOEXEC
);
134 PERROR("fcntl pipe cloexec");
144 * Close both read and write side of the pipe.
147 void utils_close_pipe(int *src
)
155 for (i
= 0; i
< 2; i
++) {
163 PERROR("close pipe");
169 * Create a new string using two strings range.
172 char *utils_strdupdelim(const char *begin
, const char *end
)
176 str
= zmalloc(end
- begin
+ 1);
178 PERROR("zmalloc strdupdelim");
182 memcpy(str
, begin
, end
- begin
);
183 str
[end
- begin
] = '\0';
190 * Set CLOEXEC flag to the give file descriptor.
193 int utils_set_fd_cloexec(int fd
)
202 ret
= fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
204 PERROR("fcntl cloexec");
213 * Create pid file to the given path and filename.
216 int utils_create_pid_file(pid_t pid
, const char *filepath
)
223 fp
= fopen(filepath
, "w");
225 PERROR("open pid file %s", filepath
);
230 ret
= fprintf(fp
, "%d\n", pid
);
232 PERROR("fprintf pid file");
236 DBG("Pid %d written in file %s", pid
, filepath
);
242 * Recursively create directory using the given path and mode.
244 * On success, return 0 else a negative error code.
247 int utils_mkdir_recursive(const char *path
, mode_t mode
)
249 char *p
, tmp
[PATH_MAX
];
256 ret
= snprintf(tmp
, sizeof(tmp
), "%s", path
);
258 PERROR("snprintf mkdir");
263 if (tmp
[len
- 1] == '/') {
267 for (p
= tmp
+ 1; *p
; p
++) {
270 if (tmp
[strlen(tmp
) - 1] == '.' &&
271 tmp
[strlen(tmp
) - 2] == '.' &&
272 tmp
[strlen(tmp
) - 3] == '/') {
273 ERR("Using '/../' is not permitted in the trace path (%s)",
278 ret
= stat(tmp
, &statbuf
);
280 ret
= mkdir(tmp
, mode
);
282 if (errno
!= EEXIST
) {
283 PERROR("mkdir recursive");
293 ret
= mkdir(tmp
, mode
);
295 if (errno
!= EEXIST
) {
296 PERROR("mkdir recursive last piece");
308 * Create the stream tracefile on disk.
310 * Return 0 on success or else a negative value.
312 int utils_create_stream_file(char *path_name
, char *file_name
, uint64_t size
,
313 uint64_t count
, int uid
, int gid
)
316 char full_path
[PATH_MAX
], *path_name_id
= NULL
, *path
;
321 ret
= snprintf(full_path
, sizeof(full_path
), "%s/%s",
322 path_name
, file_name
);
324 PERROR("snprintf create output file");
329 * If we split the trace in multiple files, we have to add the count at the
330 * end of the tracefile name
333 ret
= asprintf(&path_name_id
, "%s_%" PRIu64
, full_path
, count
);
335 PERROR("Allocating path name ID");
343 out_fd
= run_as_open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
,
344 S_IRWXU
| S_IRWXG
| S_IRWXO
, uid
, gid
);
346 PERROR("open stream path %s", path
);
358 * Change the output tracefile according to the given size and count The
359 * new_count pointer is set during this operation.
361 * From the consumer, the stream lock MUST be held before calling this function
362 * because we are modifying the stream status.
364 * Return 0 on success or else a negative value.
366 int utils_rotate_stream_file(char *path_name
, char *file_name
, uint64_t size
,
367 uint64_t count
, int uid
, int gid
, int out_fd
, uint64_t *new_count
)
373 PERROR("Closing tracefile");
378 *new_count
= (*new_count
+ 1) % count
;
383 return utils_create_stream_file(path_name
, file_name
, size
, *new_count
,
This page took 0.055321 seconds and 5 git commands to generate.