data.c 3.4 KB

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