#include <dirent.h>
#include <byteswap.h>
#include <inttypes.h>
+#include <stdbool.h>
#include <version.h>
#include <lttng/lttng.h>
struct crash_abi_unknown {
uint8_t magic[RB_CRASH_DUMP_ABI_MAGIC_LEN];
- uint64_t mmap_length; /* Overall lenght of crash record */
+ uint64_t mmap_length; /* Overall length of crash record */
uint16_t endian; /*
* { 0x12, 0x34 }: big endian
* { 0x34, 0x12 }: little endian
exit(EXIT_FAILURE);
}
- while ((opt = getopt_long(argc, argv, "+Vhvex:", long_options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+Vhve:x:", long_options, NULL)) != -1) {
switch (opt) {
case 'V':
version(stdout);
static
int copy_file(const char *file_dest, const char *file_src)
{
- int fd_src, fd_dest;
+ int fd_src = -1, fd_dest = -1;
ssize_t readlen, writelen;
char buf[COPY_BUFLEN];
+ int ret;
DBG("Copy metadata file '%s' into '%s'", file_src, file_dest);
fd_src = open(file_src, O_RDONLY);
if (fd_src < 0) {
PERROR("Error opening %s for reading", file_src);
- return fd_src;
+ ret = -errno;
+ goto error;
}
fd_dest = open(file_dest, O_RDWR | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (fd_dest < 0) {
PERROR("Error opening %s for writing", file_dest);
- return fd_dest;
+ ret = -errno;
+ goto error;
}
for (;;) {
readlen = lttng_read(fd_src, buf, COPY_BUFLEN);
if (readlen < 0) {
PERROR("Error reading input file");
- return -1;
+ ret = -1;
+ goto error;
}
if (!readlen) {
break;
writelen = lttng_write(fd_dest, buf, readlen);
if (writelen < readlen) {
PERROR("Error writing to output file");
- return -1;
+ ret = -1;
+ goto error;
}
}
- return 0;
+
+ ret = 0;
+error:
+ if (fd_src >= 0) {
+ if (close(fd_src) < 0) {
+ PERROR("Error closing %s", file_src);
+ }
+ }
+
+ if (fd_dest >= 0) {
+ if (close(fd_dest) < 0) {
+ PERROR("Error closing %s", file_dest);
+ }
+ }
+ return ret;
}
static
}
static
-int delete_trace(const char *trace_path)
+int delete_dir_recursive(const char *path)
{
- DIR *trace_dir;
- int trace_dir_fd, ret = 0, closeret;
+ DIR *dir;
+ int dir_fd, ret = 0, closeret;
struct dirent *entry;
/* Open trace directory */
- trace_dir = opendir(trace_path);
- if (!trace_dir) {
- PERROR("Cannot open '%s' path", trace_path);
- return -1;
+ dir = opendir(path);
+ if (!dir) {
+ PERROR("Cannot open '%s' path", path);
+ ret = -errno;
+ goto end;
}
- trace_dir_fd = dirfd(trace_dir);
- if (trace_dir_fd < 0) {
+ dir_fd = dirfd(dir);
+ if (dir_fd < 0) {
PERROR("dirfd");
- return -1;
+ ret = -errno;
+ goto end;
}
- while ((entry = readdir(trace_dir))) {
+ while ((entry = readdir(dir))) {
if (!strcmp(entry->d_name, ".")
|| !strcmp(entry->d_name, "..")) {
continue;
}
switch (entry->d_type) {
case DT_DIR:
- unlinkat(trace_dir_fd, entry->d_name, AT_REMOVEDIR);
+ {
+ char *subpath = zmalloc(PATH_MAX);
+
+ if (!subpath) {
+ PERROR("zmalloc path");
+ ret = -1;
+ goto end;
+ }
+ strncpy(subpath, path, PATH_MAX);
+ subpath[PATH_MAX - 1] = '\0';
+ strncat(subpath, "/",
+ PATH_MAX - strlen(subpath) - 1);
+ strncat(subpath, entry->d_name,
+ PATH_MAX - strlen(subpath) - 1);
+
+ ret = delete_dir_recursive(subpath);
+ free(subpath);
+ if (ret) {
+ /* Error occured, abort traversal. */
+ goto end;
+ }
break;
+ }
case DT_REG:
- unlinkat(trace_dir_fd, entry->d_name, 0);
+ ret = unlinkat(dir_fd, entry->d_name, 0);
+ if (ret) {
+ PERROR("Unlinking '%s'", entry->d_name);
+ goto end;
+ }
break;
default:
ret = -EINVAL;
}
}
end:
- closeret = closedir(trace_dir);
+ if (!ret) {
+ ret = rmdir(path);
+ if (ret) {
+ PERROR("rmdir '%s'", path);
+ }
+ }
+ closeret = closedir(dir);
if (closeret) {
PERROR("closedir");
}
- if (!ret) {
- ret = rmdir(trace_path);
- }
return ret;
}
*/
int main(int argc, char *argv[])
{
- int ret, has_warning = 0;
+ int ret;
+ bool has_warning = false;
const char *output_path = NULL;
char tmppath[] = "/tmp/lttng-crash-XXXXXX";
ret = parse_args(argc, argv);
if (ret > 0) {
- exit(EXIT_SUCCESS);
+ goto end;
} else if (ret < 0) {
- exit(EXIT_FAILURE);
+ has_warning = true;
+ goto end;
}
if (opt_output_path) {
ret = mkdir(output_path, S_IRWXU | S_IRWXG);
if (ret) {
PERROR("mkdir");
- exit(EXIT_FAILURE);
+ has_warning = true;
+ goto end;
}
} else {
output_path = mkdtemp(tmppath);
if (!output_path) {
PERROR("mkdtemp");
- exit(EXIT_FAILURE);
+ has_warning = true;
+ goto end;
}
}
ret = extract_trace_recursive(output_path, input_path);
if (ret < 0) {
- exit(EXIT_FAILURE);
+ has_warning = true;
+ goto end;
} else if (ret > 0) {
- has_warning = 1;
+ /* extract_trace_recursive reported a warning. */
+ has_warning = true;
}
if (!opt_output_path) {
/* View trace */
ret = view_trace(opt_viewer_path, output_path);
- if (ret)
- has_warning = 1;
-
+ if (ret) {
+ has_warning = true;
+ }
/* unlink temporary trace */
- ret = delete_trace(output_path);
- if (ret)
- has_warning = 1;
+ ret = delete_dir_recursive(output_path);
+ if (ret) {
+ has_warning = true;
+ }
}
- if (has_warning)
- exit(EXIT_FAILURE);
- exit(EXIT_SUCCESS);
+end:
+ exit(has_warning ? EXIT_FAILURE : EXIT_SUCCESS);
}