static int read_distro_hostname(char **hn) { #if defined(TARGET_ARCH) || defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA) int r; _cleanup_fclose_ FILE *f = NULL; assert(hn); f = fopen(FILENAME, "re"); if (!f) return -errno; for (;;) { char line[LINE_MAX]; char *s, *k; if (!fgets(line, sizeof(line), f)) { if (feof(f)) break; r = -errno; goto finish; } s = strstrip(line); if (!startswith_no_case(s, "HOSTNAME=")) continue; k = strdup(s+9); if (!k) { r = -ENOMEM; goto finish; } hostname_cleanup(k); if (isempty(k)) { free(k); r = -ENOENT; goto finish; } *hn = k; r = 0; goto finish; } r = -ENOENT; finish: return r; #elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) return read_and_strip_hostname(FILENAME, hn); #else return -ENOENT; #endif }
static int remove_boot_efi(const char *esp_path) { char *p; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r, c = 0; p = strjoina(esp_path, "/EFI/Boot"); d = opendir(p); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open directory \"%s\": %m", p); } while ((de = readdir(d))) { _cleanup_close_ int fd = -1; _cleanup_free_ char *v = NULL; if (de->d_name[0] == '.') continue; if (!endswith_no_case(de->d_name, ".efi")) continue; if (!startswith_no_case(de->d_name, "Boot")) continue; fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); r = get_file_version(fd, &v); if (r < 0) return r; if (r > 0 && startswith(v, "systemd-boot ")) { r = unlinkat(dirfd(d), de->d_name, 0); if (r < 0) return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name); log_info("Removed \"%s/%s\".", p, de->d_name); } c++; } return c; }
static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) { char *p; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0, c = 0; p = strjoina(esp_path, "/", path); d = opendir(p); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to read \"%s\": %m", p); } while ((de = readdir(d))) { _cleanup_close_ int fd = -1; _cleanup_free_ char *v = NULL; if (de->d_name[0] == '.') continue; if (!endswith_no_case(de->d_name, ".efi")) continue; if (prefix && !startswith_no_case(de->d_name, prefix)) continue; fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); r = get_file_version(fd, &v); if (r < 0) return r; if (r > 0) printf(" File: └─/%s/%s (%s)\n", path, de->d_name, v); else printf(" File: └─/%s/%s\n", path, de->d_name); c++; } return c; }
int dns_type_from_string(const char *s) { const struct dns_type_name *sc; assert(s); sc = lookup_dns_type(s, strlen(s)); if (sc) return sc->id; s = startswith_no_case(s, "TYPE"); if (s) { unsigned x; if (safe_atou(s, &x) >= 0 && x <= UINT16_MAX) return (int) x; } return _DNS_TYPE_INVALID; }
static int parse_weekdays(const char **p, CalendarSpec *c) { static const struct { const char *name; const int nr; } day_nr[] = { { "Monday", 0 }, { "Mon", 0 }, { "Tuesday", 1 }, { "Tue", 1 }, { "Wednesday", 2 }, { "Wed", 2 }, { "Thursday", 3 }, { "Thu", 3 }, { "Friday", 4 }, { "Fri", 4 }, { "Saturday", 5 }, { "Sat", 5 }, { "Sunday", 6 }, { "Sun", 6 } }; int l = -1; bool first = true; assert(p); assert(*p); assert(c); for (;;) { unsigned i; if (!first && **p == ' ') return 0; for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; if (!startswith_no_case(*p, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if ((*p)[skip] != '-' && (*p)[skip] != ',' && (*p)[skip] != ' ' && (*p)[skip] != 0) return -EINVAL; c->weekdays_bits |= 1 << day_nr[i].nr; if (l >= 0) { int j; if (l > day_nr[i].nr) return -EINVAL; for (j = l + 1; j < day_nr[i].nr; j++) c->weekdays_bits |= 1 << j; } *p += skip; break; } /* Couldn't find this prefix, so let's assume the weekday was not specified and let's continue with the date */ if (i >= ELEMENTSOF(day_nr)) return first ? 0 : -EINVAL; /* We reached the end of the string */ if (**p == 0) return 0; /* We reached the end of the weekday spec part */ if (**p == ' ') { *p += strspn(*p, " "); return 0; } if (**p == '-') { if (l >= 0) return -EINVAL; l = day_nr[i].nr; } else l = -1; *p += 1; first = false; } }
static int parse_weekdays(const char **p, CalendarSpec *c) { static const struct { const char *name; const int nr; } day_nr[] = { { "Monday", 0 }, { "Mon", 0 }, { "Tuesday", 1 }, { "Tue", 1 }, { "Wednesday", 2 }, { "Wed", 2 }, { "Thursday", 3 }, { "Thu", 3 }, { "Friday", 4 }, { "Fri", 4 }, { "Saturday", 5 }, { "Sat", 5 }, { "Sunday", 6 }, { "Sun", 6 } }; int l = -1; bool first = true; assert(p); assert(*p); assert(c); for (;;) { unsigned i; for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; if (!startswith_no_case(*p, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if (!IN_SET((*p)[skip], 0, '-', '.', ',', ' ')) return -EINVAL; c->weekdays_bits |= 1 << day_nr[i].nr; if (l >= 0) { int j; if (l > day_nr[i].nr) return -EINVAL; for (j = l + 1; j < day_nr[i].nr; j++) c->weekdays_bits |= 1 << j; } *p += skip; break; } /* Couldn't find this prefix, so let's assume the weekday was not specified and let's continue with the date */ if (i >= ELEMENTSOF(day_nr)) return first ? 0 : -EINVAL; /* We reached the end of the string */ if (**p == 0) return 0; /* We reached the end of the weekday spec part */ if (**p == ' ') { *p += strspn(*p, " "); return 0; } if (**p == '.') { if (l >= 0) return -EINVAL; if ((*p)[1] != '.') return -EINVAL; l = day_nr[i].nr; *p += 2; /* Support ranges with "-" for backwards compatibility */ } else if (**p == '-') { if (l >= 0) return -EINVAL; l = day_nr[i].nr; *p += 1; } else if (**p == ',') { l = -1; *p += 1; } /* Allow a trailing comma but not an open range */ if (IN_SET(**p, 0, ' ')) { *p += strspn(*p, " "); return l < 0 ? 0 : -EINVAL; } first = false; } }
int parse_timestamp(const char *t, usec_t *usec) { static const struct { const char *name; const int nr; } day_nr[] = { { "Sunday", 0 }, { "Sun", 0 }, { "Monday", 1 }, { "Mon", 1 }, { "Tuesday", 2 }, { "Tue", 2 }, { "Wednesday", 3 }, { "Wed", 3 }, { "Thursday", 4 }, { "Thu", 4 }, { "Friday", 5 }, { "Fri", 5 }, { "Saturday", 6 }, { "Sat", 6 }, }; const char *k; struct tm tm, copy; time_t x; usec_t plus = 0, minus = 0, ret; int r, weekday = -1; unsigned i; /* * Allowed syntaxes: * * 2012-09-22 16:34:22 * 2012-09-22 16:34 (seconds will be set to 0) * 2012-09-22 (time will be set to 00:00:00) * 16:34:22 (date will be set to today) * 16:34 (date will be set to today, seconds to 0) * now * yesterday (time is set to 00:00:00) * today (time is set to 00:00:00) * tomorrow (time is set to 00:00:00) * +5min * -5days * */ assert(t); assert(usec); x = time(NULL); localtime_r(&x, &tm); tm.tm_isdst = -1; if (streq(t, "now")) goto finish; else if (streq(t, "today")) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto finish; } else if (streq(t, "yesterday")) { tm.tm_mday--; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto finish; } else if (streq(t, "tomorrow")) { tm.tm_mday++; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto finish; } else if (t[0] == '+') { r = parse_sec(t + 1, &plus); if (r < 0) return r; goto finish; } else if (t[0] == '-') { r = parse_sec(t + 1, &minus); if (r < 0) return r; goto finish; } else if (endswith(t, " ago")) { char *z; z = strndup(t, strlen(t) - 4); if (!z) return -ENOMEM; r = parse_sec(z, &minus); if (r < 0) return r; goto finish; } for (i = 0; i < ARRAY_SIZE(day_nr); i++) { size_t skip; if (!startswith_no_case(t, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if (t[skip] != ' ') continue; weekday = day_nr[i].nr; t += skip + 1; break; } copy = tm; k = strptime(t, "%y-%m-%d %H:%M:%S", &tm); if (k && *k == 0) goto finish; tm = copy; k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm); if (k && *k == 0) goto finish; tm = copy; k = strptime(t, "%y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto finish; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto finish; } tm = copy; k = strptime(t, "%y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto finish; } tm = copy; k = strptime(t, "%Y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto finish; } tm = copy; k = strptime(t, "%H:%M:%S", &tm); if (k && *k == 0) goto finish; tm = copy; k = strptime(t, "%H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto finish; } tm = copy; k = strptime(t, "%Y%m%d%H%M%S", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto finish; } return -EINVAL; finish: x = mktime(&tm); if (x == (time_t)-1) return -EINVAL; if (weekday >= 0 && tm.tm_wday != weekday) return -EINVAL; ret = (usec_t) x *USEC_PER_SEC; ret += plus; if (ret > minus) ret -= minus; else ret = 0; *usec = ret; return 0; }
int parse_timestamp(const char *t, usec_t *usec) { static const struct { const char *name; const int nr; } day_nr[] = { { "Sunday", 0 }, { "Sun", 0 }, { "Monday", 1 }, { "Mon", 1 }, { "Tuesday", 2 }, { "Tue", 2 }, { "Wednesday", 3 }, { "Wed", 3 }, { "Thursday", 4 }, { "Thu", 4 }, { "Friday", 5 }, { "Fri", 5 }, { "Saturday", 6 }, { "Sat", 6 }, }; const char *k; const char *utc; struct tm tm, copy; time_t x; usec_t x_usec, plus = 0, minus = 0, ret; int r, weekday = -1; unsigned i; /* * Allowed syntaxes: * * 2012-09-22 16:34:22 * 2012-09-22 16:34 (seconds will be set to 0) * 2012-09-22 (time will be set to 00:00:00) * 16:34:22 (date will be set to today) * 16:34 (date will be set to today, seconds to 0) * now * yesterday (time is set to 00:00:00) * today (time is set to 00:00:00) * tomorrow (time is set to 00:00:00) * +5min * -5days * @2147483647 (seconds since epoch) * */ assert(t); assert(usec); if (t[0] == '@') return parse_sec(t + 1, usec); ret = now(CLOCK_REALTIME); if (streq(t, "now")) goto finish; else if (t[0] == '+') { r = parse_sec(t+1, &plus); if (r < 0) return r; goto finish; } else if (t[0] == '-') { r = parse_sec(t+1, &minus); if (r < 0) return r; goto finish; } else if ((k = endswith(t, " ago"))) { t = strndupa(t, k - t); r = parse_sec(t, &minus); if (r < 0) return r; goto finish; } else if ((k = endswith(t, " left"))) { t = strndupa(t, k - t); r = parse_sec(t, &plus); if (r < 0) return r; goto finish; } utc = endswith_no_case(t, " UTC"); if (utc) t = strndupa(t, utc - t); x = ret / USEC_PER_SEC; x_usec = 0; assert_se(localtime_or_gmtime_r(&x, &tm, utc)); tm.tm_isdst = -1; if (streq(t, "today")) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "yesterday")) { tm.tm_mday --; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "tomorrow")) { tm.tm_mday ++; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; if (!startswith_no_case(t, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if (t[skip] != ' ') continue; weekday = day_nr[i].nr; t += skip + 1; break; } copy = tm; k = strptime(t, "%y-%m-%d %H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } tm = copy; k = strptime(t, "%y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } tm = copy; k = strptime(t, "%H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } return -EINVAL; parse_usec: { unsigned add; k++; r = parse_fractional_part_u(&k, 6, &add); if (r < 0) return -EINVAL; if (*k) return -EINVAL; x_usec = add; } from_tm: x = mktime_or_timegm(&tm, utc); if (x == (time_t) -1) return -EINVAL; if (weekday >= 0 && tm.tm_wday != weekday) return -EINVAL; ret = (usec_t) x * USEC_PER_SEC + x_usec; finish: ret += plus; if (ret > minus) ret -= minus; else ret = 0; *usec = ret; return 0; }
int parse_timestamp(const char *t, usec_t *usec) { static const struct { const char *name; const int nr; } day_nr[] = { { "Sunday", 0 }, { "Sun", 0 }, { "Monday", 1 }, { "Mon", 1 }, { "Tuesday", 2 }, { "Tue", 2 }, { "Wednesday", 3 }, { "Wed", 3 }, { "Thursday", 4 }, { "Thu", 4 }, { "Friday", 5 }, { "Fri", 5 }, { "Saturday", 6 }, { "Sat", 6 }, }; const char *k, *utc, *tzn = NULL; struct tm tm, copy; time_t x; usec_t x_usec, plus = 0, minus = 0, ret; int r, weekday = -1, dst = -1; unsigned i; /* * Allowed syntaxes: * * 2012-09-22 16:34:22 * 2012-09-22 16:34 (seconds will be set to 0) * 2012-09-22 (time will be set to 00:00:00) * 16:34:22 (date will be set to today) * 16:34 (date will be set to today, seconds to 0) * now * yesterday (time is set to 00:00:00) * today (time is set to 00:00:00) * tomorrow (time is set to 00:00:00) * +5min * -5days * @2147483647 (seconds since epoch) * */ assert(t); assert(usec); if (t[0] == '@') return parse_sec(t + 1, usec); ret = now(CLOCK_REALTIME); if (streq(t, "now")) goto finish; else if (t[0] == '+') { r = parse_sec(t+1, &plus); if (r < 0) return r; goto finish; } else if (t[0] == '-') { r = parse_sec(t+1, &minus); if (r < 0) return r; goto finish; } else if ((k = endswith(t, " ago"))) { t = strndupa(t, k - t); r = parse_sec(t, &minus); if (r < 0) return r; goto finish; } else if ((k = endswith(t, " left"))) { t = strndupa(t, k - t); r = parse_sec(t, &plus); if (r < 0) return r; goto finish; } /* See if the timestamp is suffixed with UTC */ utc = endswith_no_case(t, " UTC"); if (utc) t = strndupa(t, utc - t); else { const char *e = NULL; int j; tzset(); /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because * there are no nice APIs available to cover this. By accepting the local time zone strings, we make * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't * support arbitrary timezone specifications. */ for (j = 0; j <= 1; j++) { if (isempty(tzname[j])) continue; e = endswith_no_case(t, tzname[j]); if (!e) continue; if (e == t) continue; if (e[-1] != ' ') continue; break; } if (IN_SET(j, 0, 1)) { /* Found one of the two timezones specified. */ t = strndupa(t, e - t - 1); dst = j; tzn = tzname[j]; } } x = (time_t) (ret / USEC_PER_SEC); x_usec = 0; if (!localtime_or_gmtime_r(&x, &tm, utc)) return -EINVAL; tm.tm_isdst = dst; if (tzn) tm.tm_zone = tzn; if (streq(t, "today")) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "yesterday")) { tm.tm_mday--; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "tomorrow")) { tm.tm_mday++; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; if (!startswith_no_case(t, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if (t[skip] != ' ') continue; weekday = day_nr[i].nr; t += skip + 1; break; } copy = tm; k = strptime(t, "%y-%m-%d %H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } tm = copy; k = strptime(t, "%y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } tm = copy; k = strptime(t, "%H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } return -EINVAL; parse_usec: { unsigned add; k++; r = parse_fractional_part_u(&k, 6, &add); if (r < 0) return -EINVAL; if (*k) return -EINVAL; x_usec = add; } from_tm: x = mktime_or_timegm(&tm, utc); if (x == (time_t) -1) return -EINVAL; if (weekday >= 0 && tm.tm_wday != weekday) return -EINVAL; ret = (usec_t) x * USEC_PER_SEC + x_usec; finish: ret += plus; if (ret > minus) ret -= minus; else ret = 0; *usec = ret; return 0; }