+end:
+ closeret = closedir(dir);
+ if (closeret) {
+ PERROR("closedir");
+ }
+ if (is_empty) {
+ DBG3("Attempting rmdir %s", path);
+ ret = rmdir(path);
+ }
+ return ret;
+}
+
+LTTNG_HIDDEN
+int utils_truncate_stream_file(int fd, off_t length)
+{
+ int ret;
+ off_t lseek_ret;
+
+ ret = ftruncate(fd, length);
+ if (ret < 0) {
+ PERROR("ftruncate");
+ goto end;
+ }
+ lseek_ret = lseek(fd, length, SEEK_SET);
+ if (lseek_ret < 0) {
+ PERROR("lseek");
+ ret = -1;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+static const char *get_man_bin_path(void)
+{
+ char *env_man_path = lttng_secure_getenv(DEFAULT_MAN_BIN_PATH_ENV);
+
+ if (env_man_path) {
+ return env_man_path;
+ }
+
+ return DEFAULT_MAN_BIN_PATH;
+}
+
+LTTNG_HIDDEN
+int utils_show_help(int section, const char *page_name,
+ const char *help_msg)
+{
+ char section_string[8];
+ const char *man_bin_path = get_man_bin_path();
+ int ret = 0;
+
+ if (help_msg) {
+ printf("%s", help_msg);
+ goto end;
+ }
+
+ /* Section integer -> section string */
+ ret = sprintf(section_string, "%d", section);
+ assert(ret > 0 && ret < 8);
+
+ /*
+ * Execute man pager.
+ *
+ * We provide -M to man here because LTTng-tools can
+ * be installed outside /usr, in which case its man pages are
+ * not located in the default /usr/share/man directory.
+ */
+ ret = execlp(man_bin_path, "man", "-M", MANPATH,
+ section_string, page_name, NULL);
+
+end:
+ return ret;
+}
+
+static
+int read_proc_meminfo_field(const char *field, size_t *value)
+{
+ int ret;
+ FILE *proc_meminfo;
+ char name[PROC_MEMINFO_FIELD_MAX_NAME_LEN] = {};
+
+ proc_meminfo = fopen(PROC_MEMINFO_PATH, "r");
+ if (!proc_meminfo) {
+ PERROR("Failed to fopen() " PROC_MEMINFO_PATH);
+ ret = -1;
+ goto fopen_error;
+ }
+
+ /*
+ * Read the contents of /proc/meminfo line by line to find the right
+ * field.
+ */
+ while (!feof(proc_meminfo)) {
+ unsigned long value_kb;
+
+ ret = fscanf(proc_meminfo,
+ "%" MAX_NAME_LEN_SCANF_IS_A_BROKEN_API "s %lu kB\n",
+ name, &value_kb);
+ if (ret == EOF) {
+ /*
+ * fscanf() returning EOF can indicate EOF or an error.
+ */
+ if (ferror(proc_meminfo)) {
+ PERROR("Failed to parse " PROC_MEMINFO_PATH);
+ }
+ break;
+ }
+
+ if (ret == 2 && strcmp(name, field) == 0) {
+ /*
+ * This number is displayed in kilo-bytes. Return the
+ * number of bytes.
+ */
+ *value = ((size_t) value_kb) * 1024;
+ ret = 0;
+ goto found;
+ }
+ }
+ /* Reached the end of the file without finding the right field. */
+ ret = -1;
+
+found:
+ fclose(proc_meminfo);
+fopen_error:
+ return ret;
+}
+
+/*
+ * Returns an estimate of the number of bytes of memory available based on the
+ * the information in `/proc/meminfo`. The number returned by this function is
+ * a best guess.
+ */
+LTTNG_HIDDEN
+int utils_get_memory_available(size_t *value)
+{
+ return read_proc_meminfo_field(PROC_MEMINFO_MEMAVAILABLE_LINE, value);
+}
+
+/*
+ * Returns the total size of the memory on the system in bytes based on the
+ * the information in `/proc/meminfo`.
+ */
+LTTNG_HIDDEN
+int utils_get_memory_total(size_t *value)
+{
+ return read_proc_meminfo_field(PROC_MEMINFO_MEMTOTAL_LINE, value);