static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int level, char ***units, unsigned int branches) { _cleanup_strv_free_ char **deps = NULL; char **c; int r = 0; usec_t service_longest = 0; int to_print = 0; struct unit_times *times; struct boot_times *boot; if (strv_extend(units, name)) return log_oom(); r = list_dependencies_get_dependencies(bus, name, &deps); if (r < 0) return r; qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare); r = acquire_boot_times(bus, &boot); if (r < 0) return r; STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); if (times && times->activated && times->activated <= boot->finish_time && (times->activated >= service_longest || service_longest == 0)) { service_longest = times->activated; break; } }
static int decode_and_sort_links(sd_netlink_message *m, LinkInfo **ret) { _cleanup_free_ LinkInfo *links = NULL; size_t size = 0, c = 0; sd_netlink_message *i; int r; for (i = m; i; i = sd_netlink_message_next(i)) { const char *name; unsigned iftype; uint16_t type; int ifindex; r = sd_netlink_message_get_type(i, &type); if (r < 0) return r; if (type != RTM_NEWLINK) continue; r = sd_rtnl_message_link_get_ifindex(i, &ifindex); if (r < 0) return r; r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name); if (r < 0) return r; r = sd_rtnl_message_link_get_type(i, &iftype); if (r < 0) return r; if (!GREEDY_REALLOC(links, size, c+1)) return -ENOMEM; links[c].name = name; links[c].ifindex = ifindex; links[c].iftype = iftype; c++; } qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); *ret = links; links = NULL; return (int) c; }
static void display(Hashmap *a) { Iterator i; Group *g; Group **array; signed path_columns; unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */ char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; assert(a); if (!terminal_is_dumb()) fputs(ANSI_HOME_CLEAR, stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); HASHMAP_FOREACH(g, a, i) if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) array[n++] = g; qsort_safe(array, n, sizeof(Group*), group_compare); /* Find the longest names in one run */ for (j = 0; j < n; j++) { unsigned cputlen, pathtlen; format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); cputlen = strlen(buffer); maxtcpu = MAX(maxtcpu, cputlen); pathtlen = strlen(array[j]->path); maxtpath = MAX(maxtpath, pathtlen); } if (arg_cpu_type == CPU_PERCENT) xsprintf(buffer, "%6s", "%CPU"); else xsprintf(buffer, "%*s", maxtcpu, "CPU Time"); rows = lines(); if (rows <= 10) rows = 10; if (on_tty()) { const char *on, *off; path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; on = ansi_highlight_underline(); off = ansi_underline(); printf("%s%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s%s\n", ansi_underline(), arg_order == ORDER_PATH ? on : "", path_columns, "Control Group", arg_order == ORDER_PATH ? off : "", arg_order == ORDER_TASKS ? on : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", arg_order == ORDER_TASKS ? off : "", arg_order == ORDER_CPU ? on : "", buffer, arg_order == ORDER_CPU ? off : "", arg_order == ORDER_MEMORY ? on : "", "Memory", arg_order == ORDER_MEMORY ? off : "", arg_order == ORDER_IO ? on : "", "Input/s", arg_order == ORDER_IO ? off : "", arg_order == ORDER_IO ? on : "", "Output/s", arg_order == ORDER_IO ? off : "", ansi_normal()); } else path_columns = maxtpath; for (j = 0; j < n; j++) { _cleanup_free_ char *ellipsized = NULL; const char *path; if (on_tty() && j + 6 > rows) break; g = array[j]; path = isempty(g->path) ? "/" : g->path; ellipsized = ellipsize(path, path_columns, 33); printf("%-*s", path_columns, ellipsized ?: path); if (g->n_tasks_valid) printf(" %7" PRIu64, g->n_tasks); else fputs(" -", stdout); if (arg_cpu_type == CPU_PERCENT) { if (g->cpu_valid) printf(" %6.1f", g->cpu_fraction*100); else fputs(" -", stdout); } else printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_output_bps)); putchar('\n'); } }
static int display(Hashmap *a) { Iterator i; Group *g; Group **array; signed path_columns; unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 0; char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; assert(a); /* Set cursor to top left corner and clear screen */ if (on_tty()) fputs("\033[H" "\033[2J", stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); HASHMAP_FOREACH(g, a, i) if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) array[n++] = g; qsort_safe(array, n, sizeof(Group*), group_compare); /* Find the longest names in one run */ for (j = 0; j < n; j++) { unsigned cputlen, pathtlen; format_timespan(buffer, sizeof(buffer), (nsec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); cputlen = strlen(buffer); maxtcpu = MAX(maxtcpu, cputlen); pathtlen = strlen(array[j]->path); maxtpath = MAX(maxtpath, pathtlen); } if (arg_cpu_type == CPU_PERCENT) snprintf(buffer, sizeof(buffer), "%6s", "%CPU"); else snprintf(buffer, sizeof(buffer), "%*s", maxtcpu, "CPU Time"); rows = lines(); if (rows <= 10) rows = 10; if (on_tty()) { path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; printf("%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s\n\n", arg_order == ORDER_PATH ? ON : "", path_columns, "Path", arg_order == ORDER_PATH ? OFF : "", arg_order == ORDER_TASKS ? ON : "", "Tasks", arg_order == ORDER_TASKS ? OFF : "", arg_order == ORDER_CPU ? ON : "", buffer, arg_order == ORDER_CPU ? OFF : "", arg_order == ORDER_MEMORY ? ON : "", "Memory", arg_order == ORDER_MEMORY ? OFF : "", arg_order == ORDER_IO ? ON : "", "Input/s", arg_order == ORDER_IO ? OFF : "", arg_order == ORDER_IO ? ON : "", "Output/s", arg_order == ORDER_IO ? OFF : ""); } else path_columns = maxtpath; for (j = 0; j < n; j++) { char *p; if (on_tty() && j + 5 > rows) break; g = array[j]; p = ellipsize(g->path, path_columns, 33); printf("%-*s", path_columns, p ? p : g->path); free(p); if (g->n_tasks_valid) printf(" %7u", g->n_tasks); else fputs(" -", stdout); if (arg_cpu_type == CPU_PERCENT) { if (g->cpu_valid) printf(" %6.1f", g->cpu_fraction*100); else fputs(" -", stdout); } else printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (nsec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); if (g->memory_valid) printf(" %8s", format_bytes(buffer, sizeof(buffer), g->memory)); else fputs(" -", stdout); if (g->io_valid) { printf(" %8s", format_bytes(buffer, sizeof(buffer), g->io_input_bps)); printf(" %8s", format_bytes(buffer, sizeof(buffer), g->io_output_bps)); } else fputs(" - -", stdout); putchar('\n'); } return 0; }
int journal_directory_vacuum( const char *directory, uint64_t max_use, uint64_t n_max_files, usec_t max_retention_usec, usec_t *oldest_usec, bool verbose) { _cleanup_closedir_ DIR *d = NULL; struct vacuum_info *list = NULL; unsigned n_list = 0, i, n_active_files = 0; size_t n_allocated = 0; uint64_t sum = 0, freed = 0; usec_t retention_limit = 0; char sbytes[FORMAT_BYTES_MAX]; struct dirent *de; int r; assert(directory); if (max_use <= 0 && max_retention_usec <= 0 && n_max_files <= 0) return 0; if (max_retention_usec > 0) { retention_limit = now(CLOCK_REALTIME); if (retention_limit > max_retention_usec) retention_limit -= max_retention_usec; else max_retention_usec = retention_limit = 0; } d = opendir(directory); if (!d) return -errno; FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { unsigned long long seqnum = 0, realtime; _cleanup_free_ char *p = NULL; sd_id128_t seqnum_id; bool have_seqnum; uint64_t size; struct stat st; size_t q; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { log_debug_errno(errno, "Failed to stat file %s while vacuuming, ignoring: %m", de->d_name); continue; } if (!S_ISREG(st.st_mode)) continue; q = strlen(de->d_name); if (endswith(de->d_name, ".journal")) { /* Vacuum archived files. Active files are * left around */ if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) { n_active_files++; continue; } if (de->d_name[q-8-16-1] != '-' || de->d_name[q-8-16-1-16-1] != '-' || de->d_name[q-8-16-1-16-1-32-1] != '@') { n_active_files++; continue; } p = strdup(de->d_name); if (!p) { r = -ENOMEM; goto finish; } de->d_name[q-8-16-1-16-1] = 0; if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { n_active_files++; continue; } if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { n_active_files++; continue; } have_seqnum = true; } else if (endswith(de->d_name, ".journal~")) { unsigned long long tmp; /* Vacuum corrupted files */ if (q < 1 + 16 + 1 + 16 + 8 + 1) { n_active_files ++; continue; } if (de->d_name[q-1-8-16-1] != '-' || de->d_name[q-1-8-16-1-16-1] != '@') { n_active_files ++; continue; } p = strdup(de->d_name); if (!p) { r = -ENOMEM; goto finish; } if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { n_active_files ++; continue; } have_seqnum = false; } else { /* We do not vacuum unknown files! */ log_debug("Not vacuuming unknown file %s.", de->d_name); continue; } size = 512UL * (uint64_t) st.st_blocks; r = journal_file_empty(dirfd(d), p); if (r < 0) { log_debug_errno(r, "Failed check if %s is empty, ignoring: %m", p); continue; } if (r > 0) { /* Always vacuum empty non-online files. */ if (unlinkat(dirfd(d), p, 0) >= 0) { log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted empty archived journal %s/%s (%s).", directory, p, format_bytes(sbytes, sizeof(sbytes), size)); freed += size; } else if (errno != ENOENT) log_warning_errno(errno, "Failed to delete empty archived journal %s/%s: %m", directory, p); continue; } patch_realtime(dirfd(d), p, &st, &realtime); if (!GREEDY_REALLOC(list, n_allocated, n_list + 1)) { r = -ENOMEM; goto finish; } list[n_list].filename = p; list[n_list].usage = size; list[n_list].seqnum = seqnum; list[n_list].realtime = realtime; list[n_list].seqnum_id = seqnum_id; list[n_list].have_seqnum = have_seqnum; n_list ++; p = NULL; sum += size; } qsort_safe(list, n_list, sizeof(struct vacuum_info), vacuum_compare); for (i = 0; i < n_list; i++) { unsigned left; left = n_active_files + n_list - i; if ((max_retention_usec <= 0 || list[i].realtime >= retention_limit) && (max_use <= 0 || sum <= max_use) && (n_max_files <= 0 || left <= n_max_files)) break; if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) { log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted archived journal %s/%s (%s).", directory, list[i].filename, format_bytes(sbytes, sizeof(sbytes), list[i].usage)); freed += list[i].usage; if (list[i].usage < sum) sum -= list[i].usage; else sum = 0; } else if (errno != ENOENT) log_warning_errno(errno, "Failed to delete archived journal %s/%s: %m", directory, list[i].filename); } if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec)) *oldest_usec = list[i].realtime; r = 0; finish: for (i = 0; i < n_list; i++) free(list[i].filename); free(list); log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed)); return r; }
int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ struct local_address *list = NULL; size_t n_list = 0, n_allocated = 0; sd_netlink_message *m; int r; assert(ret); if (context) rtnl = sd_netlink_ref(context); else { r = sd_netlink_open(&rtnl); if (r < 0) return r; } r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, af); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { struct local_address *a; unsigned char flags; uint16_t type; int ifi, family; r = sd_netlink_message_get_errno(m); if (r < 0) return r; r = sd_netlink_message_get_type(m, &type); if (r < 0) return r; if (type != RTM_NEWADDR) continue; r = sd_rtnl_message_addr_get_ifindex(m, &ifi); if (r < 0) return r; if (ifindex > 0 && ifi != ifindex) continue; r = sd_rtnl_message_addr_get_family(m, &family); if (r < 0) return r; if (af != AF_UNSPEC && af != family) continue; r = sd_rtnl_message_addr_get_flags(m, &flags); if (r < 0) return r; if (flags & IFA_F_DEPRECATED) continue; if (!GREEDY_REALLOC0(list, n_allocated, n_list+1)) return -ENOMEM; a = list + n_list; r = sd_rtnl_message_addr_get_scope(m, &a->scope); if (r < 0) return r; if (ifindex == 0 && IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE)) continue; switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(m, IFA_LOCAL, &a->address.in); if (r < 0) { r = sd_netlink_message_read_in_addr(m, IFA_ADDRESS, &a->address.in); if (r < 0) continue; } break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6); if (r < 0) { r = sd_netlink_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6); if (r < 0) continue; } break; default: continue; } a->ifindex = ifi; a->family = family; n_list++; }; qsort_safe(list, n_list, sizeof(struct local_address), address_compare); *ret = TAKE_PTR(list); return (int) n_list; }
int bus_match_parse( const char *match, struct bus_match_component **_components, unsigned *_n_components) { const char *p = match; struct bus_match_component *components = NULL; size_t components_allocated = 0; unsigned n_components = 0, i; _cleanup_free_ char *value = NULL; int r; assert(match); assert(_components); assert(_n_components); while (*p != 0) { const char *eq, *q; enum bus_match_node_type t; unsigned j = 0; size_t value_allocated = 0; bool escaped = false; uint8_t u; eq = strchr(p, '='); if (!eq) return -EINVAL; if (eq[1] != '\'') return -EINVAL; t = bus_match_node_type_from_string(p, eq - p); if (t < 0) return -EINVAL; for (q = eq + 2;; q++) { if (*q == 0) { r = -EINVAL; goto fail; } if (!escaped) { if (*q == '\\') { escaped = true; continue; } if (*q == '\'') { if (value) value[j] = 0; break; } } if (!GREEDY_REALLOC(value, value_allocated, j + 2)) { r = -ENOMEM; goto fail; } value[j++] = *q; escaped = false; } if (t == BUS_MATCH_MESSAGE_TYPE) { r = bus_message_type_from_string(value, &u); if (r < 0) goto fail; free(value); value = NULL; } else u = 0; if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) { r = -ENOMEM; goto fail; } components[n_components].type = t; components[n_components].value_str = value; components[n_components].value_u8 = u; n_components++; value = NULL; if (q[1] == 0) break; if (q[1] != ',') { r = -EINVAL; goto fail; } p = q + 2; } /* Order the whole thing, so that we always generate the same tree */ qsort_safe(components, n_components, sizeof(struct bus_match_component), match_component_compare); /* Check for duplicates */ for (i = 0; i+1 < n_components; i++) if (components[i].type == components[i+1].type) { r = -EINVAL; goto fail; } *_components = components; *_n_components = n_components; return 0; fail: bus_match_parse_free(components, n_components); return r; }
int journal_directory_vacuum( const char *directory, uint64_t max_use, usec_t max_retention_usec, usec_t *oldest_usec) { _cleanup_closedir_ DIR *d = NULL; int r = 0; struct vacuum_info *list = NULL; unsigned n_list = 0, i; size_t n_allocated = 0; uint64_t sum = 0, freed = 0; usec_t retention_limit = 0; assert(directory); if (max_use <= 0 && max_retention_usec <= 0) return 0; if (max_retention_usec > 0) { retention_limit = now(CLOCK_REALTIME); if (retention_limit > max_retention_usec) retention_limit -= max_retention_usec; else max_retention_usec = retention_limit = 0; } d = opendir(directory); if (!d) return -errno; for (;;) { struct dirent *de; size_t q; struct stat st; char *p; unsigned long long seqnum = 0, realtime; sd_id128_t seqnum_id; bool have_seqnum; errno = 0; de = readdir(d); if (!de && errno != 0) { r = -errno; goto finish; } if (!de) break; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) continue; if (!S_ISREG(st.st_mode)) continue; q = strlen(de->d_name); if (endswith(de->d_name, ".journal")) { /* Vacuum archived files */ if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) continue; if (de->d_name[q-8-16-1] != '-' || de->d_name[q-8-16-1-16-1] != '-' || de->d_name[q-8-16-1-16-1-32-1] != '@') continue; p = strdup(de->d_name); if (!p) { r = -ENOMEM; goto finish; } de->d_name[q-8-16-1-16-1] = 0; if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { free(p); continue; } if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { free(p); continue; } have_seqnum = true; } else if (endswith(de->d_name, ".journal~")) { unsigned long long tmp; /* Vacuum corrupted files */ if (q < 1 + 16 + 1 + 16 + 8 + 1) continue; if (de->d_name[q-1-8-16-1] != '-' || de->d_name[q-1-8-16-1-16-1] != '@') continue; p = strdup(de->d_name); if (!p) { r = -ENOMEM; goto finish; } if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { free(p); continue; } have_seqnum = false; } else /* We do not vacuum active files or unknown files! */ continue; if (journal_file_empty(dirfd(d), p)) { /* Always vacuum empty non-online files. */ uint64_t size = 512UL * (uint64_t) st.st_blocks; if (unlinkat(dirfd(d), p, 0) >= 0) { log_info("Deleted empty journal %s/%s (%"PRIu64" bytes).", directory, p, size); freed += size; } else if (errno != ENOENT) log_warning("Failed to delete %s/%s: %m", directory, p); free(p); continue; } patch_realtime(directory, p, &st, &realtime); GREEDY_REALLOC(list, n_allocated, n_list + 1); list[n_list].filename = p; list[n_list].usage = 512UL * (uint64_t) st.st_blocks; list[n_list].seqnum = seqnum; list[n_list].realtime = realtime; list[n_list].seqnum_id = seqnum_id; list[n_list].have_seqnum = have_seqnum; sum += list[n_list].usage; n_list ++; } qsort_safe(list, n_list, sizeof(struct vacuum_info), vacuum_compare); for (i = 0; i < n_list; i++) { if ((max_retention_usec <= 0 || list[i].realtime >= retention_limit) && (max_use <= 0 || sum <= max_use)) break; if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) { log_debug("Deleted archived journal %s/%s (%"PRIu64" bytes).", directory, list[i].filename, list[i].usage); freed += list[i].usage; if (list[i].usage < sum) sum -= list[i].usage; else sum = 0; } else if (errno != ENOENT) log_warning("Failed to delete %s/%s: %m", directory, list[i].filename); } if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec)) *oldest_usec = list[i].realtime; finish: for (i = 0; i < n_list; i++) free(list[i].filename); free(list); log_debug("Vacuuming done, freed %"PRIu64" bytes", freed); return r; }