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