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