blob: dd8eb804dc99863f67aa42825c0f34b7ff317aca [file] [log] [blame]
Jon Medhurste31266f2014-08-04 15:47:44 +01001/**
2 * Copyright (C) ARM Limited 2014. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include "FSDriver.h"
10
11#include <fcntl.h>
12#include <regex.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
Jon Medhurste31266f2014-08-04 15:47:44 +010017#include "DriverSource.h"
18#include "Logging.h"
Jon Medhurste31266f2014-08-04 15:47:44 +010019
Jon Medhurst96b56152014-10-30 18:01:15 +000020class FSCounter : public DriverCounter {
Jon Medhurste31266f2014-08-04 15:47:44 +010021public:
Jon Medhurst96b56152014-10-30 18:01:15 +000022 FSCounter(DriverCounter *next, char *name, char *path, const char *regex);
Jon Medhurste31266f2014-08-04 15:47:44 +010023 ~FSCounter();
24
Jon Medhurst96b56152014-10-30 18:01:15 +000025 const char *getPath() const { return mPath; }
26
Jon Medhurste31266f2014-08-04 15:47:44 +010027 int64_t read();
28
29private:
Jon Medhurst96b56152014-10-30 18:01:15 +000030 char *const mPath;
31 regex_t mReg;
32 bool mUseRegex;
Jon Medhurste31266f2014-08-04 15:47:44 +010033
34 // Intentionally unimplemented
35 FSCounter(const FSCounter &);
36 FSCounter &operator=(const FSCounter &);
37};
38
Jon Medhurst96b56152014-10-30 18:01:15 +000039FSCounter::FSCounter(DriverCounter *next, char *name, char *path, const char *regex) : DriverCounter(next, name), mPath(path), mUseRegex(regex != NULL) {
40 if (mUseRegex) {
41 int result = regcomp(&mReg, regex, REG_EXTENDED);
Jon Medhurste31266f2014-08-04 15:47:44 +010042 if (result != 0) {
43 char buf[128];
Jon Medhurst96b56152014-10-30 18:01:15 +000044 regerror(result, &mReg, buf, sizeof(buf));
Jon Medhurste31266f2014-08-04 15:47:44 +010045 logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
46 handleException();
47 }
48 }
49}
50
51FSCounter::~FSCounter() {
Jon Medhurst96b56152014-10-30 18:01:15 +000052 free(mPath);
53 if (mUseRegex) {
54 regfree(&mReg);
Jon Medhurste31266f2014-08-04 15:47:44 +010055 }
56}
57
58int64_t FSCounter::read() {
59 int64_t value;
Jon Medhurst96b56152014-10-30 18:01:15 +000060 if (mUseRegex) {
Jon Medhurste31266f2014-08-04 15:47:44 +010061 char buf[4096];
62 size_t pos = 0;
Jon Medhurst96b56152014-10-30 18:01:15 +000063 const int fd = open(mPath, O_RDONLY | O_CLOEXEC);
Jon Medhurste31266f2014-08-04 15:47:44 +010064 if (fd < 0) {
65 goto fail;
66 }
67 while (pos < sizeof(buf) - 1) {
68 const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
69 if (bytes < 0) {
70 goto fail;
71 } else if (bytes == 0) {
72 break;
73 }
74 pos += bytes;
75 }
76 close(fd);
77 buf[pos] = '\0';
78
79 regmatch_t match[2];
Jon Medhurst96b56152014-10-30 18:01:15 +000080 int result = regexec(&mReg, buf, 2, match, 0);
Jon Medhurste31266f2014-08-04 15:47:44 +010081 if (result != 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +000082 regerror(result, &mReg, buf, sizeof(buf));
83 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, buf);
Jon Medhurste31266f2014-08-04 15:47:44 +010084 handleException();
85 }
86
87 if (match[1].rm_so < 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +000088 logg->logError(__FILE__, __LINE__, "Parsing %s failed", mPath);
Jon Medhurste31266f2014-08-04 15:47:44 +010089 handleException();
90 }
Jon Medhurst96b56152014-10-30 18:01:15 +000091
Jon Medhurste31266f2014-08-04 15:47:44 +010092 errno = 0;
Jon Medhurst96b56152014-10-30 18:01:15 +000093 value = strtoll(buf + match[1].rm_so, NULL, 0);
Jon Medhurste31266f2014-08-04 15:47:44 +010094 if (errno != 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +000095 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, strerror(errno));
Jon Medhurste31266f2014-08-04 15:47:44 +010096 handleException();
97 }
98 } else {
Jon Medhurst96b56152014-10-30 18:01:15 +000099 if (DriverSource::readInt64Driver(mPath, &value) != 0) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100100 goto fail;
101 }
102 }
103 return value;
104
105 fail:
Jon Medhurst96b56152014-10-30 18:01:15 +0000106 logg->logError(__FILE__, __LINE__, "Unable to read %s", mPath);
Jon Medhurste31266f2014-08-04 15:47:44 +0100107 handleException();
108}
109
Jon Medhurst96b56152014-10-30 18:01:15 +0000110FSDriver::FSDriver() {
Jon Medhurste31266f2014-08-04 15:47:44 +0100111}
112
113FSDriver::~FSDriver() {
Jon Medhurste31266f2014-08-04 15:47:44 +0100114}
115
Jon Medhurst96b56152014-10-30 18:01:15 +0000116void FSDriver::readEvents(mxml_node_t *const xml) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100117 mxml_node_t *node = xml;
118 while (true) {
119 node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
120 if (node == NULL) {
121 break;
122 }
123 const char *counter = mxmlElementGetAttr(node, "counter");
Jon Medhurst96b56152014-10-30 18:01:15 +0000124 if (counter == NULL) {
125 continue;
Jon Medhurste31266f2014-08-04 15:47:44 +0100126 }
Jon Medhurste31266f2014-08-04 15:47:44 +0100127
Jon Medhurst96b56152014-10-30 18:01:15 +0000128 if (counter[0] == '/') {
129 logg->logError(__FILE__, __LINE__, "Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter);
130 handleException();
Jon Medhurste31266f2014-08-04 15:47:44 +0100131 }
Jon Medhurste31266f2014-08-04 15:47:44 +0100132
Jon Medhurst96b56152014-10-30 18:01:15 +0000133 if (strncmp(counter, "filesystem_", 11) != 0) {
134 continue;
Jon Medhurste31266f2014-08-04 15:47:44 +0100135 }
Jon Medhurste31266f2014-08-04 15:47:44 +0100136
Jon Medhurst96b56152014-10-30 18:01:15 +0000137 const char *path = mxmlElementGetAttr(node, "path");
138 if (path == NULL) {
139 logg->logError(__FILE__, __LINE__, "The filesystem counter %s is missing the required path attribute", counter);
140 handleException();
141 }
142 const char *regex = mxmlElementGetAttr(node, "regex");
143 setCounters(new FSCounter(getCounters(), strdup(counter), strdup(path), regex));
Jon Medhurste31266f2014-08-04 15:47:44 +0100144 }
145}
146
Jon Medhurste31266f2014-08-04 15:47:44 +0100147int FSDriver::writeCounters(mxml_node_t *root) const {
148 int count = 0;
Jon Medhurst96b56152014-10-30 18:01:15 +0000149 for (FSCounter *counter = static_cast<FSCounter *>(getCounters()); counter != NULL; counter = static_cast<FSCounter *>(counter->getNext())) {
150 if (access(counter->getPath(), R_OK) == 0) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100151 mxml_node_t *node = mxmlNewElement(root, "counter");
152 mxmlElementSetAttr(node, "name", counter->getName());
153 ++count;
154 }
155 }
156
157 return count;
158}