#include #include #include #include #include #include #include #include #include #include #include "storage.h" #include "recorder.h" static int g_out_fd = -1;; static uint64_t g_written_bytes; static const char *storage_gen_filename(void) { static char buf[32]; time_t t; struct tm *tmp; t = time(NULL); tmp = localtime(&t); strftime(buf, sizeof(buf), "%Y%m%d%H%M%S.e1cap", tmp); return buf; } void storage_close(void) { LOGP(DMAIN, LOGL_INFO, "Closing Log file\n"); close(g_out_fd); g_out_fd = -1; } static int storage_reopen_if_needed(void) { if (g_written_bytes / (1024*1024) >= g_recorder.max_file_size_mb) { storage_close(); /* we re-open below */ } if (g_out_fd < 0) { int rc; const char *fname = storage_gen_filename(); LOGP(DMAIN, LOGL_INFO, "Opening Log file %s\n", fname); rc = chdir(g_recorder.storage_path); if (rc < 0) { LOGP(DMAIN, LOGL_ERROR, "Unable to chdir(%s): %s\n", g_recorder.storage_path, strerror(errno)); return -1; } g_out_fd = open(fname, O_WRONLY|O_CREAT, 0664); if (g_out_fd < 0) { LOGP(DMAIN, LOGL_ERROR, "Unable to open(%s): %s\n", fname, strerror(errno)); } g_written_bytes = 0; } return g_out_fd; } int e1frame_store(struct e1inp_ts *ts, struct msgb *msg, enum osmo_e1cap_capture_mode mode) { struct osmo_e1cap_pkthdr _h, *h = &_h; struct timeval tv; int rc; struct iovec iov[2] = { { .iov_base = h, .iov_len = sizeof(*h), }, { .iov_base = msg->data, .iov_len = msg->len, } }; h->len = htonl(msg->len); gettimeofday(&tv, NULL); h->ts.tv_sec = tv.tv_sec; h->ts.tv_usec = tv.tv_usec; h->line_nr = ts->line->num; h->ts_nr = ts->num; h->capture_mode = mode; h->flags = 0; rc = storage_reopen_if_needed(); if (rc < 0) return rc; rc = writev(g_out_fd, iov, ARRAY_SIZE(iov)); if (rc < 0) return rc; g_written_bytes += rc; return 0; } /* reading */ struct osmo_e1cap_file { int fd; }; #define OSMO_E1REC_ALLOC_SIZE 1024 struct osmo_e1cap_file *osmo_e1cap_open(void *ctx, const char *path) { struct osmo_e1cap_file *f = talloc_zero(ctx, struct osmo_e1cap_file); if (!f) return NULL; f->fd = open(path, O_RDONLY); if (f->fd < 0) { talloc_free(f); return NULL; } return f; } struct osmo_e1cap_pkthdr *osmo_e1cap_read_next(struct osmo_e1cap_file *f) { struct osmo_e1cap_pkthdr *pkt = talloc_zero_size(f, OSMO_E1REC_ALLOC_SIZE); int rc; if (!pkt) return NULL; /* read header */ rc = read(f->fd, (uint8_t *)pkt, sizeof(*pkt)); if (rc < sizeof(*pkt)) { talloc_free(pkt); return NULL; } pkt->len = ntohl(pkt->len); /* read data */ if (pkt->len > OSMO_E1REC_ALLOC_SIZE - sizeof(*pkt)) { pkt = talloc_realloc_size(f, pkt, sizeof(*pkt) + pkt->len); if (!pkt) return NULL; } rc = read(f->fd, (uint8_t*)(pkt+1), pkt->len); if (rc < pkt->len) { talloc_free(pkt); return NULL; } return pkt; }