1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <linux/kernel.h>
11 #include <sys/types.h>
19 static void close_dir(struct perf_data_file
*files
, int nr
)
28 void perf_data__close_dir(struct perf_data
*data
)
30 close_dir(data
->dir
.files
, data
->dir
.nr
);
33 int perf_data__create_dir(struct perf_data
*data
, int nr
)
35 struct perf_data_file
*files
= NULL
;
38 if (WARN_ON(!data
->is_dir
))
41 files
= zalloc(nr
* sizeof(*files
));
45 data
->dir
.version
= PERF_DIR_VERSION
;
46 data
->dir
.files
= files
;
49 for (i
= 0; i
< nr
; i
++) {
50 struct perf_data_file
*file
= &files
[i
];
52 if (asprintf(&file
->path
, "%s/data.%d", data
->path
, i
) < 0)
55 ret
= open(file
->path
, O_RDWR
|O_CREAT
|O_TRUNC
, S_IRUSR
|S_IWUSR
);
69 int perf_data__open_dir(struct perf_data
*data
)
71 struct perf_data_file
*files
= NULL
;
77 if (WARN_ON(!data
->is_dir
))
80 /* The version is provided by DIR_FORMAT feature. */
81 if (WARN_ON(data
->dir
.version
!= PERF_DIR_VERSION
))
84 dir
= opendir(data
->path
);
88 while ((dent
= readdir(dir
)) != NULL
) {
89 struct perf_data_file
*file
;
93 snprintf(path
, sizeof(path
), "%s/%s", data
->path
, dent
->d_name
);
97 if (!S_ISREG(st
.st_mode
) || strncmp(dent
->d_name
, "data", 4))
102 file
= realloc(files
, (nr
+ 1) * sizeof(*files
));
109 file
->path
= strdup(path
);
113 ret
= open(file
->path
, O_RDONLY
);
118 file
->size
= st
.st_size
;
124 data
->dir
.files
= files
;
129 close_dir(files
, nr
);
133 int perf_data__update_dir(struct perf_data
*data
)
137 if (WARN_ON(!data
->is_dir
))
140 for (i
= 0; i
< data
->dir
.nr
; i
++) {
141 struct perf_data_file
*file
= &data
->dir
.files
[i
];
144 if (fstat(file
->fd
, &st
))
147 file
->size
= st
.st_size
;
153 static bool check_pipe(struct perf_data
*data
)
156 bool is_pipe
= false;
157 int fd
= perf_data__is_read(data
) ?
158 STDIN_FILENO
: STDOUT_FILENO
;
161 if (!fstat(fd
, &st
) && S_ISFIFO(st
.st_mode
))
164 if (!strcmp(data
->path
, "-"))
171 return data
->is_pipe
= is_pipe
;
174 static int check_backup(struct perf_data
*data
)
178 if (perf_data__is_read(data
))
181 if (!stat(data
->path
, &st
) && st
.st_size
) {
182 char oldname
[PATH_MAX
];
185 snprintf(oldname
, sizeof(oldname
), "%s.old",
188 ret
= rm_rf_perf_data(oldname
);
190 pr_err("Can't remove old data: %s (%s)\n",
192 "Unknown file found" : strerror(errno
),
197 if (rename(data
->path
, oldname
)) {
198 pr_err("Can't move data: %s (%s to %s)\n",
200 data
->path
, oldname
);
208 static bool is_dir(struct perf_data
*data
)
212 if (stat(data
->path
, &st
))
215 return (st
.st_mode
& S_IFMT
) == S_IFDIR
;
218 static int open_file_read(struct perf_data
*data
)
222 char sbuf
[STRERR_BUFSIZE
];
224 fd
= open(data
->file
.path
, O_RDONLY
);
228 pr_err("failed to open %s: %s", data
->file
.path
,
229 str_error_r(err
, sbuf
, sizeof(sbuf
)));
230 if (err
== ENOENT
&& !strcmp(data
->file
.path
, "perf.data"))
231 pr_err(" (try 'perf record' first)");
236 if (fstat(fd
, &st
) < 0)
239 if (!data
->force
&& st
.st_uid
&& (st
.st_uid
!= geteuid())) {
240 pr_err("File %s not owned by current user or root (use -f to override)\n",
246 pr_info("zero-sized data (%s), nothing to do!\n",
251 data
->file
.size
= st
.st_size
;
259 static int open_file_write(struct perf_data
*data
)
262 char sbuf
[STRERR_BUFSIZE
];
264 fd
= open(data
->file
.path
, O_CREAT
|O_RDWR
|O_TRUNC
|O_CLOEXEC
,
268 pr_err("failed to open %s : %s\n", data
->file
.path
,
269 str_error_r(errno
, sbuf
, sizeof(sbuf
)));
274 static int open_file(struct perf_data
*data
)
278 fd
= perf_data__is_read(data
) ?
279 open_file_read(data
) : open_file_write(data
);
282 zfree(&data
->file
.path
);
290 static int open_file_dup(struct perf_data
*data
)
292 data
->file
.path
= strdup(data
->path
);
293 if (!data
->file
.path
)
296 return open_file(data
);
299 static int open_dir(struct perf_data
*data
)
304 * So far we open only the header, so we can read the data version and
307 if (asprintf(&data
->file
.path
, "%s/header", data
->path
) < 0)
310 if (perf_data__is_write(data
) &&
311 mkdir(data
->path
, S_IRWXU
) < 0)
314 ret
= open_file(data
);
316 /* Cleanup whatever we managed to create so far. */
317 if (ret
&& perf_data__is_write(data
))
318 rm_rf_perf_data(data
->path
);
323 int perf_data__open(struct perf_data
*data
)
325 if (check_pipe(data
))
329 data
->path
= "perf.data";
331 if (check_backup(data
))
334 if (perf_data__is_read(data
))
335 data
->is_dir
= is_dir(data
);
337 return perf_data__is_dir(data
) ?
338 open_dir(data
) : open_file_dup(data
);
341 void perf_data__close(struct perf_data
*data
)
343 if (perf_data__is_dir(data
))
344 perf_data__close_dir(data
);
346 zfree(&data
->file
.path
);
347 close(data
->file
.fd
);
350 ssize_t
perf_data_file__write(struct perf_data_file
*file
,
351 void *buf
, size_t size
)
353 return writen(file
->fd
, buf
, size
);
356 ssize_t
perf_data__write(struct perf_data
*data
,
357 void *buf
, size_t size
)
359 return perf_data_file__write(&data
->file
, buf
, size
);
362 int perf_data__switch(struct perf_data
*data
,
364 size_t pos
, bool at_exit
,
369 if (check_pipe(data
))
371 if (perf_data__is_read(data
))
374 if (asprintf(new_filepath
, "%s.%s", data
->path
, postfix
) < 0)
378 * Only fire a warning, don't return error, continue fill
381 if (rename(data
->path
, *new_filepath
))
382 pr_warning("Failed to rename %s to %s\n", data
->path
, *new_filepath
);
385 close(data
->file
.fd
);
386 ret
= perf_data__open(data
);
390 if (lseek(data
->file
.fd
, pos
, SEEK_SET
) == (off_t
)-1) {
392 pr_debug("Failed to lseek to %zu: %s",
393 pos
, strerror(errno
));
402 unsigned long perf_data__size(struct perf_data
*data
)
404 u64 size
= data
->file
.size
;
410 for (i
= 0; i
< data
->dir
.nr
; i
++) {
411 struct perf_data_file
*file
= &data
->dir
.files
[i
];