return ts;
}
+dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
+ int64_t delta;
+ assert(ts);
+
+ ts->realtime = u;
+
+ if (u == 0)
+ ts->monotonic = 0;
+ else {
+ delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
+
+ ts->monotonic = now(CLOCK_MONOTONIC);
+
+ if ((int64_t) ts->monotonic > delta)
+ ts->monotonic -= delta;
+ else
+ ts->monotonic = 0;
+ }
+
+ return ts;
+}
+
usec_t timespec_load(const struct timespec *ts) {
assert(ts);
if (streq(s, "tty")) {
free(s);
- return get_ctty(r, NULL);
+ return get_ctty(0, NULL, r);
}
*r = s;
return 0;
}
-int get_ctty_devnr(dev_t *d) {
+int get_ctty_devnr(pid_t pid, dev_t *d) {
int k;
- char line[LINE_MAX], *p;
+ char line[LINE_MAX], *p, *fn;
unsigned long ttynr;
FILE *f;
- if (!(f = fopen("/proc/self/stat", "r")))
+ if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
+ return -ENOMEM;
+
+ f = fopen(fn, "re");
+ free(fn);
+ if (!f)
return -errno;
- if (!(fgets(line, sizeof(line), f))) {
+ if (!fgets(line, sizeof(line), f)) {
k = -errno;
fclose(f);
return k;
fclose(f);
- if (!(p = strrchr(line, ')')))
+ p = strrchr(line, ')');
+ if (!p)
return -EIO;
p++;
return 0;
}
-int get_ctty(char **r, dev_t *_devnr) {
+int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
int k;
char fn[PATH_MAX], *s, *b, *p;
dev_t devnr;
assert(r);
- if ((k = get_ctty_devnr(&devnr)) < 0)
+ k = get_ctty_devnr(pid, &devnr);
+ if (k < 0)
return k;
snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
if (startswith(tty, "/dev/"))
tty += 5;
- return startswith(tty, "tty") &&
- tty[3] >= '0' && tty[3] <= '9';
+ return vtnr_from_tty(tty) >= 0;
+}
+
+int vtnr_from_tty(const char *tty) {
+ int i, r;
+
+ assert(tty);
+
+ if (startswith(tty, "/dev/"))
+ tty += 5;
+
+ if (!startswith(tty, "tty") )
+ return -EINVAL;
+
+ if (tty[3] < '0' || tty[3] > '9')
+ return -EINVAL;
+
+ r = safe_atoi(tty+3, &i);
+ if (r < 0)
+ return r;
+
+ if (i < 0 || i > 63)
+ return -EINVAL;
+
+ return i;
}
const char *default_term_for_tty(const char *tty) {
return r;
}
-bool hwclock_is_localtime(void) {
+int hwclock_is_localtime(void) {
FILE *f;
- char line[LINE_MAX];
bool local = false;
/*
* The third line of adjtime is "UTC" or "LOCAL" or nothing.
* # /etc/adjtime
- * 0.0 0 0.0
+ * 0.0 0 0
* 0
* UTC
*/
f = fopen("/etc/adjtime", "re");
if (f) {
- if (fgets(line, sizeof(line), f) &&
- fgets(line, sizeof(line), f) &&
- fgets(line, sizeof(line), f) ) {
- if (!strcmp(line, "LOCAL\n"))
- local = true;
- }
+ char line[LINE_MAX];
+ bool b;
+
+ b = fgets(line, sizeof(line), f) &&
+ fgets(line, sizeof(line), f) &&
+ fgets(line, sizeof(line), f);
+
fclose(f);
- }
+
+ if (!b)
+ return -EIO;
+
+
+ truncate_nl(line);
+ local = streq(line, "LOCAL");
+
+ } else if (errno != -ENOENT)
+ return -errno;
+
return local;
}
int hwclock_apply_localtime_delta(void) {
const struct timeval *tv_null = NULL;
- struct timeval tv;
+ struct timespec ts;
struct tm *tm;
int minuteswest;
struct timezone tz;
- gettimeofday(&tv, NULL);
- tm = localtime(&tv.tv_sec);
+ assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
+ assert_se(tm = localtime(&ts.tv_sec));
minuteswest = tm->tm_gmtoff / 60;
tz.tz_minuteswest = -minuteswest;
*/
if (settimeofday(tv_null, &tz) < 0)
return -errno;
- else
- return minuteswest;
+
+ return minuteswest;
+}
+
+int hwclock_reset_localtime_delta(void) {
+ const struct timeval *tv_null = NULL;
+ struct timezone tz;
+
+ tz.tz_minuteswest = 0;
+ tz.tz_dsttime = 0; /* DST_NONE*/
+
+ if (settimeofday(tv_null, &tz) < 0)
+ return -errno;
+
+ return 0;
}
int hwclock_get_time(struct tm *tm) {
int fd;
int err = 0;
+ assert(tm);
+
fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
if (fd < 0)
return -errno;
+
+ /* This leaves the timezone fields of struct tm
+ * uninitialized! */
if (ioctl(fd, RTC_RD_TIME, tm) < 0)
err = -errno;
- close(fd);
+
+ /* We don't now daylight saving, so we reset this in order not
+ * to confused mktime(). */
+ tm->tm_isdst = -1;
+
+ close_nointr_nofail(fd);
return err;
}
int fd;
int err = 0;
+ assert(tm);
+
fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
if (fd < 0)
return -errno;
+
if (ioctl(fd, RTC_SET_TIME, tm) < 0)
err = -errno;
- close(fd);
+
+ close_nointr_nofail(fd);
return err;
}
return r;
}
+int audit_session_from_pid(pid_t pid, uint32_t *id) {
+ char *p, *s;
+ uint32_t u;
+ int r;
+
+ assert(pid >= 1);
+ assert(id);
+
+ if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
+ return -ENOENT;
+
+ if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
+ return -ENOMEM;
+
+ r = read_one_line_file(p, &s);
+ free(p);
+ if (r < 0)
+ return r;
+
+ r = safe_atou32(s, &u);
+ free(s);
+
+ if (r < 0)
+ return r;
+
+ if (u == (uint32_t) -1 || u <= 0)
+ return -ENOENT;
+
+ *id = u;
+ return 0;
+}
+
+bool display_is_local(const char *display) {
+ assert(display);
+
+ return
+ display[0] == ':' &&
+ display[1] >= '0' &&
+ display[1] <= '9';
+}
+
+int socket_from_display(const char *display, char **path) {
+ size_t k;
+ char *f, *c;
+
+ assert(display);
+ assert(path);
+
+ if (!display_is_local(display))
+ return -EINVAL;
+
+ k = strspn(display+1, "0123456789");
+
+ f = new(char, sizeof("/tmp/.X11-unix/X") + k);
+ if (!f)
+ return -ENOMEM;
+
+ c = stpcpy(f, "/tmp/.X11-unix/X");
+ memcpy(c, display+1, k);
+ c[k] = 0;
+
+ *path = f;
+
+ return 0;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",