| #include "aos/logging/log_namer.h" |
| |
| #include <dirent.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <mntent.h> |
| #include <pwd.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <time.h> |
| #include <unistd.h> |
| #include <string> |
| |
| #include "aos/configuration.h" |
| #include "glog/logging.h" |
| |
| DEFINE_string(logging_folder, |
| #ifdef AOS_ARCHITECTURE_arm_frc |
| "", |
| #else |
| "./logs", |
| #endif |
| "The folder to log to. If empty, search for the /media/sd*1/ " |
| "folder and place logs there."); |
| |
| namespace aos { |
| namespace logging { |
| namespace { |
| void AllocateLogName(char **filename, const char *directory, |
| const char *basename) { |
| int fileindex = 0; |
| DIR *const d = opendir(directory); |
| if (d == nullptr) { |
| PLOG(FATAL) << "could not open directory" << directory; |
| } |
| int index = 0; |
| while (true) { |
| errno = 0; |
| struct dirent *const dir = readdir(d); |
| if (dir == nullptr) { |
| if (errno == 0) { |
| break; |
| } else { |
| PLOG(FATAL) << "readdir(" << d << ") failed"; |
| } |
| } else { |
| const std::string format_string = std::string(basename) + "-%d"; |
| if (sscanf(dir->d_name, format_string.c_str(), &index) == 1) { |
| if (index >= fileindex) { |
| fileindex = index + 1; |
| } |
| } |
| } |
| } |
| closedir(d); |
| |
| char previous[512]; |
| ::std::string path = ::std::string(directory) + "/" + basename + "-current"; |
| ssize_t len = ::readlink(path.c_str(), previous, sizeof(previous)); |
| if (len != -1) { |
| previous[len] = '\0'; |
| } else { |
| previous[0] = '\0'; |
| LOG(INFO) << "Could not find " << path; |
| } |
| if (asprintf(filename, "%s/%s-%03d", directory, basename, fileindex) == -1) { |
| PLOG(FATAL) << "couldn't create final name"; |
| } |
| LOG(INFO) << "Created log file (" << basename << "-" << fileindex |
| << ") in directory (" << directory |
| << "). Previous file " |
| "was (" |
| << previous << ")."; |
| } |
| |
| bool FoundThumbDrive(const char *path) { |
| FILE *mnt_fp = setmntent("/etc/mtab", "r"); |
| if (mnt_fp == nullptr) { |
| LOG(FATAL) << "Could not open /etc/mtab"; |
| } |
| |
| bool found = false; |
| struct mntent mntbuf; |
| char buf[256]; |
| while (!found) { |
| struct mntent *mount_list = getmntent_r(mnt_fp, &mntbuf, buf, sizeof(buf)); |
| if (mount_list == nullptr) { |
| break; |
| } |
| if (strcmp(mount_list->mnt_dir, path) == 0) { |
| found = true; |
| } |
| } |
| endmntent(mnt_fp); |
| return found; |
| } |
| |
| bool FindDevice(char *device, size_t device_size) { |
| char test_device[10]; |
| for (char i = 'a'; i < 'z'; ++i) { |
| snprintf(test_device, sizeof(test_device), "/dev/sd%c", i); |
| VLOG(1) << "Trying to access" << test_device; |
| if (access(test_device, F_OK) != -1) { |
| snprintf(device, device_size, "sd%c", i); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| } // namespace |
| |
| std::string GetLogName(const char *basename) { |
| if (FLAGS_logging_folder.empty()) { |
| char folder[128]; |
| { |
| char dev_name[8]; |
| while (!FindDevice(dev_name, sizeof(dev_name))) { |
| LOG(INFO) << "Waiting for a device"; |
| sleep(5); |
| } |
| snprintf(folder, sizeof(folder), "/media/%s1", dev_name); |
| while (!FoundThumbDrive(folder)) { |
| LOG(INFO) << "Waiting for" << folder; |
| sleep(1); |
| } |
| snprintf(folder, sizeof(folder), "/media/%s1/", dev_name); |
| } |
| |
| if (access(folder, F_OK) == -1) { |
| LOG(FATAL) << "folder '" << folder |
| << "' does not exist. please create it."; |
| } |
| |
| FLAGS_logging_folder = folder; |
| } |
| const char *folder = FLAGS_logging_folder.c_str(); |
| if (access(folder, R_OK | W_OK) == -1) { |
| LOG(FATAL) << "folder '" << folder << "' does not exist. please create it."; |
| } |
| LOG(INFO) << "logging to folder '" << folder << "'"; |
| |
| char *tmp; |
| AllocateLogName(&tmp, folder, basename); |
| |
| std::string log_base_name = tmp; |
| std::string log_roborio_name = log_base_name + "_roborio_data.bfbs"; |
| free(tmp); |
| |
| char *tmp2; |
| if (asprintf(&tmp2, "%s/%s-current.bfbs", folder, basename) == -1) { |
| PLOG(WARNING) << "couldn't create current symlink name"; |
| } else { |
| if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) { |
| LOG(WARNING) << "unlink('" << tmp2 << "') failed"; |
| } |
| if (symlink(log_roborio_name.c_str(), tmp2) == -1) { |
| PLOG(WARNING) << "symlink('" << log_roborio_name.c_str() << "', '" << tmp2 |
| << "') failed"; |
| } |
| free(tmp2); |
| } |
| return log_base_name; |
| } |
| |
| } // namespace logging |
| } // namespace aos |