linux/tools/perf/util/data.c
<<
>>
Prefs
   1#include <linux/compiler.h>
   2#include <linux/kernel.h>
   3#include <sys/types.h>
   4#include <sys/stat.h>
   5#include <errno.h>
   6#include <unistd.h>
   7#include <string.h>
   8
   9#include "data.h"
  10#include "util.h"
  11#include "debug.h"
  12
  13static bool check_pipe(struct perf_data_file *file)
  14{
  15        struct stat st;
  16        bool is_pipe = false;
  17        int fd = perf_data_file__is_read(file) ?
  18                 STDIN_FILENO : STDOUT_FILENO;
  19
  20        if (!file->path) {
  21                if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
  22                        is_pipe = true;
  23        } else {
  24                if (!strcmp(file->path, "-"))
  25                        is_pipe = true;
  26        }
  27
  28        if (is_pipe)
  29                file->fd = fd;
  30
  31        return file->is_pipe = is_pipe;
  32}
  33
  34static int check_backup(struct perf_data_file *file)
  35{
  36        struct stat st;
  37
  38        if (!stat(file->path, &st) && st.st_size) {
  39                /* TODO check errors properly */
  40                char oldname[PATH_MAX];
  41                snprintf(oldname, sizeof(oldname), "%s.old",
  42                         file->path);
  43                unlink(oldname);
  44                rename(file->path, oldname);
  45        }
  46
  47        return 0;
  48}
  49
  50static int open_file_read(struct perf_data_file *file)
  51{
  52        struct stat st;
  53        int fd;
  54        char sbuf[STRERR_BUFSIZE];
  55
  56        fd = open(file->path, O_RDONLY);
  57        if (fd < 0) {
  58                int err = errno;
  59
  60                pr_err("failed to open %s: %s", file->path,
  61                        str_error_r(err, sbuf, sizeof(sbuf)));
  62                if (err == ENOENT && !strcmp(file->path, "perf.data"))
  63                        pr_err("  (try 'perf record' first)");
  64                pr_err("\n");
  65                return -err;
  66        }
  67
  68        if (fstat(fd, &st) < 0)
  69                goto out_close;
  70
  71        if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
  72                pr_err("File %s not owned by current user or root (use -f to override)\n",
  73                       file->path);
  74                goto out_close;
  75        }
  76
  77        if (!st.st_size) {
  78                pr_info("zero-sized file (%s), nothing to do!\n",
  79                        file->path);
  80                goto out_close;
  81        }
  82
  83        file->size = st.st_size;
  84        return fd;
  85
  86 out_close:
  87        close(fd);
  88        return -1;
  89}
  90
  91static int open_file_write(struct perf_data_file *file)
  92{
  93        int fd;
  94        char sbuf[STRERR_BUFSIZE];
  95
  96        if (check_backup(file))
  97                return -1;
  98
  99        fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
 100
 101        if (fd < 0)
 102                pr_err("failed to open %s : %s\n", file->path,
 103                        str_error_r(errno, sbuf, sizeof(sbuf)));
 104
 105        return fd;
 106}
 107
 108static int open_file(struct perf_data_file *file)
 109{
 110        int fd;
 111
 112        fd = perf_data_file__is_read(file) ?
 113             open_file_read(file) : open_file_write(file);
 114
 115        file->fd = fd;
 116        return fd < 0 ? -1 : 0;
 117}
 118
 119int perf_data_file__open(struct perf_data_file *file)
 120{
 121        if (check_pipe(file))
 122                return 0;
 123
 124        if (!file->path)
 125                file->path = "perf.data";
 126
 127        return open_file(file);
 128}
 129
 130void perf_data_file__close(struct perf_data_file *file)
 131{
 132        close(file->fd);
 133}
 134
 135ssize_t perf_data_file__write(struct perf_data_file *file,
 136                              void *buf, size_t size)
 137{
 138        return writen(file->fd, buf, size);
 139}
 140
 141int perf_data_file__switch(struct perf_data_file *file,
 142                           const char *postfix,
 143                           size_t pos, bool at_exit)
 144{
 145        char *new_filepath;
 146        int ret;
 147
 148        if (check_pipe(file))
 149                return -EINVAL;
 150        if (perf_data_file__is_read(file))
 151                return -EINVAL;
 152
 153        if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0)
 154                return -ENOMEM;
 155
 156        /*
 157         * Only fire a warning, don't return error, continue fill
 158         * original file.
 159         */
 160        if (rename(file->path, new_filepath))
 161                pr_warning("Failed to rename %s to %s\n", file->path, new_filepath);
 162
 163        if (!at_exit) {
 164                close(file->fd);
 165                ret = perf_data_file__open(file);
 166                if (ret < 0)
 167                        goto out;
 168
 169                if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) {
 170                        ret = -errno;
 171                        pr_debug("Failed to lseek to %zu: %s",
 172                                 pos, strerror(errno));
 173                        goto out;
 174                }
 175        }
 176        ret = file->fd;
 177out:
 178        free(new_filepath);
 179        return ret;
 180}
 181