blob: d4584efad5148dba32abd2582f922210f435f6e5 [file] [log] [blame]
James Kuszmaul011b67a2019-12-15 12:52:34 -08001#include "aos/logging/log_namer.h"
2
3#include <dirent.h>
4#include <errno.h>
5#include <fcntl.h>
6#include <mntent.h>
7#include <pwd.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/types.h>
12#include <time.h>
13#include <unistd.h>
14#include <string>
15
16#include "aos/configuration.h"
17#include "glog/logging.h"
18
19namespace aos {
20namespace logging {
21namespace {
22void AllocateLogName(char **filename, const char *directory,
23 const char *basename) {
24 int fileindex = 0;
25 DIR *const d = opendir(directory);
26 if (d == nullptr) {
27 PLOG(FATAL) << "could not open directory" << directory;
28 }
29 int index = 0;
30 while (true) {
31 errno = 0;
32 struct dirent *const dir = readdir(d);
33 if (dir == nullptr) {
34 if (errno == 0) {
35 break;
36 } else {
37 PLOG(FATAL) << "readdir(" << d << ") failed";
38 }
39 } else {
40 const std::string format_string = std::string(basename) + "-%d";
41 if (sscanf(dir->d_name, format_string.c_str(), &index) == 1) {
42 if (index >= fileindex) {
43 fileindex = index + 1;
44 }
45 }
46 }
47 }
48 closedir(d);
49
50 char previous[512];
51 ::std::string path = ::std::string(directory) + "/" + basename + "-current";
52 ssize_t len = ::readlink(path.c_str(), previous, sizeof(previous));
53 if (len != -1) {
54 previous[len] = '\0';
55 } else {
56 previous[0] = '\0';
57 LOG(INFO) << "Could not find " << path;
58 }
59 if (asprintf(filename, "%s/%s-%03d", directory, basename, fileindex) == -1) {
60 PLOG(FATAL) << "couldn't create final name";
61 }
62 LOG(INFO) << "Created log file (" << basename << "-" << fileindex
63 << ") in directory (" << directory
64 << "). Previous file "
65 "was ("
66 << previous << ").";
67}
68
69#ifdef AOS_ARCHITECTURE_arm_frc
70bool FoundThumbDrive(const char *path) {
71 FILE *mnt_fp = setmntent("/etc/mtab", "r");
72 if (mnt_fp == nullptr) {
73 LOG(FATAL) << "Could not open /etc/mtab";
74 }
75
76 bool found = false;
77 struct mntent mntbuf;
78 char buf[256];
79 while (!found) {
80 struct mntent *mount_list = getmntent_r(mnt_fp, &mntbuf, buf, sizeof(buf));
81 if (mount_list == nullptr) {
82 break;
83 }
84 if (strcmp(mount_list->mnt_dir, path) == 0) {
85 found = true;
86 }
87 }
88 endmntent(mnt_fp);
89 return found;
90}
91
92bool FindDevice(char *device, size_t device_size) {
93 char test_device[10];
94 for (char i = 'a'; i < 'z'; ++i) {
95 snprintf(test_device, sizeof(test_device), "/dev/sd%c", i);
96 LOG(INFO) << "Trying to access" << test_device;
97 if (access(test_device, F_OK) != -1) {
98 snprintf(device, device_size, "sd%c", i);
99 return true;
100 }
101 }
102 return false;
103}
104#endif
105} // namespace
106
107std::string GetLogName(const char *basename) {
108#ifdef AOS_ARCHITECTURE_arm_frc
109 char folder[128];
110 {
111 char dev_name[8];
112 while (!FindDevice(dev_name, sizeof(dev_name))) {
113 LOG(INFO) << "Waiting for a device";
114 sleep(5);
115 }
116 snprintf(folder, sizeof(folder), "/media/%s1", dev_name);
117 while (!FoundThumbDrive(folder)) {
118 LOG(INFO) << "Waiting for" << folder;
119 sleep(1);
120 }
121 snprintf(folder, sizeof(folder), "/media/%s1/", dev_name);
122 }
123
124 if (access(folder, F_OK) == -1) {
125#else
126 const char *folder = configuration::GetLoggingDirectory();
127 if (access(folder, R_OK | W_OK) == -1) {
128#endif
129 LOG(FATAL) << "folder '" << folder << "' does not exist. please create it.";
130 }
131 LOG(INFO) << "logging to folder '" << folder << "'";
132
133 char *tmp;
134 AllocateLogName(&tmp, folder, basename);
135 char *tmp2;
136 if (asprintf(&tmp2, "%s/%s-current", folder, basename) == -1) {
137 PLOG(WARNING) << "couldn't create current symlink name";
138 } else {
139 if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
140 LOG(WARNING) << "unlink('" << tmp2 << "') failed";
141 }
142 if (symlink(tmp, tmp2) == -1) {
143 PLOG(WARNING) << "symlink('" << tmp << "', '" << tmp2 << "') failed";
144 }
145 free(tmp2);
146 }
147 std::string result = tmp;
148 free(tmp);
149 return result;
150}
151
152} // namespace logging
153} // namespace aos