static int stats_file_setup(struct stats_file *file) { struct stats_file_header *hdr; struct stat st; size_t size = 0; int err; DBG("file %p fd %d name %s", file, file->fd, file->name); err = fstat(file->fd, &st); if (err < 0) { connman_error("fstat error %s for %s\n", strerror(errno), file->name); TFR(close(file->fd)); g_free(file->name); file->name = NULL; return -errno; } size = (size_t)st.st_size; file->max_len = STATS_MAX_FILE_SIZE; if (size < (size_t)sysconf(_SC_PAGESIZE)) size = sysconf(_SC_PAGESIZE); err = stats_file_remap(file, size); if (err < 0) { TFR(close(file->fd)); g_free(file->name); file->name = NULL; return err; } hdr = get_hdr(file); if (hdr->magic != MAGIC || hdr->begin < sizeof(struct stats_file_header) || hdr->end < sizeof(struct stats_file_header) || hdr->home < sizeof(struct stats_file_header) || hdr->roaming < sizeof(struct stats_file_header) || hdr->begin > file->len || hdr->end > file->len) { hdr->magic = MAGIC; hdr->begin = sizeof(struct stats_file_header); hdr->end = sizeof(struct stats_file_header); hdr->home = UINT_MAX; hdr->roaming = UINT_MAX; stats_file_update_cache(file); } return 0; }
static int append_record(struct stats_file *file, struct stats_record *rec) { struct stats_record *cur, *next; int err; if (file->last == get_end(file)) { err = stats_file_remap(file, file->len + sysconf(_SC_PAGESIZE)); if (err < 0) return err; stats_file_update_cache(file); } cur = get_end(file); next = get_next(file, cur); memcpy(next, rec, sizeof(struct stats_record)); set_end(file, next); return 0; }
static int stats_create(struct stats_file *file, unsigned int nr, unsigned int interval, time_t start_ts, struct stats_record *start) { unsigned int i; int err; struct stats_record *cur, *next; struct stats_file_header *hdr; unsigned int pkt; unsigned int step_ts; unsigned int roaming = FALSE; hdr = get_hdr(file); hdr->magic = MAGIC; hdr->begin = sizeof(struct stats_file_header); hdr->end = sizeof(struct stats_file_header); hdr->home = UINT_MAX; hdr->roaming = UINT_MAX; stats_file_update_cache(file); if (start) { struct stats_record *rec; rec = get_end(file); memcpy(rec, start, sizeof(struct stats_record)); } else { get_end(file)->ts = start_ts; } for (i = 0; i < nr; i++) { if (file->last == get_end(file)) { err = stats_file_remap(file, file->len + sysconf(_SC_PAGESIZE)); if (err < 0) return err; stats_file_update_cache(file); } cur = get_end(file); next = get_next(file, cur); step_ts = (rand() % interval); if (step_ts == 0) step_ts = 1; next->ts = cur->ts + step_ts; next->roaming = roaming; next->data.time = cur->data.time + step_ts; next->data.rx_packets = cur->data.rx_packets; next->data.rx_bytes = cur->data.rx_bytes; if (rand() % 3 == 0) { pkt = rand() % 5; next->data.rx_packets += pkt; next->data.rx_bytes += pkt * (rand() % 1500); } next->data.tx_packets = cur->data.tx_packets; next->data.tx_bytes = cur->data.tx_bytes; if (rand() % 3 == 0) { pkt = rand() % 5; next->data.tx_packets += pkt; next->data.tx_bytes += pkt * (rand() % 1500); } set_end(file, next); if ((rand() % 50) == 0) roaming = roaming ? FALSE : TRUE; } return 0; }
static int stats_open(struct stats_file *file, const char *name) { struct stats_file_header *hdr; struct stat tm; int err; size_t size = 0; bzero(file, sizeof(struct stats_file)); if (name) { file->name = g_strdup(name); file->fd = TFR(open(file->name, O_RDWR | O_CREAT | O_CLOEXEC, 0644)); if (file->fd == -1) { fprintf(stderr, "open error %s for %s\n", strerror(errno), file->name); return -errno; } err = fstat(file->fd, &tm); if (err < 0) { fprintf(stderr, "fstat error %s for %s\n", strerror(errno), file->name); return err; } size = (size_t)tm.st_size; } else { file->name = g_strdup("stats.XXXXXX.tmp"); file->fd = g_mkstemp_full(file->name, O_RDWR | O_CREAT, 0644); if (file->fd == -1) { fprintf(stderr, "creating tmp failed\n"); return -1; } } if (size == 0) size = sysconf(_SC_PAGESIZE); err = stats_file_remap(file, size); if (err < 0) { fprintf(stderr, "remap failed\n"); return err; } /* Initialize new file */ hdr = get_hdr(file); if (hdr->magic != MAGIC || hdr->begin < sizeof(struct stats_file_header) || hdr->end < sizeof(struct stats_file_header) || hdr->home < sizeof(struct stats_file_header) || hdr->roaming < sizeof(struct stats_file_header) || hdr->begin > file->len || hdr->end > file->len) { hdr->magic = MAGIC; hdr->begin = sizeof(struct stats_file_header); hdr->end = sizeof(struct stats_file_header); hdr->home = UINT_MAX; hdr->roaming = UINT_MAX; } stats_file_update_cache(file); return 0; }
static void stats_convert(struct stats_file *file) { struct stats_file temp_file; int err; DBG("converting data file %s", file->name); stats_file_update_cache32(file); bzero(&temp_file, sizeof(struct stats_file)); err = stats_open_temp(&temp_file); if (err < 0) { connman_error("failed to open temporary file during data conversion"); return; } stats_file_setup(&temp_file); struct stats_iter32 data_iter; struct stats_record32 *record; data_iter.file = file; data_iter.begin = get_iterator_begin32(data_iter.file); data_iter.end = get_iterator_end32(data_iter.file); data_iter.it = data_iter.begin; record = get_next_record32(&data_iter); while (record) { struct stats_record *next; if (temp_file.last == get_end(&temp_file)) { err = stats_file_remap(&temp_file, temp_file.len + sysconf(_SC_PAGESIZE)); if (err < 0) { connman_error("failed to extend file %s", temp_file.name); unlink(temp_file.name); stats_file_unmap(&temp_file); TFR(close(temp_file.fd)); stats_file_cleanup(&temp_file); return; } stats_file_update_cache(&temp_file); } next = get_next(&temp_file, get_end(&temp_file)); if (next == get_begin(&temp_file)) { connman_error("ring buffer is full"); unlink(temp_file.name); stats_file_unmap(&temp_file); TFR(close(temp_file.fd)); stats_file_cleanup(&temp_file); return; } next->ts = record->ts; next->roaming = record->roaming; next->data.rx_packets = record->data.rx_packets; next->data.tx_packets = record->data.tx_packets; next->data.rx_bytes = record->data.rx_bytes; next->data.tx_bytes = record->data.tx_bytes; next->data.rx_errors = record->data.rx_errors; next->data.tx_errors = record->data.tx_errors; next->data.rx_dropped = record->data.rx_dropped; next->data.tx_dropped = record->data.tx_dropped; next->data.time = record->data.time; if (next->roaming) set_roaming(&temp_file, next); else set_home(&temp_file, next); set_end(&temp_file, next); record = get_next_record32(&data_iter); } // close and swap stats_file_unmap(file); TFR(close(file->fd)); err = rename(temp_file.name, file->name); if (err < 0) connman_error("failed to rename converted data file %s to %s", temp_file.name, file->name); g_free(temp_file.name); temp_file.name = file->name; memcpy(file, &temp_file, sizeof(struct stats_file)); }
static int stats_file_setup(struct stats_file *file) { struct stats_file_header *hdr; struct stat st; size_t size = 0; int err; DBG("file %p fd %d name %s", file, file->fd, file->name); err = fstat(file->fd, &st); if (err < 0) { connman_error("fstat error %s for %s\n", strerror(errno), file->name); TFR(close(file->fd)); g_free(file->name); file->name = NULL; return -errno; } size = (size_t)st.st_size; file->max_len = STATS_MAX_FILE_SIZE; if (size < (size_t)sysconf(_SC_PAGESIZE)) size = sysconf(_SC_PAGESIZE); err = stats_file_remap(file, size); if (err < 0) { TFR(close(file->fd)); g_free(file->name); file->name = NULL; return err; } hdr = get_hdr(file); /* Check if data file is in old format and convert */ if (hdr->magic == MAGIC32 && hdr->begin >= sizeof(struct stats_file_header) && hdr->end >= sizeof(struct stats_file_header) && hdr->home >= sizeof(struct stats_file_header) && hdr->roaming >= sizeof(struct stats_file_header) && hdr->begin <= file->len && hdr->end <= file->len) { stats_convert(file); /* conversion changes the mapped address */ hdr = get_hdr(file); } if (hdr->magic != MAGIC64 || hdr->begin < sizeof(struct stats_file_header) || hdr->end < sizeof(struct stats_file_header) || hdr->home < sizeof(struct stats_file_header) || hdr->roaming < sizeof(struct stats_file_header) || hdr->begin > file->len || hdr->end > file->len) { hdr->magic = MAGIC64; hdr->begin = sizeof(struct stats_file_header); hdr->end = sizeof(struct stats_file_header); hdr->home = UINT_MAX; hdr->roaming = UINT_MAX; stats_file_update_cache(file); } return 0; }