blob: 99ad61640af785026fd1f64307e1495a8320d3ae [file] [log] [blame]
Darin Petkov65b01462010-04-14 13:32:20 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/*
6 * metrics_library.cc
7 *
8 * Created on: Dec 1, 2009
9 * Author: sosa
10 */
11
12#include "metrics_library.h"
13
14#include <errno.h>
15#include <sys/file.h>
16#include <string.h>
17#include <stdio.h>
18
19#define READ_WRITE_ALL_FILE_FLAGS \
20 (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
21
22static const char kAutotestPath[] = "/tmp/.chromeos-metrics-autotest";
23static const char kChromePath[] = "/tmp/.chromeos-metrics";
24static const int kBufferSize = 4096;
25
26using namespace std;
27
28// TODO(sosa@chromium.org) - use Chromium logger instead of stderr
29void MetricsLibrary::PrintError(const char *message, const char *file,
30 int code) {
31 const char *kProgramName = "metrics_library";
32 if (code == 0) {
33 fprintf(stderr, "%s: %s\n", kProgramName, message);
34 } else if (file == NULL) {
35 fprintf(stderr, "%s: ", kProgramName);
36 perror(message);
37 } else {
38 fprintf(stderr, "%s: %s: ", kProgramName, file);
39 perror(message);
40 }
41}
42
43void MetricsLibrary::SendToAutotest(string name, string value) {
44 FILE *autotest_file = fopen(kAutotestPath, "a+");
45 if (autotest_file == NULL) {
46 PrintError("fopen", kAutotestPath, errno);
47 return;
48 }
49
50 fprintf(autotest_file, "%s=%s\n", name.c_str(), value.c_str());
51 fclose(autotest_file);
52}
53
54void MetricsLibrary::SendToChrome(string name, string value) {
55 int chrome_fd = open(kChromePath,
56 O_WRONLY | O_APPEND | O_CREAT,
57 READ_WRITE_ALL_FILE_FLAGS);
58 // If we failed to open it, return
59 if (chrome_fd < 0) {
60 PrintError("open", kChromePath, errno);
61 return;
62 }
63
64 // Need to chmod because open flags are anded with umask.
65 if (fchmod(chrome_fd, READ_WRITE_ALL_FILE_FLAGS) < 0) {
66 PrintError("fchmod", kChromePath, errno);
67 close(chrome_fd);
68 return;
69 }
70
71 // Grab an exclusive lock to protect Chrome from truncating underneath us
72 if (flock(chrome_fd, LOCK_EX) < 0) {
73 PrintError("flock", kChromePath, errno);
74 close(chrome_fd);
75 return;
76 }
77
78 // Message format is: LENGTH (binary), NAME, VALUE
79 char message[kBufferSize];
80 char *curr_ptr = message;
81 int32_t message_length =
82 name.length() + value.length() + 2 + sizeof(message_length);
83 if (message_length > static_cast<int32_t>(sizeof(message)))
84 PrintError("name/value too long", NULL, 0);
85
86 // Make sure buffer is blanked
87 memset(message, 0, sizeof(message));
88 memcpy(curr_ptr, &message_length, sizeof(message_length));
89 curr_ptr += sizeof(message_length);
90 strncpy(curr_ptr, name.c_str(), name.length());
91 curr_ptr += name.length() + 1;
92 strncpy(curr_ptr, value.c_str(), value.length());
93 if (write(chrome_fd, message, message_length) != message_length)
94 PrintError("write", kChromePath, errno);
95
96 // Release the file lock and close file
97 if (flock(chrome_fd, LOCK_UN) < 0)
98 PrintError("unlock", kChromePath, errno);
99 close(chrome_fd);
100}