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