Introduce a new utils_resolve_relative function
[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 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <inttypes.h>
29 #include <regex.h>
30 #include <grp.h>
31
32 #include <common/common.h>
33 #include <common/runas.h>
34
35 #include "utils.h"
36 #include "defaults.h"
37
38 /*
39 * Resolve the './' and '../' strings in the middle of a path using
40 * our very own way to do it, so that it works even if the directory
41 * does not exist
42 */
43 LTTNG_HIDDEN
44 char *utils_resolve_relative(const char *path)
45 {
46 char *next, *previous, *slash, *start_path, *absolute_path = NULL;
47
48 /* Safety net */
49 if (path == NULL) {
50 goto error;
51 }
52
53 /* Allocate memory for the absolute path */
54 absolute_path = zmalloc(PATH_MAX);
55 if (absolute_path == NULL) {
56 PERROR("zmalloc expand path");
57 goto error;
58 }
59
60 /* Copy the path in the absolute path */
61 strncpy(absolute_path, path, PATH_MAX);
62
63 /* As long as we find '/./' in the path string */
64 while ((next = strstr(absolute_path, "/./"))) {
65
66 /* We prepare the start_path not containing it */
67 start_path = strndup(absolute_path, next - absolute_path);
68
69 /* And we concatenate it with the part after this string */
70 snprintf(absolute_path, PATH_MAX, "%s%s", start_path, next + 2);
71
72 free(start_path);
73 }
74
75 /* As long as we find '/../' in the path string */
76 while ((next = strstr(absolute_path, "/../"))) {
77 /* If the path starts with '/../', there's a problem */
78 if (next == absolute_path) {
79 ERR("%s: Path cannot be resolved", path);
80 goto error;
81 }
82
83 /* We find the last level of directory */
84 previous = absolute_path;
85 while ((slash = strpbrk(previous + 1, "/")) && slash != next) {
86 previous = slash;
87 }
88
89 /* Then we prepare the start_path not containing it */
90 start_path = strndup(absolute_path, previous - absolute_path);
91
92 /* And we concatenate it with the part after the '/../' */
93 snprintf(absolute_path, PATH_MAX, "%s%s", start_path, next + 3);
94
95 free(start_path);
96 }
97
98 return absolute_path;
99
100 error:
101 free(absolute_path);
102 return NULL;
103 }
104
105
106 /*
107 * Return the realpath(3) of the path even if the last directory token does not
108 * exist. For example, with /tmp/test1/test2, if test2/ does not exist but the
109 * /tmp/test1 does, the real path is returned. In normal time, realpath(3)
110 * fails if the end point directory does not exist.
111 */
112 LTTNG_HIDDEN
113 char *utils_expand_path(const char *path)
114 {
115 const char *end_path = path;
116 char *next, *cut_path = NULL, *expanded_path = NULL;
117
118 /* Safety net */
119 if (path == NULL) {
120 goto error;
121 }
122
123 /* Find last token delimited by '/' */
124 while ((next = strpbrk(end_path + 1, "/"))) {
125 end_path = next;
126 }
127
128 /* Cut last token from original path */
129 cut_path = strndup(path, end_path - path);
130
131 expanded_path = zmalloc(PATH_MAX);
132 if (expanded_path == NULL) {
133 PERROR("zmalloc expand path");
134 goto error;
135 }
136
137 expanded_path = realpath((char *)cut_path, expanded_path);
138 if (expanded_path == NULL) {
139 switch (errno) {
140 case ENOENT:
141 ERR("%s: No such file or directory", cut_path);
142 break;
143 default:
144 PERROR("realpath utils expand path");
145 break;
146 }
147 goto error;
148 }
149
150 /* Add end part to expanded path */
151 strncat(expanded_path, end_path, PATH_MAX - strlen(expanded_path) - 1);
152
153 free(cut_path);
154 return expanded_path;
155
156 error:
157 free(expanded_path);
158 free(cut_path);
159 return NULL;
160 }
161
162 /*
163 * Create a pipe in dst.
164 */
165 LTTNG_HIDDEN
166 int utils_create_pipe(int *dst)
167 {
168 int ret;
169
170 if (dst == NULL) {
171 return -1;
172 }
173
174 ret = pipe(dst);
175 if (ret < 0) {
176 PERROR("create pipe");
177 }
178
179 return ret;
180 }
181
182 /*
183 * Create pipe and set CLOEXEC flag to both fd.
184 *
185 * Make sure the pipe opened by this function are closed at some point. Use
186 * utils_close_pipe().
187 */
188 LTTNG_HIDDEN
189 int utils_create_pipe_cloexec(int *dst)
190 {
191 int ret, i;
192
193 if (dst == NULL) {
194 return -1;
195 }
196
197 ret = utils_create_pipe(dst);
198 if (ret < 0) {
199 goto error;
200 }
201
202 for (i = 0; i < 2; i++) {
203 ret = fcntl(dst[i], F_SETFD, FD_CLOEXEC);
204 if (ret < 0) {
205 PERROR("fcntl pipe cloexec");
206 goto error;
207 }
208 }
209
210 error:
211 return ret;
212 }
213
214 /*
215 * Create pipe and set fd flags to FD_CLOEXEC and O_NONBLOCK.
216 *
217 * Make sure the pipe opened by this function are closed at some point. Use
218 * utils_close_pipe(). Using pipe() and fcntl rather than pipe2() to
219 * support OSes other than Linux 2.6.23+.
220 */
221 LTTNG_HIDDEN
222 int utils_create_pipe_cloexec_nonblock(int *dst)
223 {
224 int ret, i;
225
226 if (dst == NULL) {
227 return -1;
228 }
229
230 ret = utils_create_pipe(dst);
231 if (ret < 0) {
232 goto error;
233 }
234
235 for (i = 0; i < 2; i++) {
236 ret = fcntl(dst[i], F_SETFD, FD_CLOEXEC);
237 if (ret < 0) {
238 PERROR("fcntl pipe cloexec");
239 goto error;
240 }
241 /*
242 * Note: we override any flag that could have been
243 * previously set on the fd.
244 */
245 ret = fcntl(dst[i], F_SETFL, O_NONBLOCK);
246 if (ret < 0) {
247 PERROR("fcntl pipe nonblock");
248 goto error;
249 }
250 }
251
252 error:
253 return ret;
254 }
255
256 /*
257 * Close both read and write side of the pipe.
258 */
259 LTTNG_HIDDEN
260 void utils_close_pipe(int *src)
261 {
262 int i, ret;
263
264 if (src == NULL) {
265 return;
266 }
267
268 for (i = 0; i < 2; i++) {
269 /* Safety check */
270 if (src[i] < 0) {
271 continue;
272 }
273
274 ret = close(src[i]);
275 if (ret) {
276 PERROR("close pipe");
277 }
278 }
279 }
280
281 /*
282 * Create a new string using two strings range.
283 */
284 LTTNG_HIDDEN
285 char *utils_strdupdelim(const char *begin, const char *end)
286 {
287 char *str;
288
289 str = zmalloc(end - begin + 1);
290 if (str == NULL) {
291 PERROR("zmalloc strdupdelim");
292 goto error;
293 }
294
295 memcpy(str, begin, end - begin);
296 str[end - begin] = '\0';
297
298 error:
299 return str;
300 }
301
302 /*
303 * Set CLOEXEC flag to the give file descriptor.
304 */
305 LTTNG_HIDDEN
306 int utils_set_fd_cloexec(int fd)
307 {
308 int ret;
309
310 if (fd < 0) {
311 ret = -EINVAL;
312 goto end;
313 }
314
315 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
316 if (ret < 0) {
317 PERROR("fcntl cloexec");
318 ret = -errno;
319 }
320
321 end:
322 return ret;
323 }
324
325 /*
326 * Create pid file to the given path and filename.
327 */
328 LTTNG_HIDDEN
329 int utils_create_pid_file(pid_t pid, const char *filepath)
330 {
331 int ret;
332 FILE *fp;
333
334 assert(filepath);
335
336 fp = fopen(filepath, "w");
337 if (fp == NULL) {
338 PERROR("open pid file %s", filepath);
339 ret = -1;
340 goto error;
341 }
342
343 ret = fprintf(fp, "%d\n", pid);
344 if (ret < 0) {
345 PERROR("fprintf pid file");
346 }
347
348 fclose(fp);
349 DBG("Pid %d written in file %s", pid, filepath);
350 error:
351 return ret;
352 }
353
354 /*
355 * Recursively create directory using the given path and mode.
356 *
357 * On success, return 0 else a negative error code.
358 */
359 LTTNG_HIDDEN
360 int utils_mkdir_recursive(const char *path, mode_t mode)
361 {
362 char *p, tmp[PATH_MAX];
363 size_t len;
364 int ret;
365
366 assert(path);
367
368 ret = snprintf(tmp, sizeof(tmp), "%s", path);
369 if (ret < 0) {
370 PERROR("snprintf mkdir");
371 goto error;
372 }
373
374 len = ret;
375 if (tmp[len - 1] == '/') {
376 tmp[len - 1] = 0;
377 }
378
379 for (p = tmp + 1; *p; p++) {
380 if (*p == '/') {
381 *p = 0;
382 if (tmp[strlen(tmp) - 1] == '.' &&
383 tmp[strlen(tmp) - 2] == '.' &&
384 tmp[strlen(tmp) - 3] == '/') {
385 ERR("Using '/../' is not permitted in the trace path (%s)",
386 tmp);
387 ret = -1;
388 goto error;
389 }
390 ret = mkdir(tmp, mode);
391 if (ret < 0) {
392 if (errno != EEXIST) {
393 PERROR("mkdir recursive");
394 ret = -errno;
395 goto error;
396 }
397 }
398 *p = '/';
399 }
400 }
401
402 ret = mkdir(tmp, mode);
403 if (ret < 0) {
404 if (errno != EEXIST) {
405 PERROR("mkdir recursive last piece");
406 ret = -errno;
407 } else {
408 ret = 0;
409 }
410 }
411
412 error:
413 return ret;
414 }
415
416 /*
417 * Create the stream tracefile on disk.
418 *
419 * Return 0 on success or else a negative value.
420 */
421 LTTNG_HIDDEN
422 int utils_create_stream_file(const char *path_name, char *file_name, uint64_t size,
423 uint64_t count, int uid, int gid, char *suffix)
424 {
425 int ret, out_fd, flags, mode;
426 char full_path[PATH_MAX], *path_name_suffix = NULL, *path;
427 char *extra = NULL;
428
429 assert(path_name);
430 assert(file_name);
431
432 ret = snprintf(full_path, sizeof(full_path), "%s/%s",
433 path_name, file_name);
434 if (ret < 0) {
435 PERROR("snprintf create output file");
436 goto error;
437 }
438
439 /* Setup extra string if suffix or/and a count is needed. */
440 if (size > 0 && suffix) {
441 ret = asprintf(&extra, "_%" PRIu64 "%s", count, suffix);
442 } else if (size > 0) {
443 ret = asprintf(&extra, "_%" PRIu64, count);
444 } else if (suffix) {
445 ret = asprintf(&extra, "%s", suffix);
446 }
447 if (ret < 0) {
448 PERROR("Allocating extra string to name");
449 goto error;
450 }
451
452 /*
453 * If we split the trace in multiple files, we have to add the count at the
454 * end of the tracefile name
455 */
456 if (extra) {
457 ret = asprintf(&path_name_suffix, "%s%s", full_path, extra);
458 if (ret < 0) {
459 PERROR("Allocating path name with extra string");
460 goto error_free_suffix;
461 }
462 path = path_name_suffix;
463 } else {
464 path = full_path;
465 }
466
467 flags = O_WRONLY | O_CREAT | O_TRUNC;
468 /* Open with 660 mode */
469 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
470
471 if (uid < 0 || gid < 0) {
472 out_fd = open(path, flags, mode);
473 } else {
474 out_fd = run_as_open(path, flags, mode, uid, gid);
475 }
476 if (out_fd < 0) {
477 PERROR("open stream path %s", path);
478 goto error_open;
479 }
480 ret = out_fd;
481
482 error_open:
483 free(path_name_suffix);
484 error_free_suffix:
485 free(extra);
486 error:
487 return ret;
488 }
489
490 /*
491 * Change the output tracefile according to the given size and count The
492 * new_count pointer is set during this operation.
493 *
494 * From the consumer, the stream lock MUST be held before calling this function
495 * because we are modifying the stream status.
496 *
497 * Return 0 on success or else a negative value.
498 */
499 LTTNG_HIDDEN
500 int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
501 uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count,
502 int *stream_fd)
503 {
504 int ret;
505
506 assert(new_count);
507 assert(stream_fd);
508
509 ret = close(out_fd);
510 if (ret < 0) {
511 PERROR("Closing tracefile");
512 goto error;
513 }
514
515 if (count > 0) {
516 *new_count = (*new_count + 1) % count;
517 } else {
518 (*new_count)++;
519 }
520
521 ret = utils_create_stream_file(path_name, file_name, size, *new_count,
522 uid, gid, 0);
523 if (ret < 0) {
524 goto error;
525 }
526 *stream_fd = ret;
527
528 /* Success. */
529 ret = 0;
530
531 error:
532 return ret;
533 }
534
535 /**
536 * Prints the error message corresponding to a regex error code.
537 *
538 * @param errcode The error code.
539 * @param regex The regex object that produced the error code.
540 */
541 static void regex_print_error(int errcode, regex_t *regex)
542 {
543 /* Get length of error message and allocate accordingly */
544 size_t length;
545 char *buffer;
546
547 assert(regex != NULL);
548
549 length = regerror(errcode, regex, NULL, 0);
550 if (length == 0) {
551 ERR("regerror returned a length of 0");
552 return;
553 }
554
555 buffer = zmalloc(length);
556 if (!buffer) {
557 ERR("regex_print_error: zmalloc failed");
558 return;
559 }
560
561 /* Get and print error message */
562 regerror(errcode, regex, buffer, length);
563 ERR("regex error: %s\n", buffer);
564 free(buffer);
565
566 }
567
568 /**
569 * Parse a string that represents a size in human readable format. It
570 * supports decimal integers suffixed by 'k', 'M' or 'G'.
571 *
572 * The suffix multiply the integer by:
573 * 'k': 1024
574 * 'M': 1024^2
575 * 'G': 1024^3
576 *
577 * @param str The string to parse.
578 * @param size Pointer to a size_t that will be filled with the
579 * resulting size.
580 *
581 * @return 0 on success, -1 on failure.
582 */
583 LTTNG_HIDDEN
584 int utils_parse_size_suffix(char *str, uint64_t *size)
585 {
586 regex_t regex;
587 int ret;
588 const int nmatch = 3;
589 regmatch_t suffix_match, matches[nmatch];
590 unsigned long long base_size;
591 long shift = 0;
592
593 if (!str) {
594 return 0;
595 }
596
597 /* Compile regex */
598 ret = regcomp(&regex, "^\\(0x\\)\\{0,1\\}[0-9][0-9]*\\([kKMG]\\{0,1\\}\\)$", 0);
599 if (ret != 0) {
600 regex_print_error(ret, &regex);
601 ret = -1;
602 goto end;
603 }
604
605 /* Match regex */
606 ret = regexec(&regex, str, nmatch, matches, 0);
607 if (ret != 0) {
608 ret = -1;
609 goto free;
610 }
611
612 /* There is a match ! */
613 errno = 0;
614 base_size = strtoull(str, NULL, 0);
615 if (errno != 0) {
616 PERROR("strtoull");
617 ret = -1;
618 goto free;
619 }
620
621 /* Check if there is a suffix */
622 suffix_match = matches[2];
623 if (suffix_match.rm_eo - suffix_match.rm_so == 1) {
624 switch (*(str + suffix_match.rm_so)) {
625 case 'K':
626 case 'k':
627 shift = KIBI_LOG2;
628 break;
629 case 'M':
630 shift = MEBI_LOG2;
631 break;
632 case 'G':
633 shift = GIBI_LOG2;
634 break;
635 default:
636 ERR("parse_human_size: invalid suffix");
637 ret = -1;
638 goto free;
639 }
640 }
641
642 *size = base_size << shift;
643
644 /* Check for overflow */
645 if ((*size >> shift) != base_size) {
646 ERR("parse_size_suffix: oops, overflow detected.");
647 ret = -1;
648 goto free;
649 }
650
651 ret = 0;
652
653 free:
654 regfree(&regex);
655 end:
656 return ret;
657 }
658
659 /*
660 * fls: returns the position of the most significant bit.
661 * Returns 0 if no bit is set, else returns the position of the most
662 * significant bit (from 1 to 32 on 32-bit, from 1 to 64 on 64-bit).
663 */
664 #if defined(__i386) || defined(__x86_64)
665 static inline unsigned int fls_u32(uint32_t x)
666 {
667 int r;
668
669 asm("bsrl %1,%0\n\t"
670 "jnz 1f\n\t"
671 "movl $-1,%0\n\t"
672 "1:\n\t"
673 : "=r" (r) : "rm" (x));
674 return r + 1;
675 }
676 #define HAS_FLS_U32
677 #endif
678
679 #ifndef HAS_FLS_U32
680 static __attribute__((unused)) unsigned int fls_u32(uint32_t x)
681 {
682 unsigned int r = 32;
683
684 if (!x) {
685 return 0;
686 }
687 if (!(x & 0xFFFF0000U)) {
688 x <<= 16;
689 r -= 16;
690 }
691 if (!(x & 0xFF000000U)) {
692 x <<= 8;
693 r -= 8;
694 }
695 if (!(x & 0xF0000000U)) {
696 x <<= 4;
697 r -= 4;
698 }
699 if (!(x & 0xC0000000U)) {
700 x <<= 2;
701 r -= 2;
702 }
703 if (!(x & 0x80000000U)) {
704 x <<= 1;
705 r -= 1;
706 }
707 return r;
708 }
709 #endif
710
711 /*
712 * Return the minimum order for which x <= (1UL << order).
713 * Return -1 if x is 0.
714 */
715 LTTNG_HIDDEN
716 int utils_get_count_order_u32(uint32_t x)
717 {
718 if (!x) {
719 return -1;
720 }
721
722 return fls_u32(x - 1);
723 }
724
725 /**
726 * Obtain the value of LTTNG_HOME environment variable, if exists.
727 * Otherwise returns the value of HOME.
728 */
729 LTTNG_HIDDEN
730 char *utils_get_home_dir(void)
731 {
732 char *val = NULL;
733 val = getenv(DEFAULT_LTTNG_HOME_ENV_VAR);
734 if (val != NULL) {
735 return val;
736 }
737 return getenv(DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR);
738 }
739
740 /*
741 * With the given format, fill dst with the time of len maximum siz.
742 *
743 * Return amount of bytes set in the buffer or else 0 on error.
744 */
745 LTTNG_HIDDEN
746 size_t utils_get_current_time_str(const char *format, char *dst, size_t len)
747 {
748 size_t ret;
749 time_t rawtime;
750 struct tm *timeinfo;
751
752 assert(format);
753 assert(dst);
754
755 /* Get date and time for session path */
756 time(&rawtime);
757 timeinfo = localtime(&rawtime);
758 ret = strftime(dst, len, format, timeinfo);
759 if (ret == 0) {
760 ERR("Unable to strftime with format %s at dst %p of len %lu", format,
761 dst, len);
762 }
763
764 return ret;
765 }
766
767 /*
768 * Return the group ID matching name, else 0 if it cannot be found.
769 */
770 LTTNG_HIDDEN
771 gid_t utils_get_group_id(const char *name)
772 {
773 struct group *grp;
774
775 grp = getgrnam(name);
776 if (!grp) {
777 static volatile int warn_once;
778
779 if (!warn_once) {
780 WARN("No tracing group detected");
781 warn_once = 1;
782 }
783 return 0;
784 }
785 return grp->gr_gid;
786 }
This page took 0.044371 seconds and 5 git commands to generate.