shared: make timezone and locale enumeration and validation generic
This way we can reuse it other code thatn just localectl/localed + timedatectl/timedated.
This commit is contained in:
parent
a940778fb1
commit
7568345034
|
@ -727,6 +727,8 @@ libsystemd_shared_la_SOURCES = \
|
|||
src/shared/path-util.h \
|
||||
src/shared/time-util.c \
|
||||
src/shared/time-util.h \
|
||||
src/shared/locale-util.c \
|
||||
src/shared/locale-util.h \
|
||||
src/shared/hashmap.c \
|
||||
src/shared/hashmap.h \
|
||||
src/shared/siphash24.c \
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "path-util.h"
|
||||
#include "utf8.h"
|
||||
#include "def.h"
|
||||
#include "locale-util.h"
|
||||
|
||||
static bool arg_no_pager = false;
|
||||
static bool arg_ask_password = true;
|
||||
|
@ -177,192 +178,19 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int add_locales_from_archive(Set *locales) {
|
||||
/* Stolen from glibc... */
|
||||
|
||||
struct locarhead {
|
||||
uint32_t magic;
|
||||
/* Serial number. */
|
||||
uint32_t serial;
|
||||
/* Name hash table. */
|
||||
uint32_t namehash_offset;
|
||||
uint32_t namehash_used;
|
||||
uint32_t namehash_size;
|
||||
/* String table. */
|
||||
uint32_t string_offset;
|
||||
uint32_t string_used;
|
||||
uint32_t string_size;
|
||||
/* Table with locale records. */
|
||||
uint32_t locrectab_offset;
|
||||
uint32_t locrectab_used;
|
||||
uint32_t locrectab_size;
|
||||
/* MD5 sum hash table. */
|
||||
uint32_t sumhash_offset;
|
||||
uint32_t sumhash_used;
|
||||
uint32_t sumhash_size;
|
||||
};
|
||||
|
||||
struct namehashent {
|
||||
/* Hash value of the name. */
|
||||
uint32_t hashval;
|
||||
/* Offset of the name in the string table. */
|
||||
uint32_t name_offset;
|
||||
/* Offset of the locale record. */
|
||||
uint32_t locrec_offset;
|
||||
};
|
||||
|
||||
const struct locarhead *h;
|
||||
const struct namehashent *e;
|
||||
const void *p = MAP_FAILED;
|
||||
_cleanup_close_ int fd = -1;
|
||||
size_t sz = 0;
|
||||
struct stat st;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_error("Failed to open locale archive: %m");
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
log_error("fstat() failed: %m");
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
log_error("Archive file is not regular");
|
||||
r = -EBADMSG;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (st.st_size < (off_t) sizeof(struct locarhead)) {
|
||||
log_error("Archive has invalid size");
|
||||
r = -EBADMSG;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
log_error("Failed to map archive: %m");
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
h = (const struct locarhead *) p;
|
||||
if (h->magic != 0xde020109 ||
|
||||
h->namehash_offset + h->namehash_size > st.st_size ||
|
||||
h->string_offset + h->string_size > st.st_size ||
|
||||
h->locrectab_offset + h->locrectab_size > st.st_size ||
|
||||
h->sumhash_offset + h->sumhash_size > st.st_size) {
|
||||
log_error("Invalid archive file.");
|
||||
r = -EBADMSG;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
|
||||
for (i = 0; i < h->namehash_size; i++) {
|
||||
char *z;
|
||||
|
||||
if (e[i].locrec_offset == 0)
|
||||
continue;
|
||||
|
||||
if (!utf8_is_valid((char*) p + e[i].name_offset))
|
||||
continue;
|
||||
|
||||
z = strdup((char*) p + e[i].name_offset);
|
||||
if (!z) {
|
||||
r = log_oom();
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = set_consume(locales, z);
|
||||
if (r < 0) {
|
||||
log_error("Failed to add locale: %s", strerror(-r));
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
if (p != MAP_FAILED)
|
||||
munmap((void*) p, sz);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int add_locales_from_libdir (Set *locales) {
|
||||
_cleanup_closedir_ DIR *dir;
|
||||
struct dirent *entry;
|
||||
int r;
|
||||
|
||||
dir = opendir("/usr/lib/locale");
|
||||
if (!dir) {
|
||||
log_error("Failed to open locale directory: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
while ((entry = readdir(dir))) {
|
||||
char *z;
|
||||
|
||||
if (entry->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
if (ignore_file(entry->d_name))
|
||||
continue;
|
||||
|
||||
z = strdup(entry->d_name);
|
||||
if (!z)
|
||||
return log_oom();
|
||||
|
||||
r = set_consume(locales, z);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
log_error("Failed to add locale: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
if (errno > 0) {
|
||||
log_error("Failed to read locale directory: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int list_locales(sd_bus *bus, char **args, unsigned n) {
|
||||
_cleanup_set_free_ Set *locales;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int r;
|
||||
|
||||
locales = set_new(string_hash_func, string_compare_func);
|
||||
if (!locales)
|
||||
return log_oom();
|
||||
assert(args);
|
||||
|
||||
r = add_locales_from_archive(locales);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
r = get_locales(&l);
|
||||
if (r < 0) {
|
||||
log_error("Failed to read list of locales: %s", strerror(-r));
|
||||
return r;
|
||||
|
||||
r = add_locales_from_libdir(locales);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = set_get_strv(locales);
|
||||
if (!l)
|
||||
return log_oom();
|
||||
|
||||
strv_sort(l);
|
||||
}
|
||||
|
||||
pager_open_if_enabled();
|
||||
|
||||
strv_print(l);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "bus-error.h"
|
||||
#include "bus-message.h"
|
||||
#include "event-util.h"
|
||||
#include "locale-util.h"
|
||||
|
||||
enum {
|
||||
/* We don't list LC_ALL here on purpose. People should be
|
||||
|
@ -848,7 +849,7 @@ static int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_
|
|||
k = strlen(names[p]);
|
||||
if (startswith(*i, names[p]) &&
|
||||
(*i)[k] == '=' &&
|
||||
string_is_safe((*i) + k + 1)) {
|
||||
locale_is_valid((*i) + k + 1)) {
|
||||
valid = true;
|
||||
passed[p] = true;
|
||||
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "set.h"
|
||||
#include "util.h"
|
||||
#include "utf8.h"
|
||||
#include "strv.h"
|
||||
|
||||
#include "locale-util.h"
|
||||
|
||||
static int add_locales_from_archive(Set *locales) {
|
||||
/* Stolen from glibc... */
|
||||
|
||||
struct locarhead {
|
||||
uint32_t magic;
|
||||
/* Serial number. */
|
||||
uint32_t serial;
|
||||
/* Name hash table. */
|
||||
uint32_t namehash_offset;
|
||||
uint32_t namehash_used;
|
||||
uint32_t namehash_size;
|
||||
/* String table. */
|
||||
uint32_t string_offset;
|
||||
uint32_t string_used;
|
||||
uint32_t string_size;
|
||||
/* Table with locale records. */
|
||||
uint32_t locrectab_offset;
|
||||
uint32_t locrectab_used;
|
||||
uint32_t locrectab_size;
|
||||
/* MD5 sum hash table. */
|
||||
uint32_t sumhash_offset;
|
||||
uint32_t sumhash_used;
|
||||
uint32_t sumhash_size;
|
||||
};
|
||||
|
||||
struct namehashent {
|
||||
/* Hash value of the name. */
|
||||
uint32_t hashval;
|
||||
/* Offset of the name in the string table. */
|
||||
uint32_t name_offset;
|
||||
/* Offset of the locale record. */
|
||||
uint32_t locrec_offset;
|
||||
};
|
||||
|
||||
const struct locarhead *h;
|
||||
const struct namehashent *e;
|
||||
const void *p = MAP_FAILED;
|
||||
_cleanup_close_ int fd = -1;
|
||||
size_t sz = 0;
|
||||
struct stat st;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -EBADMSG;
|
||||
|
||||
if (st.st_size < (off_t) sizeof(struct locarhead))
|
||||
return -EBADMSG;
|
||||
|
||||
p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
h = (const struct locarhead *) p;
|
||||
if (h->magic != 0xde020109 ||
|
||||
h->namehash_offset + h->namehash_size > st.st_size ||
|
||||
h->string_offset + h->string_size > st.st_size ||
|
||||
h->locrectab_offset + h->locrectab_size > st.st_size ||
|
||||
h->sumhash_offset + h->sumhash_size > st.st_size) {
|
||||
r = -EBADMSG;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
|
||||
for (i = 0; i < h->namehash_size; i++) {
|
||||
char *z;
|
||||
|
||||
if (e[i].locrec_offset == 0)
|
||||
continue;
|
||||
|
||||
if (!utf8_is_valid((char*) p + e[i].name_offset))
|
||||
continue;
|
||||
|
||||
z = strdup((char*) p + e[i].name_offset);
|
||||
if (!z) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = set_consume(locales, z);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
if (p != MAP_FAILED)
|
||||
munmap((void*) p, sz);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int add_locales_from_libdir (Set *locales) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
struct dirent *entry;
|
||||
int r;
|
||||
|
||||
dir = opendir("/usr/lib/locale");
|
||||
if (!dir)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
FOREACH_DIRENT(entry, dir, return -errno) {
|
||||
char *z;
|
||||
|
||||
if (entry->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
z = strdup(entry->d_name);
|
||||
if (!z)
|
||||
return -ENOMEM;
|
||||
|
||||
r = set_consume(locales, z);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_locales(char ***ret) {
|
||||
_cleanup_set_free_ Set *locales = NULL;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int r;
|
||||
|
||||
locales = set_new(string_hash_func, string_compare_func);
|
||||
if (!locales)
|
||||
return -ENOMEM;
|
||||
|
||||
r = add_locales_from_archive(locales);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
r = add_locales_from_libdir(locales);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = set_get_strv(locales);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
strv_sort(l);
|
||||
|
||||
*ret = l;
|
||||
l = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool locale_is_valid(const char *name) {
|
||||
|
||||
if (isempty(name))
|
||||
return false;
|
||||
|
||||
if (strlen(name) >= 128)
|
||||
return false;
|
||||
|
||||
if (!utf8_is_valid(name))
|
||||
return false;
|
||||
|
||||
if (!filename_is_safe(name))
|
||||
return false;
|
||||
|
||||
if (!string_is_safe(name))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int get_locales(char ***l);
|
||||
bool locale_is_valid(const char *name);
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "time-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
usec_t now(clockid_t clock_id) {
|
||||
struct timespec ts;
|
||||
|
@ -826,3 +827,105 @@ bool ntp_synced(void) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
int get_timezones(char ***ret) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_strv_free_ char **zones = NULL;
|
||||
size_t n_zones = 0, n_allocated = 0;
|
||||
|
||||
assert(ret);
|
||||
|
||||
zones = strv_new("UTC", NULL);
|
||||
if (!zones)
|
||||
return -ENOMEM;
|
||||
|
||||
n_allocated = 2;
|
||||
n_zones = 1;
|
||||
|
||||
f = fopen("/usr/share/zoneinfo/zone.tab", "re");
|
||||
if (f) {
|
||||
char l[LINE_MAX];
|
||||
|
||||
FOREACH_LINE(l, f, return -errno) {
|
||||
char *p, *w;
|
||||
size_t k;
|
||||
|
||||
p = strstrip(l);
|
||||
|
||||
if (isempty(p) || *p == '#')
|
||||
continue;
|
||||
|
||||
/* Skip over country code */
|
||||
p += strcspn(p, WHITESPACE);
|
||||
p += strspn(p, WHITESPACE);
|
||||
|
||||
/* Skip over coordinates */
|
||||
p += strcspn(p, WHITESPACE);
|
||||
p += strspn(p, WHITESPACE);
|
||||
|
||||
/* Found timezone name */
|
||||
k = strcspn(p, WHITESPACE);
|
||||
if (k <= 0)
|
||||
continue;
|
||||
|
||||
w = strndup(p, k);
|
||||
if (!w)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!GREEDY_REALLOC(zones, n_allocated, n_zones + 2)) {
|
||||
free(w);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
zones[n_zones++] = w;
|
||||
zones[n_zones] = NULL;
|
||||
}
|
||||
|
||||
strv_sort(zones);
|
||||
|
||||
} else if (errno != ENOENT)
|
||||
return -errno;
|
||||
|
||||
*ret = zones;
|
||||
zones = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool timezone_is_valid(const char *name) {
|
||||
bool slash = false;
|
||||
const char *p, *t;
|
||||
struct stat st;
|
||||
|
||||
if (!name || *name == 0 || *name == '/')
|
||||
return false;
|
||||
|
||||
for (p = name; *p; p++) {
|
||||
if (!(*p >= '0' && *p <= '9') &&
|
||||
!(*p >= 'a' && *p <= 'z') &&
|
||||
!(*p >= 'A' && *p <= 'Z') &&
|
||||
!(*p == '-' || *p == '_' || *p == '+' || *p == '/'))
|
||||
return false;
|
||||
|
||||
if (*p == '/') {
|
||||
|
||||
if (slash)
|
||||
return false;
|
||||
|
||||
slash = true;
|
||||
} else
|
||||
slash = false;
|
||||
}
|
||||
|
||||
if (slash)
|
||||
return false;
|
||||
|
||||
t = strappenda("/usr/share/zoneinfo/", name);
|
||||
if (stat(t, &st) < 0)
|
||||
return false;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -95,3 +95,6 @@ int parse_sec(const char *t, usec_t *usec);
|
|||
int parse_nsec(const char *t, nsec_t *nsec);
|
||||
|
||||
bool ntp_synced(void);
|
||||
|
||||
int get_timezones(char ***l);
|
||||
bool timezone_is_valid(const char *name);
|
||||
|
|
|
@ -355,69 +355,19 @@ static int set_ntp(sd_bus *bus, char **args, unsigned n) {
|
|||
}
|
||||
|
||||
static int list_timezones(sd_bus *bus, char **args, unsigned n) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_strv_free_ char **zones = NULL;
|
||||
size_t n_zones = 0;
|
||||
int r;
|
||||
|
||||
assert(args);
|
||||
assert(n == 1);
|
||||
|
||||
f = fopen("/usr/share/zoneinfo/zone.tab", "re");
|
||||
if (!f) {
|
||||
log_error("Failed to open time zone database: %m");
|
||||
return -errno;
|
||||
r = get_timezones(&zones);
|
||||
if (r < 0) {
|
||||
log_error("Failed to read list of time zones: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char l[LINE_MAX], *p, **z, *w;
|
||||
size_t k;
|
||||
|
||||
if (!fgets(l, sizeof(l), f)) {
|
||||
if (feof(f))
|
||||
break;
|
||||
|
||||
log_error("Failed to read time zone database: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
p = strstrip(l);
|
||||
|
||||
if (isempty(p) || *p == '#')
|
||||
continue;
|
||||
|
||||
/* Skip over country code */
|
||||
p += strcspn(p, WHITESPACE);
|
||||
p += strspn(p, WHITESPACE);
|
||||
|
||||
/* Skip over coordinates */
|
||||
p += strcspn(p, WHITESPACE);
|
||||
p += strspn(p, WHITESPACE);
|
||||
|
||||
/* Found timezone name */
|
||||
k = strcspn(p, WHITESPACE);
|
||||
if (k <= 0)
|
||||
continue;
|
||||
|
||||
w = strndup(p, k);
|
||||
if (!w)
|
||||
return log_oom();
|
||||
|
||||
z = realloc(zones, sizeof(char*) * (n_zones + 2));
|
||||
if (!z) {
|
||||
free(w);
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
zones = z;
|
||||
zones[n_zones++] = w;
|
||||
}
|
||||
|
||||
if (zones)
|
||||
zones[n_zones] = NULL;
|
||||
|
||||
pager_open_if_enabled();
|
||||
|
||||
strv_sort(zones);
|
||||
strv_print(zones);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/capability.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
#include "sd-messages.h"
|
||||
|
@ -58,54 +59,6 @@ static void context_free(Context *c, sd_bus *bus) {
|
|||
bus_verify_polkit_async_registry_free(bus, c->polkit_registry);
|
||||
}
|
||||
|
||||
static bool valid_timezone(const char *name) {
|
||||
const char *p;
|
||||
char *t;
|
||||
bool slash = false;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
assert(name);
|
||||
|
||||
if (*name == '/' || *name == 0)
|
||||
return false;
|
||||
|
||||
for (p = name; *p; p++) {
|
||||
if (!(*p >= '0' && *p <= '9') &&
|
||||
!(*p >= 'a' && *p <= 'z') &&
|
||||
!(*p >= 'A' && *p <= 'Z') &&
|
||||
!(*p == '-' || *p == '_' || *p == '+' || *p == '/'))
|
||||
return false;
|
||||
|
||||
if (*p == '/') {
|
||||
|
||||
if (slash)
|
||||
return false;
|
||||
|
||||
slash = true;
|
||||
} else
|
||||
slash = false;
|
||||
}
|
||||
|
||||
if (slash)
|
||||
return false;
|
||||
|
||||
t = strappend("/usr/share/zoneinfo/", name);
|
||||
if (!t)
|
||||
return false;
|
||||
|
||||
r = stat(t, &st);
|
||||
free(t);
|
||||
|
||||
if (r < 0)
|
||||
return false;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int context_read_data(Context *c) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
int r;
|
||||
|
@ -502,7 +455,7 @@ static int method_set_timezone(sd_bus *bus, sd_bus_message *m, void *userdata, s
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!valid_timezone(z))
|
||||
if (!timezone_is_valid(z))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid time zone '%s'", z);
|
||||
|
||||
if (streq_ptr(z, c->zone))
|
||||
|
@ -737,8 +690,6 @@ static int method_set_ntp(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus
|
|||
return sd_bus_reply_method_return(m, NULL);
|
||||
}
|
||||
|
||||
#include <sys/capability.h>
|
||||
|
||||
static const sd_bus_vtable timedate_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
|
|
Loading…
Reference in New Issue