static int test_unit_file_get_set(void) { int r; Hashmap *h; Iterator i; UnitFileList *p; h = hashmap_new(&string_hash_ops); assert_se(h); r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h); if (r == -EPERM || r == -EACCES) { printf("Skipping test: unit_file_get_list: %s", strerror(-r)); return EXIT_TEST_SKIP; } log_full(r == 0 ? LOG_INFO : LOG_ERR, "unit_file_get_list: %s", strerror(-r)); if (r < 0) return EXIT_FAILURE; HASHMAP_FOREACH(p, h, i) printf("%s = %s\n", p->path, unit_file_state_to_string(p->state)); unit_file_list_free(h); return 0; }
static int mount_one(const MountPoint *p, bool relabel) { int r; assert(p); if (p->condition_fn && !p->condition_fn()) return 0; /* Relabel first, just in case */ if (relabel) label_fix(p->where, true, true); r = path_is_mount_point(p->where, true); if (r < 0) return r; if (r > 0) return 0; /* Skip securityfs in a container */ if (!(p->mode & MNT_IN_CONTAINER) && detect_container(NULL) > 0) return 0; /* The access mode here doesn't really matter too much, since * the mounted file system will take precedence anyway. */ if (relabel) mkdir_p_label(p->where, 0755); else mkdir_p(p->where, 0755); log_debug("Mounting %s to %s of type %s with options %s.", p->what, p->where, p->type, strna(p->options)); if (mount(p->what, p->where, p->type, p->flags, p->options) < 0) { log_full((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, "Failed to mount %s at %s: %m", p->type, p->where); return (p->mode & MNT_FATAL) ? -errno : 0; } /* Relabel again, since we now mounted something fresh here */ if (relabel) label_fix(p->where, false, false); return 1; }
int server_open_dev_kmsg(Server *s) { mode_t mode; int r; assert(s); if (s->read_kmsg) mode = O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY; else mode = O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY; s->dev_kmsg_fd = open("/dev/kmsg", mode); if (s->dev_kmsg_fd < 0) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to open /dev/kmsg, ignoring: %m"); return 0; } if (!s->read_kmsg) return 0; r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); if (r < 0) { /* This will fail with EPERM on older kernels where * /dev/kmsg is not readable. */ if (r == -EPERM) { r = 0; goto fail; } log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); goto fail; } r = sd_event_source_set_priority(s->dev_kmsg_event_source, SD_EVENT_PRIORITY_IMPORTANT+10); if (r < 0) { log_error_errno(r, "Failed to adjust priority of kmsg event source: %m"); goto fail; } s->dev_kmsg_readable = true; return 0; fail: s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); s->dev_kmsg_fd = safe_close(s->dev_kmsg_fd); return r; }
static int hibernation_partition_size(size_t *size, size_t *used) { _cleanup_fclose_ FILE *f; unsigned i; assert(size); assert(used); f = fopen("/proc/swaps", "re"); if (!f) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to retrieve open /proc/swaps: %m"); assert(errno > 0); return -errno; } (void) fscanf(f, "%*s %*s %*s %*s %*s\n"); for (i = 1;; i++) { _cleanup_free_ char *dev = NULL, *type = NULL; size_t size_field, used_field; int k; k = fscanf(f, "%ms " /* device/file */ "%ms " /* type of swap */ "%zu " /* swap size */ "%zu " /* used */ "%*i\n", /* priority */ &dev, &type, &size_field, &used_field); if (k != 4) { if (k == EOF) break; log_warning("Failed to parse /proc/swaps:%u", i); continue; } if (streq(type, "partition") && endswith(dev, "\\040(deleted)")) { log_warning("Ignoring deleted swapfile '%s'.", dev); continue; } *size = size_field; *used = used_field; return 0; } log_debug("No swap partitions were found."); return -ENOSYS; }
bool log_event(EventType type, time_t timestamp) { if (log_full()) { APP_LOG(APP_LOG_LEVEL_ERROR, "log capacity exhausted"); return false; } eventLog[(firstEventIdx + eventLogSize++) % EVENT_LOG_MAX_SIZE] = (Event){ .type = type, .timestamp = timestamp }; LOG(APP_LOG_LEVEL_DEBUG, "recorded one event"); return true; }
int server_open_dev_kmsg(Server *s) { int r; assert(s); s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (s->dev_kmsg_fd < 0) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to open /dev/kmsg, ignoring: %m"); return 0; } r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); if (r < 0) { /* This will fail with EPERM on older kernels where * /dev/kmsg is not readable. */ if (r == -EPERM) { r = 0; goto fail; } log_error("Failed to add /dev/kmsg fd to event loop: %s", strerror(-r)); goto fail; } r = sd_event_source_set_priority(s->dev_kmsg_event_source, SD_EVENT_PRIORITY_IMPORTANT+10); if (r < 0) { log_error("Failed to adjust priority of kmsg event source: %s", strerror(-r)); goto fail; } s->dev_kmsg_readable = true; return 0; fail: if (s->dev_kmsg_event_source) s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); if (s->dev_kmsg_fd >= 0) { close_nointr_nofail(s->dev_kmsg_fd); s->dev_kmsg_fd = -1; } return r; }
int label_socket_set(const char *label) { #ifdef HAVE_SELINUX if (!use_selinux()) return 0; if (setsockcreatecon((security_context_t) label) < 0) { log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to set SELinux context (%s) on socket: %m", label); if (security_getenforce() == 1) return -errno; } #endif return 0; }
static int update_timeout(void) { int r; if (watchdog_fd < 0) return 0; if (watchdog_timeout == USEC_INFINITY) return 0; else if (watchdog_timeout == 0) { int flags; flags = WDIOS_DISABLECARD; r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); if (r < 0) return log_warning_errno(errno, "Failed to disable hardware watchdog: %m"); } else { int sec, flags; char buf[FORMAT_TIMESPAN_MAX]; sec = (int) ((watchdog_timeout + USEC_PER_SEC - 1) / USEC_PER_SEC); r = ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec); if (r < 0) return log_warning_errno(errno, "Failed to set timeout to %is: %m", sec); watchdog_timeout = (usec_t) sec * USEC_PER_SEC; log_info("Set hardware watchdog to %s.", format_timespan(buf, sizeof(buf), watchdog_timeout, 0)); flags = WDIOS_ENABLECARD; r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); if (r < 0) { /* ENOTTY means the watchdog is always enabled so we're fine */ log_full(errno == ENOTTY ? LOG_DEBUG : LOG_WARNING, "Failed to enable hardware watchdog: %m"); if (errno != ENOTTY) return -errno; } r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0); if (r < 0) return log_warning_errno(errno, "Failed to ping hardware watchdog: %m"); } return 0; }
int label_fix(const char *path, bool ignore_enoent) { int r = 0; #ifdef HAVE_SELINUX struct stat st; security_context_t fcon; if (!use_selinux() || !label_hnd) return 0; r = lstat(path, &st); if (r == 0) { r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); /* If there's no label to set, then exit without warning */ if (r < 0 && errno == ENOENT) return 0; if (r == 0) { r = setfilecon(path, fcon); freecon(fcon); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == ENOTSUP) return 0; } } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Unable to fix label of %s: %m", path); r = security_getenforce() == 1 ? -errno : 0; } #endif return r; }
int label_init(void) { int r = 0; #ifdef HAVE_SELINUX if (!use_selinux()) return 0; if (label_hnd) return 0; label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); if (!label_hnd) { log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to initialize SELinux context: %m"); r = security_getenforce() == 1 ? -errno : 0; } #endif return r; }
void cryptsetup_log_glue(int level, const char *msg, void *usrptr) { switch (level) { case CRYPT_LOG_NORMAL: level = LOG_NOTICE; break; case CRYPT_LOG_ERROR: level = LOG_ERR; break; case CRYPT_LOG_VERBOSE: level = LOG_INFO; break; case CRYPT_LOG_DEBUG: level = LOG_DEBUG; break; default: log_error("Unknown libcryptsetup log level: %d", level); level = LOG_ERR; } log_full(level, "%s", msg); }
static int test_unit_file_get_set(void) { int r; Hashmap *h; Iterator i; UnitFileList *p; h = hashmap_new(string_hash_func, string_compare_func); assert(h); r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h); log_full(r == 0 ? LOG_INFO : LOG_ERR, "unit_file_get_list: %s", strerror(-r)); if (r < 0) return EXIT_FAILURE; HASHMAP_FOREACH(p, h, i) printf("%s = %s\n", p->path, unit_file_state_to_string(p->state)); unit_file_list_free(h); return 0; }
/* Go through the file and parse each line */ int config_parse(const char *unit, const char *filename, FILE *f, const char *sections, ConfigItemLookup lookup, const void *table, bool relaxed, bool allow_include, bool warn, void *userdata) { _cleanup_free_ char *section = NULL, *continuation = NULL; _cleanup_fclose_ FILE *ours = NULL; unsigned line = 0, section_line = 0; bool section_ignored = false; int r; assert(filename); assert(lookup); if (!f) { f = ours = fopen(filename, "re"); if (!f) { /* Only log on request, except for ENOENT, * since we return 0 to the caller. */ if (warn || errno == ENOENT) log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR, "Failed to open configuration file '%s': %m", filename); return errno == ENOENT ? 0 : -errno; } } fd_warn_permissions(filename, fileno(f)); while (!feof(f)) { char l[LINE_MAX], *p, *c = NULL, *e; bool escaped = false; if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; log_error_errno(errno, "Failed to read configuration file '%s': %m", filename); return -errno; } truncate_nl(l); if (continuation) { c = strappend(continuation, l); if (!c) { if (warn) log_oom(); return -ENOMEM; } continuation = mfree(continuation); p = c; } else p = l; for (e = p; *e; e++) { if (escaped) escaped = false; else if (*e == '\\') escaped = true; } if (escaped) { *(e-1) = ' '; if (c) continuation = c; else { continuation = strdup(l); if (!continuation) { if (warn) log_oom(); return -ENOMEM; } } continue; } r = parse_line(unit, filename, ++line, sections, lookup, table, relaxed, allow_include, §ion, §ion_line, §ion_ignored, p, userdata); free(c); if (r < 0) { if (warn) log_warning_errno(r, "Failed to parse file '%s': %m", filename); return r; } } return 0; }
int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { _cleanup_strv_free_ char **suspend_mode = NULL, **suspend_state = NULL, **hibernate_mode = NULL, **hibernate_state = NULL, **hybrid_mode = NULL, **hybrid_state = NULL; char **modes, **states; const ConfigTableItem items[] = { { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, {} }; int r; _cleanup_fclose_ FILE *f; f = fopen(PKGSYSCONFDIR "/sleep.conf", "re"); if (!f) log_full(errno == ENOENT ? LOG_DEBUG: LOG_WARNING, "Failed to open configuration file " PKGSYSCONFDIR "/sleep.conf: %m"); else { r = config_parse(NULL, PKGSYSCONFDIR "/sleep.conf", f, "Sleep\0", config_item_table_lookup, (void*) items, false, false, NULL); if (r < 0) log_warning("Failed to parse configuration file: %s", strerror(-r)); } if (streq(verb, "suspend")) { /* empty by default */ USE(modes, suspend_mode); if (suspend_state) USE(states, suspend_state); else states = strv_new("mem", "standby", "freeze", NULL); } else if (streq(verb, "hibernate")) { if (hibernate_mode) USE(modes, hibernate_mode); else modes = strv_new("platform", "shutdown", NULL); if (hibernate_state) USE(states, hibernate_state); else states = strv_new("disk", NULL); } else if (streq(verb, "hybrid-sleep")) { if (hybrid_mode) USE(modes, hybrid_mode); else modes = strv_new("suspend", "platform", "shutdown", NULL); if (hybrid_state) USE(states, hybrid_state); else states = strv_new("disk", NULL); } else assert_not_reached("what verb"); if ((!modes && !streq(verb, "suspend")) || !states) { strv_free(modes); strv_free(states); return log_oom(); } *_modes = modes; *_states = states; 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 parse_sleep_config(const char *verb, char ***modes, char ***states) { _cleanup_strv_free_ char **suspend_mode = NULL, **suspend_state = NULL, **hibernate_mode = NULL, **hibernate_state = NULL, **hybrid_mode = NULL, **hybrid_state = NULL; const ConfigTableItem items[] = { { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, {}}; int r; FILE _cleanup_fclose_ *f; f = fopen(PKGSYSCONFDIR "/sleep.conf", "re"); if (!f) log_full(errno == ENOENT ? LOG_DEBUG: LOG_WARNING, "Failed to open configuration file " PKGSYSCONFDIR "/sleep.conf: %m"); else { r = config_parse(NULL, PKGSYSCONFDIR "/sleep.conf", f, "Sleep\0", config_item_table_lookup, (void*) items, false, false, NULL); if (r < 0) log_warning("Failed to parse configuration file: %s", strerror(-r)); } if (streq(verb, "suspend")) { /* empty by default */ *modes = suspend_mode; if (suspend_state) *states = suspend_state; else *states = strv_split_nulstr("mem\0standby\0freeze\0"); suspend_mode = suspend_state = NULL; } else if (streq(verb, "hibernate")) { if (hibernate_mode) *modes = hibernate_mode; else *modes = strv_split_nulstr("platform\0shutdown\0"); if (hibernate_state) *states = hibernate_state; else *states = strv_split_nulstr("disk\0"); hibernate_mode = hibernate_state = NULL; } else if (streq(verb, "hybrid-sleep")) { if (hybrid_mode) *modes = hybrid_mode; else *modes = strv_split_nulstr("suspend\0platform\0shutdown\0"); if (hybrid_state) *states = hybrid_state; else *states = strv_split_nulstr("disk\0"); hybrid_mode = hybrid_state = NULL; } else assert_not_reached("what verb"); if (!modes || !states) { strv_free(*modes); strv_free(*states); return log_oom(); } return 0; }
/* Go through the file and parse each line */ int config_parse(const char *unit, const char *filename, FILE *f, const char *sections, ConfigItemLookup lookup, const void *table, ConfigParseFlags flags, void *userdata) { _cleanup_free_ char *section = NULL, *continuation = NULL; _cleanup_fclose_ FILE *ours = NULL; unsigned line = 0, section_line = 0; bool section_ignored = false; int r; assert(filename); assert(lookup); if (!f) { f = ours = fopen(filename, "re"); if (!f) { /* Only log on request, except for ENOENT, * since we return 0 to the caller. */ if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT) log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR, "Failed to open configuration file '%s': %m", filename); return errno == ENOENT ? 0 : -errno; } } fd_warn_permissions(filename, fileno(f)); for (;;) { _cleanup_free_ char *buf = NULL; bool escaped = false; char *l, *p, *e; r = read_line(f, LONG_LINE_MAX, &buf); if (r == 0) break; if (r == -ENOBUFS) { if (flags & CONFIG_PARSE_WARN) log_error_errno(r, "%s:%u: Line too long", filename, line); return r; } if (r < 0) { if (CONFIG_PARSE_WARN) log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line); return r; } l = buf; if (!(flags & CONFIG_PARSE_REFUSE_BOM)) { char *q; q = startswith(buf, UTF8_BYTE_ORDER_MARK); if (q) { l = q; flags |= CONFIG_PARSE_REFUSE_BOM; } } if (continuation) { if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) { if (flags & CONFIG_PARSE_WARN) log_error("%s:%u: Continuation line too long", filename, line); return -ENOBUFS; } if (!strextend(&continuation, l, NULL)) { if (flags & CONFIG_PARSE_WARN) log_oom(); return -ENOMEM; } p = continuation; } else p = l; for (e = p; *e; e++) { if (escaped) escaped = false; else if (*e == '\\') escaped = true; } if (escaped) { *(e-1) = ' '; if (!continuation) { continuation = strdup(l); if (!continuation) { if (flags & CONFIG_PARSE_WARN) log_oom(); return -ENOMEM; } } continue; } r = parse_line(unit, filename, ++line, sections, lookup, table, flags, §ion, §ion_line, §ion_ignored, p, userdata); if (r < 0) { if (flags & CONFIG_PARSE_WARN) log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line); return r; } continuation = mfree(continuation); } return 0; }
/** * This function is the only log function which should be called from the simulation platform. Actually, * it is a demultiplexer which calls the correct function depending on the current configuration of the * platform. Note that this function only returns a pointer to a malloc'd area which contains the * state buffers. This means that this memory area cannot be used as-is, but should be wrapped * into a state_t structure, which gives information about the simulation state pointer (defined * via <SetState>() by the application-level code and the lvt associated with the log. * This is done implicitly by the <LogState>() function, which in turn connects the newly taken * snapshot with the currencly-scheduled LP. * Therefore, any point of the simulator which wants to take a (real) log, shouldn't call directly this * function, rather <LogState>() should be used, after having correctly set current_lp and current_lvt. * * @author Alessandro Pellegrini * * @param lid The logical process' local identifier * @return A pointer to a malloc()'d memory area which contains the log of the current simulation state, * along with the relative meta-data which can be used to perform a restore operation. */ void *log_state(int lid) { statistics_post_lp_data(lid, STAT_CKPT, 1.0); return log_full(lid); }