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