data.c 3.6 KB

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