gint lutil_file_open(lutil_file_open_t p) { gchar *mode; g_assert(p != NULL); g_assert(p->xperr != NULL); g_assert(p->fpath != NULL); p->result.skip_retrieved_already = FALSE; p->result.initial_bytes = 0; p->result.file = NULL; mode = "wb"; if (p->overwrite_if_exists == FALSE) { if (g_file_test(p->fpath, G_FILE_TEST_EXISTS) == TRUE) { if (_chk_len(p, &mode) != EXIT_SUCCESS) return (EXIT_FAILURE); } } p->result.file = fopen(p->fpath, mode); if (p->result.file == NULL) return (_perr(p, "fopen")); return (EXIT_SUCCESS); }
/** * process_subbufs - write ready subbufs to disk */ static int process_subbufs(struct _stp_buf_info *info, struct switchfile_ctrl_block *scb) { unsigned subbufs_ready, start_subbuf, end_subbuf, subbuf_idx, i; int len, cpu = info->cpu; char *subbuf_ptr; int subbufs_consumed = 0; unsigned padding; subbufs_ready = info->produced - info->consumed; start_subbuf = info->consumed % n_subbufs; end_subbuf = start_subbuf + subbufs_ready; for (i = start_subbuf; i < end_subbuf; i++) { subbuf_idx = i % n_subbufs; subbuf_ptr = relay_buffer[cpu] + subbuf_idx * subbuf_size; padding = *((unsigned *)subbuf_ptr); subbuf_ptr += sizeof(padding); len = (subbuf_size - sizeof(padding)) - padding; scb->wsize += len; if (fsize_max && scb->wsize > fsize_max) { if (switch_oldoutfile(cpu, scb) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); return -1; } scb->wsize = len; } if (len) { #ifdef __ANDROID__ if (fwrite (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { #else if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { #endif if (errno != EPIPE) _perr("Couldn't write to output file for cpu %d, exiting:", cpu); return -1; } } subbufs_consumed++; } return subbufs_consumed; } /** * reader_thread - per-cpu channel buffer reader */ static void *reader_thread(void *data) { int rc; int cpu = (long)data; struct pollfd pollfd; struct _stp_consumed_info consumed_info; unsigned subbufs_consumed; cpu_set_t cpu_mask; struct timespec tim = {.tv_sec=0, .tv_nsec=200000000}, *timeout = &tim;
static gint _chk_len(lutil_file_open_t p, gchar **mode) { #ifdef HAVE_GLIB_2_26 GStatBuf b; #else struct stat b; #endif if (g_stat(p->fpath, &b) == -1) return (_perr(p, "g_stat")); if (b.st_size >= p->content_bytes) { p->result.skip_retrieved_already = TRUE; return (_perr(p, NULL)); } else if (b.st_size < p->content_bytes) { p->result.initial_bytes = b.st_size; if (mode != NULL) *mode = "ab"; } return (EXIT_SUCCESS); }
/** * process_subbufs - write ready subbufs to disk */ static int process_subbufs(struct _stp_buf_info *info, struct switchfile_ctrl_block *scb) { unsigned subbufs_ready, start_subbuf, end_subbuf, subbuf_idx, i; int len, cpu = info->cpu; char *subbuf_ptr; int subbufs_consumed = 0; unsigned padding; subbufs_ready = info->produced - info->consumed; start_subbuf = info->consumed % n_subbufs; end_subbuf = start_subbuf + subbufs_ready; for (i = start_subbuf; i < end_subbuf; i++) { subbuf_idx = i % n_subbufs; subbuf_ptr = relay_buffer[cpu] + subbuf_idx * subbuf_size; padding = *((unsigned *)subbuf_ptr); subbuf_ptr += sizeof(padding); len = (subbuf_size - sizeof(padding)) - padding; scb->wsize += len; if (fsize_max && scb->wsize > fsize_max) { if (switch_oldoutfile(cpu, scb) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); return -1; } scb->wsize = len; } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { if (errno != EPIPE) _perr("Couldn't write to output file for cpu %d, exiting:", cpu); return -1; } } subbufs_consumed++; } return subbufs_consumed; }
/** * open_relayfs_files - open and mmap buffer and open output file. * Returns -1 on unexpected failure, 0 if file not found, 1 on success. */ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *proc_filebase) { size_t total_bufsize; char tmp[PATH_MAX]; memset(&status[cpu], 0, sizeof(struct buf_status)); status[cpu].info.cpu = cpu; if (sprintf_chk(tmp, "%s%d", relay_filebase, cpu)) return -1; dbug(2, "Opening %s.\n", tmp); relay_fd[cpu] = open(tmp, O_RDONLY | O_NONBLOCK); if (relay_fd[cpu] < 0 || set_clexec(relay_fd[cpu]) < 0) { relay_fd[cpu] = 0; return 0; } if (sprintf_chk(tmp, "%s%d", proc_filebase, cpu)) goto err1; dbug(2, "Opening %s.\n", tmp); proc_fd[cpu] = open(tmp, O_RDWR | O_NONBLOCK); if (proc_fd[cpu] < 0) { perr("Couldn't open proc file %s", tmp); goto err1; } if (set_clexec(relay_fd[cpu]) < 0) { relay_fd[cpu] = 0; return -1; } if (fsize_max) { if (init_backlog(cpu) < 0) goto err2; if (open_oldoutfile(0, cpu, 0) < 0) goto err2; goto opened; } if (outfile_name) { /* special case: for testing we sometimes want to * write to /dev/null */ if (strcmp(outfile_name, "/dev/null") == 0) { strcpy(tmp, "/dev/null"); } else { int len; len = stap_strfloctime(tmp, PATH_MAX, outfile_name, time(NULL)); if (len < 0) { err("Invalid FILE name format\n"); goto err2; } if (snprintf_chk(&tmp[len], PATH_MAX - len, "_%d", cpu)) goto err2; } } else { if (sprintf_chk(tmp, "stpd_cpu%d", cpu)) goto err2; } if((percpu_tmpfile[cpu] = fopen(tmp, "w+")) == NULL) { perr("Couldn't open output file %s", tmp); goto err2; } out_fd[cpu] = fileno(percpu_tmpfile[cpu]); if (set_clexec(out_fd[cpu]) < 0) { perr("Couldn't open output file %s", tmp); goto err2; } opened: total_bufsize = subbuf_size * n_subbufs; relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, relay_fd[cpu], 0); if(relay_buffer[cpu] == MAP_FAILED) { _perr("Couldn't mmap relay file, total_bufsize (%d)" \ "= subbuf_size (%d) * n_subbufs(%d)", (int)total_bufsize, (int)subbuf_size, (int)n_subbufs); goto err3; } return 1; err3: fclose(percpu_tmpfile[cpu]); err2: close (proc_fd[cpu]); err1: close (relay_fd[cpu]); relay_fd[cpu] = 0; return -1; }