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