Build fix: specialization of template in different namespace
[lttng-tools.git] / src / common / utils.cpp
1 /*
2 * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
3 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-only
6 *
7 */
8
9 #define _LGPL_SOURCE
10 #include <ctype.h>
11 #include <fcntl.h>
12 #include <grp.h>
13 #include <inttypes.h>
14 #include <limits.h>
15 #include <pwd.h>
16 #include <stdlib.h>
17 #include <sys/file.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include <common/common.hpp>
23 #include <common/compat/directory-handle.hpp>
24 #include <common/compat/dirent.hpp>
25 #include <common/compat/getenv.hpp>
26 #include <common/compat/string.hpp>
27 #include <common/dynamic-buffer.hpp>
28 #include <common/readwrite.hpp>
29 #include <common/runas.hpp>
30 #include <common/string-utils/format.hpp>
31 #include <lttng/constant.h>
32
33 #include "defaults.hpp"
34 #include "time.hpp"
35 #include "utils.hpp"
36
37 #define PROC_MEMINFO_PATH "/proc/meminfo"
38 #define PROC_MEMINFO_MEMAVAILABLE_LINE "MemAvailable:"
39 #define PROC_MEMINFO_MEMTOTAL_LINE "MemTotal:"
40
41 /* The length of the longest field of `/proc/meminfo`. */
42 #define PROC_MEMINFO_FIELD_MAX_NAME_LEN 20
43
44 #if (PROC_MEMINFO_FIELD_MAX_NAME_LEN == 20)
45 #define MAX_NAME_LEN_SCANF_IS_A_BROKEN_API "19"
46 #else
47 #error MAX_NAME_LEN_SCANF_IS_A_BROKEN_API must be updated to match (PROC_MEMINFO_FIELD_MAX_NAME_LEN - 1)
48 #endif
49
50 #define FALLBACK_USER_BUFLEN 16384
51 #define FALLBACK_GROUP_BUFLEN 16384
52
53 /*
54 * Create a pipe in dst.
55 */
56 int utils_create_pipe(int *dst)
57 {
58 int ret;
59
60 if (dst == NULL) {
61 return -1;
62 }
63
64 ret = pipe(dst);
65 if (ret < 0) {
66 PERROR("create pipe");
67 }
68
69 return ret;
70 }
71
72 /*
73 * Create pipe and set CLOEXEC flag to both fd.
74 *
75 * Make sure the pipe opened by this function are closed at some point. Use
76 * utils_close_pipe().
77 */
78 int utils_create_pipe_cloexec(int *dst)
79 {
80 int ret, i;
81
82 if (dst == NULL) {
83 return -1;
84 }
85
86 ret = utils_create_pipe(dst);
87 if (ret < 0) {
88 goto error;
89 }
90
91 for (i = 0; i < 2; i++) {
92 ret = fcntl(dst[i], F_SETFD, FD_CLOEXEC);
93 if (ret < 0) {
94 PERROR("fcntl pipe cloexec");
95 goto error;
96 }
97 }
98
99 error:
100 return ret;
101 }
102
103 /*
104 * Create pipe and set fd flags to FD_CLOEXEC and O_NONBLOCK.
105 *
106 * Make sure the pipe opened by this function are closed at some point. Use
107 * utils_close_pipe(). Using pipe() and fcntl rather than pipe2() to
108 * support OSes other than Linux 2.6.23+.
109 */
110 int utils_create_pipe_cloexec_nonblock(int *dst)
111 {
112 int ret, i;
113
114 if (dst == NULL) {
115 return -1;
116 }
117
118 ret = utils_create_pipe(dst);
119 if (ret < 0) {
120 goto error;
121 }
122
123 for (i = 0; i < 2; i++) {
124 ret = fcntl(dst[i], F_SETFD, FD_CLOEXEC);
125 if (ret < 0) {
126 PERROR("fcntl pipe cloexec");
127 goto error;
128 }
129 /*
130 * Note: we override any flag that could have been
131 * previously set on the fd.
132 */
133 ret = fcntl(dst[i], F_SETFL, O_NONBLOCK);
134 if (ret < 0) {
135 PERROR("fcntl pipe nonblock");
136 goto error;
137 }
138 }
139
140 error:
141 return ret;
142 }
143
144 /*
145 * Close both read and write side of the pipe.
146 */
147 void utils_close_pipe(int *src)
148 {
149 int i, ret;
150
151 if (src == NULL) {
152 return;
153 }
154
155 for (i = 0; i < 2; i++) {
156 /* Safety check */
157 if (src[i] < 0) {
158 continue;
159 }
160
161 ret = close(src[i]);
162 if (ret) {
163 PERROR("close pipe");
164 }
165 src[i] = -1;
166 }
167 }
168
169 /*
170 * Create a new string using two strings range.
171 */
172 char *utils_strdupdelim(const char *begin, const char *end)
173 {
174 char *str = zmalloc<char>(end - begin + 1);
175
176 if (str == NULL) {
177 PERROR("zmalloc strdupdelim");
178 goto error;
179 }
180
181 memcpy(str, begin, end - begin);
182 str[end - begin] = '\0';
183
184 error:
185 return str;
186 }
187
188 /*
189 * Set CLOEXEC flag to the give file descriptor.
190 */
191 int utils_set_fd_cloexec(int fd)
192 {
193 int ret;
194
195 if (fd < 0) {
196 ret = -EINVAL;
197 goto end;
198 }
199
200 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
201 if (ret < 0) {
202 PERROR("fcntl cloexec");
203 ret = -errno;
204 }
205
206 end:
207 return ret;
208 }
209
210 /*
211 * Create pid file to the given path and filename.
212 */
213 int utils_create_pid_file(pid_t pid, const char *filepath)
214 {
215 int ret;
216 FILE *fp;
217
218 LTTNG_ASSERT(filepath);
219
220 fp = fopen(filepath, "w");
221 if (fp == NULL) {
222 PERROR("open pid file %s", filepath);
223 ret = -1;
224 goto error;
225 }
226
227 ret = fprintf(fp, "%d\n", (int) pid);
228 if (ret < 0) {
229 PERROR("fprintf pid file");
230 goto error;
231 }
232
233 if (fclose(fp)) {
234 PERROR("fclose");
235 }
236 DBG("Pid %d written in file %s", (int) pid, filepath);
237 ret = 0;
238 error:
239 return ret;
240 }
241
242 /*
243 * Create lock file to the given path and filename.
244 * Returns the associated file descriptor, -1 on error.
245 */
246 int utils_create_lock_file(const char *filepath)
247 {
248 int ret;
249 int fd;
250 struct flock lock;
251
252 LTTNG_ASSERT(filepath);
253
254 memset(&lock, 0, sizeof(lock));
255 fd = open(filepath, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR |
256 S_IRGRP | S_IWGRP);
257 if (fd < 0) {
258 PERROR("open lock file %s", filepath);
259 fd = -1;
260 goto error;
261 }
262
263 /*
264 * Attempt to lock the file. If this fails, there is
265 * already a process using the same lock file running
266 * and we should exit.
267 */
268 lock.l_whence = SEEK_SET;
269 lock.l_type = F_WRLCK;
270
271 ret = fcntl(fd, F_SETLK, &lock);
272 if (ret == -1) {
273 PERROR("fcntl lock file");
274 ERR("Could not get lock file %s, another instance is running.",
275 filepath);
276 if (close(fd)) {
277 PERROR("close lock file");
278 }
279 fd = ret;
280 goto error;
281 }
282
283 error:
284 return fd;
285 }
286
287 /*
288 * Create directory using the given path and mode.
289 *
290 * On success, return 0 else a negative error code.
291 */
292 int utils_mkdir(const char *path, mode_t mode, int uid, int gid)
293 {
294 int ret;
295 struct lttng_directory_handle *handle;
296 const struct lttng_credentials creds = {
297 .uid = LTTNG_OPTIONAL_INIT_VALUE((uid_t) uid),
298 .gid = LTTNG_OPTIONAL_INIT_VALUE((gid_t) gid),
299 };
300
301 handle = lttng_directory_handle_create(NULL);
302 if (!handle) {
303 ret = -1;
304 goto end;
305 }
306 ret = lttng_directory_handle_create_subdirectory_as_user(
307 handle, path, mode,
308 (uid >= 0 || gid >= 0) ? &creds : NULL);
309 end:
310 lttng_directory_handle_put(handle);
311 return ret;
312 }
313
314 /*
315 * Recursively create directory using the given path and mode, under the
316 * provided uid and gid.
317 *
318 * On success, return 0 else a negative error code.
319 */
320 int utils_mkdir_recursive(const char *path, mode_t mode, int uid, int gid)
321 {
322 int ret;
323 struct lttng_directory_handle *handle;
324 const struct lttng_credentials creds = {
325 .uid = LTTNG_OPTIONAL_INIT_VALUE((uid_t) uid),
326 .gid = LTTNG_OPTIONAL_INIT_VALUE((gid_t) gid),
327 };
328
329 handle = lttng_directory_handle_create(NULL);
330 if (!handle) {
331 ret = -1;
332 goto end;
333 }
334 ret = lttng_directory_handle_create_subdirectory_recursive_as_user(
335 handle, path, mode,
336 (uid >= 0 || gid >= 0) ? &creds : NULL);
337 end:
338 lttng_directory_handle_put(handle);
339 return ret;
340 }
341
342 /*
343 * out_stream_path is the output parameter.
344 *
345 * Return 0 on success or else a negative value.
346 */
347 int utils_stream_file_path(const char *path_name, const char *file_name,
348 uint64_t size, uint64_t count, const char *suffix,
349 char *out_stream_path, size_t stream_path_len)
350 {
351 int ret;
352 char count_str[MAX_INT_DEC_LEN(count) + 1] = {};
353 const char *path_separator;
354
355 if (path_name && (path_name[0] == '\0' ||
356 path_name[strlen(path_name) - 1] == '/')) {
357 path_separator = "";
358 } else {
359 path_separator = "/";
360 }
361
362 path_name = path_name ? : "";
363 suffix = suffix ? : "";
364 if (size > 0) {
365 ret = snprintf(count_str, sizeof(count_str), "_%" PRIu64,
366 count);
367 LTTNG_ASSERT(ret > 0 && ret < sizeof(count_str));
368 }
369
370 ret = snprintf(out_stream_path, stream_path_len, "%s%s%s%s%s",
371 path_name, path_separator, file_name, count_str,
372 suffix);
373 if (ret < 0 || ret >= stream_path_len) {
374 ERR("Truncation occurred while formatting stream path");
375 ret = -1;
376 } else {
377 ret = 0;
378 }
379 return ret;
380 }
381
382 /**
383 * Parse a string that represents a size in human readable format. It
384 * supports decimal integers suffixed by 'k', 'K', 'M' or 'G'.
385 *
386 * The suffix multiply the integer by:
387 * 'k': 1024
388 * 'M': 1024^2
389 * 'G': 1024^3
390 *
391 * @param str The string to parse.
392 * @param size Pointer to a uint64_t that will be filled with the
393 * resulting size.
394 *
395 * @return 0 on success, -1 on failure.
396 */
397 int utils_parse_size_suffix(const char * const str, uint64_t * const size)
398 {
399 int ret;
400 uint64_t base_size;
401 long shift = 0;
402 const char *str_end;
403 char *num_end;
404
405 if (!str) {
406 DBG("utils_parse_size_suffix: received a NULL string.");
407 ret = -1;
408 goto end;
409 }
410
411 /* strtoull will accept a negative number, but we don't want to. */
412 if (strchr(str, '-') != NULL) {
413 DBG("utils_parse_size_suffix: invalid size string, should not contain '-'.");
414 ret = -1;
415 goto end;
416 }
417
418 /* str_end will point to the \0 */
419 str_end = str + strlen(str);
420 errno = 0;
421 base_size = strtoull(str, &num_end, 0);
422 if (errno != 0) {
423 PERROR("utils_parse_size_suffix strtoull");
424 ret = -1;
425 goto end;
426 }
427
428 if (num_end == str) {
429 /* strtoull parsed nothing, not good. */
430 DBG("utils_parse_size_suffix: strtoull had nothing good to parse.");
431 ret = -1;
432 goto end;
433 }
434
435 /* Check if a prefix is present. */
436 switch (*num_end) {
437 case 'G':
438 shift = GIBI_LOG2;
439 num_end++;
440 break;
441 case 'M': /* */
442 shift = MEBI_LOG2;
443 num_end++;
444 break;
445 case 'K':
446 case 'k':
447 shift = KIBI_LOG2;
448 num_end++;
449 break;
450 case '\0':
451 break;
452 default:
453 DBG("utils_parse_size_suffix: invalid suffix.");
454 ret = -1;
455 goto end;
456 }
457
458 /* Check for garbage after the valid input. */
459 if (num_end != str_end) {
460 DBG("utils_parse_size_suffix: Garbage after size string.");
461 ret = -1;
462 goto end;
463 }
464
465 *size = base_size << shift;
466
467 /* Check for overflow */
468 if ((*size >> shift) != base_size) {
469 DBG("utils_parse_size_suffix: oops, overflow detected.");
470 ret = -1;
471 goto end;
472 }
473
474 ret = 0;
475 end:
476 return ret;
477 }
478
479 /**
480 * Parse a string that represents a time in human readable format. It
481 * supports decimal integers suffixed by:
482 * "us" for microsecond,
483 * "ms" for millisecond,
484 * "s" for second,
485 * "m" for minute,
486 * "h" for hour
487 *
488 * The suffix multiply the integer by:
489 * "us" : 1
490 * "ms" : 1000
491 * "s" : 1000000
492 * "m" : 60000000
493 * "h" : 3600000000
494 *
495 * Note that unit-less numbers are assumed to be microseconds.
496 *
497 * @param str The string to parse, assumed to be NULL-terminated.
498 * @param time_us Pointer to a uint64_t that will be filled with the
499 * resulting time in microseconds.
500 *
501 * @return 0 on success, -1 on failure.
502 */
503 int utils_parse_time_suffix(char const * const str, uint64_t * const time_us)
504 {
505 int ret;
506 uint64_t base_time;
507 uint64_t multiplier = 1;
508 const char *str_end;
509 char *num_end;
510
511 if (!str) {
512 DBG("utils_parse_time_suffix: received a NULL string.");
513 ret = -1;
514 goto end;
515 }
516
517 /* strtoull will accept a negative number, but we don't want to. */
518 if (strchr(str, '-') != NULL) {
519 DBG("utils_parse_time_suffix: invalid time string, should not contain '-'.");
520 ret = -1;
521 goto end;
522 }
523
524 /* str_end will point to the \0 */
525 str_end = str + strlen(str);
526 errno = 0;
527 base_time = strtoull(str, &num_end, 10);
528 if (errno != 0) {
529 PERROR("utils_parse_time_suffix strtoull on string \"%s\"", str);
530 ret = -1;
531 goto end;
532 }
533
534 if (num_end == str) {
535 /* strtoull parsed nothing, not good. */
536 DBG("utils_parse_time_suffix: strtoull had nothing good to parse.");
537 ret = -1;
538 goto end;
539 }
540
541 /* Check if a prefix is present. */
542 switch (*num_end) {
543 case 'u':
544 /*
545 * Microsecond (us)
546 *
547 * Skip the "us" if the string matches the "us" suffix,
548 * otherwise let the check for the end of the string handle
549 * the error reporting.
550 */
551 if (*(num_end + 1) == 's') {
552 num_end += 2;
553 }
554 break;
555 case 'm':
556 if (*(num_end + 1) == 's') {
557 /* Millisecond (ms) */
558 multiplier = USEC_PER_MSEC;
559 /* Skip the 's' */
560 num_end++;
561 } else {
562 /* Minute (m) */
563 multiplier = USEC_PER_MINUTE;
564 }
565 num_end++;
566 break;
567 case 's':
568 /* Second */
569 multiplier = USEC_PER_SEC;
570 num_end++;
571 break;
572 case 'h':
573 /* Hour */
574 multiplier = USEC_PER_HOURS;
575 num_end++;
576 break;
577 case '\0':
578 break;
579 default:
580 DBG("utils_parse_time_suffix: invalid suffix.");
581 ret = -1;
582 goto end;
583 }
584
585 /* Check for garbage after the valid input. */
586 if (num_end != str_end) {
587 DBG("utils_parse_time_suffix: Garbage after time string.");
588 ret = -1;
589 goto end;
590 }
591
592 *time_us = base_time * multiplier;
593
594 /* Check for overflow */
595 if ((*time_us / multiplier) != base_time) {
596 DBG("utils_parse_time_suffix: oops, overflow detected.");
597 ret = -1;
598 goto end;
599 }
600
601 ret = 0;
602 end:
603 return ret;
604 }
605
606 /*
607 * fls: returns the position of the most significant bit.
608 * Returns 0 if no bit is set, else returns the position of the most
609 * significant bit (from 1 to 32 on 32-bit, from 1 to 64 on 64-bit).
610 */
611 #if defined(__i386) || defined(__x86_64)
612 static inline unsigned int fls_u32(uint32_t x)
613 {
614 int r;
615
616 asm("bsrl %1,%0\n\t"
617 "jnz 1f\n\t"
618 "movl $-1,%0\n\t"
619 "1:\n\t"
620 : "=r" (r) : "rm" (x));
621 return r + 1;
622 }
623 #define HAS_FLS_U32
624 #endif
625
626 #if defined(__x86_64) && defined(__LP64__)
627 static inline
628 unsigned int fls_u64(uint64_t x)
629 {
630 long r;
631
632 asm("bsrq %1,%0\n\t"
633 "jnz 1f\n\t"
634 "movq $-1,%0\n\t"
635 "1:\n\t"
636 : "=r" (r) : "rm" (x));
637 return r + 1;
638 }
639 #define HAS_FLS_U64
640 #endif
641
642 #ifndef HAS_FLS_U64
643 static __attribute__((unused))
644 unsigned int fls_u64(uint64_t x)
645 {
646 unsigned int r = 64;
647
648 if (!x)
649 return 0;
650
651 if (!(x & 0xFFFFFFFF00000000ULL)) {
652 x <<= 32;
653 r -= 32;
654 }
655 if (!(x & 0xFFFF000000000000ULL)) {
656 x <<= 16;
657 r -= 16;
658 }
659 if (!(x & 0xFF00000000000000ULL)) {
660 x <<= 8;
661 r -= 8;
662 }
663 if (!(x & 0xF000000000000000ULL)) {
664 x <<= 4;
665 r -= 4;
666 }
667 if (!(x & 0xC000000000000000ULL)) {
668 x <<= 2;
669 r -= 2;
670 }
671 if (!(x & 0x8000000000000000ULL)) {
672 x <<= 1;
673 r -= 1;
674 }
675 return r;
676 }
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 int utils_get_count_order_u32(uint32_t x)
716 {
717 if (!x) {
718 return -1;
719 }
720
721 return fls_u32(x - 1);
722 }
723
724 /*
725 * Return the minimum order for which x <= (1UL << order).
726 * Return -1 if x is 0.
727 */
728 int utils_get_count_order_u64(uint64_t x)
729 {
730 if (!x) {
731 return -1;
732 }
733
734 return fls_u64(x - 1);
735 }
736
737 /**
738 * Obtain the value of LTTNG_HOME environment variable, if exists.
739 * Otherwise returns the value of HOME.
740 */
741 const char *utils_get_home_dir(void)
742 {
743 char *val = NULL;
744 struct passwd *pwd;
745
746 val = lttng_secure_getenv(DEFAULT_LTTNG_HOME_ENV_VAR);
747 if (val != NULL) {
748 goto end;
749 }
750 val = lttng_secure_getenv(DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR);
751 if (val != NULL) {
752 goto end;
753 }
754
755 /* Fallback on the password file entry. */
756 pwd = getpwuid(getuid());
757 if (!pwd) {
758 goto end;
759 }
760 val = pwd->pw_dir;
761
762 DBG3("Home directory is '%s'", val);
763
764 end:
765 return val;
766 }
767
768 /**
769 * Get user's home directory. Dynamically allocated, must be freed
770 * by the caller.
771 */
772 char *utils_get_user_home_dir(uid_t uid)
773 {
774 struct passwd pwd;
775 struct passwd *result;
776 char *home_dir = NULL;
777 char *buf = NULL;
778 long buflen;
779 int ret;
780
781 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
782 if (buflen == -1) {
783 goto end;
784 }
785 retry:
786 buf = zmalloc<char>(buflen);
787 if (!buf) {
788 goto end;
789 }
790
791 ret = getpwuid_r(uid, &pwd, buf, buflen, &result);
792 if (ret || !result) {
793 if (ret == ERANGE) {
794 free(buf);
795 buflen *= 2;
796 goto retry;
797 }
798 goto end;
799 }
800
801 home_dir = strdup(pwd.pw_dir);
802 end:
803 free(buf);
804 return home_dir;
805 }
806
807 /*
808 * With the given format, fill dst with the time of len maximum siz.
809 *
810 * Return amount of bytes set in the buffer or else 0 on error.
811 */
812 size_t utils_get_current_time_str(const char *format, char *dst, size_t len)
813 {
814 size_t ret;
815 time_t rawtime;
816 struct tm *timeinfo;
817
818 LTTNG_ASSERT(format);
819 LTTNG_ASSERT(dst);
820
821 /* Get date and time for session path */
822 time(&rawtime);
823 timeinfo = localtime(&rawtime);
824 DIAGNOSTIC_PUSH
825 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
826 ret = strftime(dst, len, format, timeinfo);
827 DIAGNOSTIC_POP
828 if (ret == 0) {
829 ERR("Unable to strftime with format %s at dst %p of len %zu", format,
830 dst, len);
831 }
832
833 return ret;
834 }
835
836 /*
837 * Return 0 on success and set *gid to the group_ID matching the passed name.
838 * Else -1 if it cannot be found or an error occurred.
839 */
840 int utils_get_group_id(const char *name, bool warn, gid_t *gid)
841 {
842 static volatile int warn_once;
843 int ret;
844 long sys_len;
845 size_t len;
846 struct group grp;
847 struct group *result;
848 struct lttng_dynamic_buffer buffer;
849
850 /* Get the system limit, if it exists. */
851 sys_len = sysconf(_SC_GETGR_R_SIZE_MAX);
852 if (sys_len == -1) {
853 len = 1024;
854 } else {
855 len = (size_t) sys_len;
856 }
857
858 lttng_dynamic_buffer_init(&buffer);
859 ret = lttng_dynamic_buffer_set_size(&buffer, len);
860 if (ret) {
861 ERR("Failed to allocate group info buffer");
862 ret = -1;
863 goto error;
864 }
865
866 while ((ret = getgrnam_r(name, &grp, buffer.data, buffer.size, &result)) == ERANGE) {
867 const size_t new_len = 2 * buffer.size;
868
869 /* Buffer is not big enough, increase its size. */
870 if (new_len < buffer.size) {
871 ERR("Group info buffer size overflow");
872 ret = -1;
873 goto error;
874 }
875
876 ret = lttng_dynamic_buffer_set_size(&buffer, new_len);
877 if (ret) {
878 ERR("Failed to grow group info buffer to %zu bytes",
879 new_len);
880 ret = -1;
881 goto error;
882 }
883 }
884 if (ret) {
885 if (ret == ESRCH) {
886 DBG("Could not find group file entry for group name '%s'",
887 name);
888 } else {
889 PERROR("Failed to get group file entry for group name '%s'",
890 name);
891 }
892
893 ret = -1;
894 goto error;
895 }
896
897 /* Group not found. */
898 if (!result) {
899 ret = -1;
900 goto error;
901 }
902
903 *gid = result->gr_gid;
904 ret = 0;
905
906 error:
907 if (ret && warn && !warn_once) {
908 WARN("No tracing group detected");
909 warn_once = 1;
910 }
911 lttng_dynamic_buffer_reset(&buffer);
912 return ret;
913 }
914
915 /*
916 * Return a newly allocated option string. This string is to be used as the
917 * optstring argument of getopt_long(), see GETOPT(3). opt_count is the number
918 * of elements in the long_options array. Returns NULL if the string's
919 * allocation fails.
920 */
921 char *utils_generate_optstring(const struct option *long_options,
922 size_t opt_count)
923 {
924 int i;
925 size_t string_len = opt_count, str_pos = 0;
926 char *optstring;
927
928 /*
929 * Compute the necessary string length. One letter per option, two when an
930 * argument is necessary, and a trailing NULL.
931 */
932 for (i = 0; i < opt_count; i++) {
933 string_len += long_options[i].has_arg ? 1 : 0;
934 }
935
936 optstring = zmalloc<char>(string_len);
937 if (!optstring) {
938 goto end;
939 }
940
941 for (i = 0; i < opt_count; i++) {
942 if (!long_options[i].name) {
943 /* Got to the trailing NULL element */
944 break;
945 }
946
947 if (long_options[i].val != '\0') {
948 optstring[str_pos++] = (char) long_options[i].val;
949 if (long_options[i].has_arg) {
950 optstring[str_pos++] = ':';
951 }
952 }
953 }
954
955 end:
956 return optstring;
957 }
958
959 /*
960 * Try to remove a hierarchy of empty directories, recursively. Don't unlink
961 * any file. Try to rmdir any empty directory within the hierarchy.
962 */
963 int utils_recursive_rmdir(const char *path)
964 {
965 int ret;
966 struct lttng_directory_handle *handle;
967
968 handle = lttng_directory_handle_create(NULL);
969 if (!handle) {
970 ret = -1;
971 goto end;
972 }
973 ret = lttng_directory_handle_remove_subdirectory(handle, path);
974 end:
975 lttng_directory_handle_put(handle);
976 return ret;
977 }
978
979 int utils_truncate_stream_file(int fd, off_t length)
980 {
981 int ret;
982 off_t lseek_ret;
983
984 ret = ftruncate(fd, length);
985 if (ret < 0) {
986 PERROR("ftruncate");
987 goto end;
988 }
989 lseek_ret = lseek(fd, length, SEEK_SET);
990 if (lseek_ret < 0) {
991 PERROR("lseek");
992 ret = -1;
993 goto end;
994 }
995 end:
996 return ret;
997 }
998
999 static const char *get_man_bin_path(void)
1000 {
1001 char *env_man_path = lttng_secure_getenv(DEFAULT_MAN_BIN_PATH_ENV);
1002
1003 if (env_man_path) {
1004 return env_man_path;
1005 }
1006
1007 return DEFAULT_MAN_BIN_PATH;
1008 }
1009
1010 int utils_show_help(int section, const char *page_name,
1011 const char *help_msg)
1012 {
1013 char section_string[8];
1014 const char *man_bin_path = get_man_bin_path();
1015 int ret = 0;
1016
1017 if (help_msg) {
1018 printf("%s", help_msg);
1019 goto end;
1020 }
1021
1022 /* Section integer -> section string */
1023 ret = sprintf(section_string, "%d", section);
1024 LTTNG_ASSERT(ret > 0 && ret < 8);
1025
1026 /*
1027 * Execute man pager.
1028 *
1029 * We provide -M to man here because LTTng-tools can
1030 * be installed outside /usr, in which case its man pages are
1031 * not located in the default /usr/share/man directory.
1032 */
1033 ret = execlp(man_bin_path, "man", "-M", MANPATH,
1034 section_string, page_name, NULL);
1035
1036 end:
1037 return ret;
1038 }
1039
1040 static
1041 int read_proc_meminfo_field(const char *field, uint64_t *value)
1042 {
1043 int ret;
1044 FILE *proc_meminfo;
1045 char name[PROC_MEMINFO_FIELD_MAX_NAME_LEN] = {};
1046
1047 proc_meminfo = fopen(PROC_MEMINFO_PATH, "r");
1048 if (!proc_meminfo) {
1049 PERROR("Failed to fopen() " PROC_MEMINFO_PATH);
1050 ret = -1;
1051 goto fopen_error;
1052 }
1053
1054 /*
1055 * Read the contents of /proc/meminfo line by line to find the right
1056 * field.
1057 */
1058 while (!feof(proc_meminfo)) {
1059 uint64_t value_kb;
1060
1061 ret = fscanf(proc_meminfo,
1062 "%" MAX_NAME_LEN_SCANF_IS_A_BROKEN_API "s %" SCNu64 " kB\n",
1063 name, &value_kb);
1064 if (ret == EOF) {
1065 /*
1066 * fscanf() returning EOF can indicate EOF or an error.
1067 */
1068 if (ferror(proc_meminfo)) {
1069 PERROR("Failed to parse " PROC_MEMINFO_PATH);
1070 }
1071 break;
1072 }
1073
1074 if (ret == 2 && strcmp(name, field) == 0) {
1075 /*
1076 * This number is displayed in kilo-bytes. Return the
1077 * number of bytes.
1078 */
1079 if (value_kb > UINT64_MAX / 1024) {
1080 ERR("Overflow on kb to bytes conversion");
1081 break;
1082 }
1083
1084 *value = value_kb * 1024;
1085 ret = 0;
1086 goto found;
1087 }
1088 }
1089 /* Reached the end of the file without finding the right field. */
1090 ret = -1;
1091
1092 found:
1093 fclose(proc_meminfo);
1094 fopen_error:
1095 return ret;
1096 }
1097
1098 /*
1099 * Returns an estimate of the number of bytes of memory available based on the
1100 * the information in `/proc/meminfo`. The number returned by this function is
1101 * a best guess.
1102 */
1103 int utils_get_memory_available(uint64_t *value)
1104 {
1105 return read_proc_meminfo_field(PROC_MEMINFO_MEMAVAILABLE_LINE, value);
1106 }
1107
1108 /*
1109 * Returns the total size of the memory on the system in bytes based on the
1110 * the information in `/proc/meminfo`.
1111 */
1112 int utils_get_memory_total(uint64_t *value)
1113 {
1114 return read_proc_meminfo_field(PROC_MEMINFO_MEMTOTAL_LINE, value);
1115 }
1116
1117 int utils_change_working_directory(const char *path)
1118 {
1119 int ret;
1120
1121 LTTNG_ASSERT(path);
1122
1123 DBG("Changing working directory to \"%s\"", path);
1124 ret = chdir(path);
1125 if (ret) {
1126 PERROR("Failed to change working directory to \"%s\"", path);
1127 goto end;
1128 }
1129
1130 /* Check for write access */
1131 if (access(path, W_OK)) {
1132 if (errno == EACCES) {
1133 /*
1134 * Do not treat this as an error since the permission
1135 * might change in the lifetime of the process
1136 */
1137 DBG("Working directory \"%s\" is not writable", path);
1138 } else {
1139 PERROR("Failed to check if working directory \"%s\" is writable",
1140 path);
1141 }
1142 }
1143
1144 end:
1145 return ret;
1146 }
1147
1148 enum lttng_error_code utils_user_id_from_name(const char *user_name, uid_t *uid)
1149 {
1150 struct passwd p, *pres;
1151 int ret;
1152 enum lttng_error_code ret_val = LTTNG_OK;
1153 char *buf = NULL;
1154 ssize_t buflen;
1155
1156 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1157 if (buflen < 0) {
1158 buflen = FALLBACK_USER_BUFLEN;
1159 }
1160
1161 buf = zmalloc<char>(buflen);
1162 if (!buf) {
1163 ret_val = LTTNG_ERR_NOMEM;
1164 goto end;
1165 }
1166
1167 for (;;) {
1168 ret = getpwnam_r(user_name, &p, buf, buflen, &pres);
1169 switch (ret) {
1170 case EINTR:
1171 continue;
1172 case ERANGE:
1173 buflen *= 2;
1174 free(buf);
1175 buf = zmalloc<char>(buflen);
1176 if (!buf) {
1177 ret_val = LTTNG_ERR_NOMEM;
1178 goto end;
1179 }
1180 continue;
1181 default:
1182 goto end_loop;
1183 }
1184 }
1185 end_loop:
1186
1187 switch (ret) {
1188 case 0:
1189 if (pres == NULL) {
1190 ret_val = LTTNG_ERR_USER_NOT_FOUND;
1191 } else {
1192 *uid = p.pw_uid;
1193 DBG("Lookup of tracker UID/VUID: name '%s' maps to uid %" PRId64,
1194 user_name, (int64_t) *uid);
1195 ret_val = LTTNG_OK;
1196 }
1197 break;
1198 case ENOENT:
1199 case ESRCH:
1200 case EBADF:
1201 case EPERM:
1202 ret_val = LTTNG_ERR_USER_NOT_FOUND;
1203 break;
1204 default:
1205 ret_val = LTTNG_ERR_NOMEM;
1206 }
1207 end:
1208 free(buf);
1209 return ret_val;
1210 }
1211
1212 enum lttng_error_code utils_group_id_from_name(
1213 const char *group_name, gid_t *gid)
1214 {
1215 struct group g, *gres;
1216 int ret;
1217 enum lttng_error_code ret_val = LTTNG_OK;
1218 char *buf = NULL;
1219 ssize_t buflen;
1220
1221 buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1222 if (buflen < 0) {
1223 buflen = FALLBACK_GROUP_BUFLEN;
1224 }
1225
1226 buf = zmalloc<char>(buflen);
1227 if (!buf) {
1228 ret_val = LTTNG_ERR_NOMEM;
1229 goto end;
1230 }
1231
1232 for (;;) {
1233 ret = getgrnam_r(group_name, &g, buf, buflen, &gres);
1234 switch (ret) {
1235 case EINTR:
1236 continue;
1237 case ERANGE:
1238 buflen *= 2;
1239 free(buf);
1240 buf = zmalloc<char>(buflen);
1241 if (!buf) {
1242 ret_val = LTTNG_ERR_NOMEM;
1243 goto end;
1244 }
1245 continue;
1246 default:
1247 goto end_loop;
1248 }
1249 }
1250 end_loop:
1251
1252 switch (ret) {
1253 case 0:
1254 if (gres == NULL) {
1255 ret_val = LTTNG_ERR_GROUP_NOT_FOUND;
1256 } else {
1257 *gid = g.gr_gid;
1258 DBG("Lookup of tracker GID/GUID: name '%s' maps to gid %" PRId64,
1259 group_name, (int64_t) *gid);
1260 ret_val = LTTNG_OK;
1261 }
1262 break;
1263 case ENOENT:
1264 case ESRCH:
1265 case EBADF:
1266 case EPERM:
1267 ret_val = LTTNG_ERR_GROUP_NOT_FOUND;
1268 break;
1269 default:
1270 ret_val = LTTNG_ERR_NOMEM;
1271 }
1272 end:
1273 free(buf);
1274 return ret_val;
1275 }
1276
1277 int utils_parse_unsigned_long_long(const char *str,
1278 unsigned long long *value)
1279 {
1280 int ret;
1281 char *endptr;
1282
1283 LTTNG_ASSERT(str);
1284 LTTNG_ASSERT(value);
1285
1286 errno = 0;
1287 *value = strtoull(str, &endptr, 10);
1288
1289 /* Conversion failed. Out of range? */
1290 if (errno != 0) {
1291 /* Don't print an error; allow the caller to log a better error. */
1292 DBG("Failed to parse string as unsigned long long number: string = '%s', errno = %d",
1293 str, errno);
1294 ret = -1;
1295 goto end;
1296 }
1297
1298 /* Not the end of the string or empty string. */
1299 if (*endptr || endptr == str) {
1300 DBG("Failed to parse string as unsigned long long number: string = '%s'",
1301 str);
1302 ret = -1;
1303 goto end;
1304 }
1305
1306 ret = 0;
1307
1308 end:
1309 return ret;
1310 }
This page took 0.056434 seconds and 4 git commands to generate.