+static uint64_t get_reaper_start_time(pid_t pid)
+{
+ int ret;
+ FILE *f;
+ uint64_t starttime;
+ /* strlen("/proc/") = 6
+ * +
+ * LXCFS_NUMSTRLEN64
+ * +
+ * strlen("/stat") = 5
+ * +
+ * \0 = 1
+ * */
+#define __PROC_PID_STAT_LEN (6 + LXCFS_NUMSTRLEN64 + 5 + 1)
+ char path[__PROC_PID_STAT_LEN];
+ pid_t qpid;
+
+ qpid = lookup_initpid_in_store(pid);
+ if (qpid <= 0) {
+ /* Caller can check for EINVAL on 0. */
+ errno = EINVAL;
+ return 0;
+ }
+
+ ret = snprintf(path, __PROC_PID_STAT_LEN, "/proc/%d/stat", qpid);
+ if (ret < 0 || ret >= __PROC_PID_STAT_LEN) {
+ /* Caller can check for EINVAL on 0. */
+ errno = EINVAL;
+ return 0;
+ }
+
+ f = fopen(path, "r");
+ if (!f) {
+ /* Caller can check for EINVAL on 0. */
+ errno = EINVAL;
+ return 0;
+ }
+
+ /* Note that the *scanf() argument supression requires that length
+ * modifiers such as "l" are omitted. Otherwise some compilers will yell
+ * at us. It's like telling someone you're not married and then asking
+ * if you can bring your wife to the party.
+ */
+ ret = fscanf(f, "%*d " /* (1) pid %d */
+ "%*s " /* (2) comm %s */
+ "%*c " /* (3) state %c */
+ "%*d " /* (4) ppid %d */
+ "%*d " /* (5) pgrp %d */
+ "%*d " /* (6) session %d */
+ "%*d " /* (7) tty_nr %d */
+ "%*d " /* (8) tpgid %d */
+ "%*u " /* (9) flags %u */
+ "%*u " /* (10) minflt %lu */
+ "%*u " /* (11) cminflt %lu */
+ "%*u " /* (12) majflt %lu */
+ "%*u " /* (13) cmajflt %lu */
+ "%*u " /* (14) utime %lu */
+ "%*u " /* (15) stime %lu */
+ "%*d " /* (16) cutime %ld */
+ "%*d " /* (17) cstime %ld */
+ "%*d " /* (18) priority %ld */
+ "%*d " /* (19) nice %ld */
+ "%*d " /* (20) num_threads %ld */
+ "%*d " /* (21) itrealvalue %ld */
+ "%" PRIu64, /* (22) starttime %llu */
+ &starttime);
+ if (ret != 1) {
+ fclose(f);
+ /* Caller can check for EINVAL on 0. */
+ errno = EINVAL;
+ return 0;
+ }
+
+ fclose(f);
+
+ errno = 0;
+ return starttime;
+}
+
+static uint64_t get_reaper_start_time_in_sec(pid_t pid)
+{
+ uint64_t clockticks;
+ int64_t ticks_per_sec;
+
+ clockticks = get_reaper_start_time(pid);
+ if (clockticks == 0 && errno == EINVAL) {
+ lxcfs_debug("failed to retrieve start time of pid %d\n", pid);
+ return 0;
+ }
+
+ ticks_per_sec = sysconf(_SC_CLK_TCK);
+ if (ticks_per_sec < 0 && errno == EINVAL) {
+ lxcfs_debug(
+ "%s\n",
+ "failed to determine number of clock ticks in a second");
+ return 0;
+ }
+
+ return (clockticks /= ticks_per_sec);
+}
+
+static uint64_t get_reaper_age(pid_t pid)
+{
+ uint64_t procstart, uptime, procage;
+
+ /* We need to substract the time the process has started since system
+ * boot minus the time when the system has started to get the actual
+ * reaper age.
+ */
+ procstart = get_reaper_start_time_in_sec(pid);
+ procage = procstart;
+ if (procstart > 0) {
+ int ret;
+ struct timespec spec;
+
+ ret = clock_gettime(CLOCK_BOOTTIME, &spec);
+ if (ret < 0)
+ return 0;
+ /* We could make this more precise here by using the tv_nsec
+ * field in the timespec struct and convert it to milliseconds
+ * and then create a double for the seconds and milliseconds but
+ * that seems more work than it is worth.
+ */
+ uptime = spec.tv_sec;
+ procage = uptime - procstart;
+ }
+
+ return procage;
+}
+
+static uint64_t get_reaper_btime(pid)
+{
+ int ret;
+ struct sysinfo sys;
+ uint64_t procstart;
+ uint64_t uptime;
+
+ ret = sysinfo(&sys);
+ if (ret < 0) {
+ lxcfs_debug("%s\n", "failed to retrieve system information");
+ return 0;
+ }
+
+ uptime = (uint64_t)time(NULL) - (uint64_t)sys.uptime;
+ procstart = get_reaper_start_time_in_sec(pid);
+ return uptime + procstart;
+}
+
+#define CPUALL_MAX_SIZE (BUF_RESERVE_SIZE / 2)