OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Implementation of bootstat_log(), part of the Chromium OS 'bootstat' | 5 // Implementation of bootstat_log(), part of the Chromium OS 'bootstat' |
6 // facility. | 6 // facility. |
7 | 7 |
8 #include "bootstat.h" | 8 #include "bootstat.h" |
| 9 #include "bootstat_test.h" |
9 | 10 |
| 11 #include <assert.h> |
| 12 #include <stddef.h> |
10 #include <stdio.h> | 13 #include <stdio.h> |
11 #include <stddef.h> | |
12 | 14 |
| 15 #include <sys/fcntl.h> |
| 16 #include <sys/param.h> |
| 17 #include <sys/stat.h> |
13 #include <sys/types.h> | 18 #include <sys/types.h> |
14 #include <sys/stat.h> | |
15 #include <sys/fcntl.h> | |
16 #include <unistd.h> | 19 #include <unistd.h> |
17 | 20 |
18 // | 21 // |
| 22 // Default path to directory where output statistics will be stored. |
| 23 // |
| 24 static const char kDefaultOutputDirectoryName[] = "/tmp"; |
| 25 |
| 26 // |
19 // Paths to the statistics files we snapshot as part of the data to | 27 // Paths to the statistics files we snapshot as part of the data to |
20 // be logged. | 28 // be logged. |
21 // | 29 // |
22 static const char kUptimeStatisticsFileName[] = "/proc/uptime"; | 30 static const char kDefaultUptimeStatisticsFileName[] = "/proc/uptime"; |
23 | 31 |
24 #if defined (__amd64__) || defined (__x86_64__) || defined (__i386__) | 32 #if defined (__amd64__) || defined (__x86_64__) || defined (__i386__) |
25 static const char kDiskStatisticsFileName[] = "/sys/block/sda/stat"; | 33 static const char kDefaultDiskStatisticsFileName[] = "/sys/block/sda/stat"; |
26 #elif defined (__arm__) | 34 #elif defined (__arm__) |
27 static const char kDiskStatisticsFileName[] = "/sys/block/mmcblk0/stat"; | 35 static const char kDefaultDiskStatisticsFileName[] = "/sys/block/mmcblk0/stat"; |
28 #else | 36 #else |
29 #error "unknown processor type?" | 37 #error "unknown processor type?" |
30 #endif | 38 #endif |
31 | 39 |
32 | 40 static const char *output_directory_name = kDefaultOutputDirectoryName; |
33 // | 41 static const char *uptime_statistics_file_name = |
34 // Maximum length of any pathname for storing event statistics. | 42 kDefaultUptimeStatisticsFileName; |
35 // Arbitrarily chosen, but see the comment below about truncation. | 43 static const char *disk_statistics_file_name = kDefaultDiskStatisticsFileName; |
36 // | |
37 #define MAX_STAT_PATH 128 | |
38 | |
39 // | |
40 // Output file creation mode: 0666, a.k.a. rw-rw-rw-. | |
41 // | |
42 static const int kFileCreationMode = | |
43 (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); | |
44 | |
45 | 44 |
46 static void append_logdata(const char* input_path, | 45 static void append_logdata(const char* input_path, |
47 const char* output_name_prefix, | 46 const char* output_name_prefix, |
48 const char* event_name) | 47 const char* event_name) |
49 { | 48 { |
50 char output_path[MAX_STAT_PATH]; | 49 const mode_t kFileCreationMode = |
| 50 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; |
| 51 char output_path[PATH_MAX]; |
51 char buffer[256]; | 52 char buffer[256]; |
52 ssize_t num_read; | 53 ssize_t num_read; |
53 int ifd, ofd; | 54 int ifd, ofd; |
| 55 int output_path_len; |
54 | 56 |
55 ifd = open(input_path, O_RDONLY); | 57 ifd = open(input_path, O_RDONLY); |
56 if (ifd < 0) { | 58 if (ifd < 0) { |
57 return; | 59 return; |
58 } | 60 } |
59 | 61 |
60 // | 62 // |
61 // We don't want the file name "/tmp/uptime-..." truncated | 63 // For those not up on the more esoteric features of printf |
62 // differently from the the name "/tmp/disk-...", so we truncate | 64 // formats: the "%.*s" format is used to truncate the event name |
63 // event_name separately using the "%.*s" format. | 65 // to the proper number of characters.. |
64 // | 66 // |
65 // We expect that BOOTSTAT_MAX_EVENT_LEN is enough smaller than | 67 // The assertion for output_path overflow should only be able to |
66 // MAX_STAT_PATH that output_path will never be truncated. | 68 // fail if output_directory_name is changed from its default, |
| 69 // which can only happen in unit tests, and then only in the event |
| 70 // of a serious test bug. |
67 // | 71 // |
68 (void) snprintf(output_path, sizeof(output_path), "/tmp/%s-%.*s", | 72 output_path_len = snprintf(output_path, sizeof(output_path), "%s/%s-%.*s", |
69 output_name_prefix, | 73 output_directory_name, |
70 BOOTSTAT_MAX_EVENT_LEN - 1, event_name); | 74 output_name_prefix, |
| 75 BOOTSTAT_MAX_EVENT_LEN - 1, event_name); |
| 76 assert(output_path_len < sizeof(output_path)); |
71 ofd = open(output_path, O_WRONLY | O_APPEND | O_CREAT, | 77 ofd = open(output_path, O_WRONLY | O_APPEND | O_CREAT, |
72 kFileCreationMode); | 78 kFileCreationMode); |
73 if (ofd < 0) { | 79 if (ofd < 0) { |
74 (void) close(ifd); | 80 (void)close(ifd); |
75 return; | 81 return; |
76 } | 82 } |
77 | 83 |
78 while ((num_read = read(ifd, buffer, sizeof(buffer))) > 0) { | 84 while ((num_read = read(ifd, buffer, sizeof(buffer))) > 0) { |
79 ssize_t num_written = write(ofd, buffer, num_read); | 85 ssize_t num_written = write(ofd, buffer, num_read); |
80 if (num_written != num_read) | 86 if (num_written != num_read) |
81 break; | 87 break; |
82 } | 88 } |
83 (void) close(ofd); | 89 (void)close(ofd); |
84 (void) close(ifd); | 90 (void)close(ifd); |
85 } | 91 } |
86 | 92 |
87 | 93 |
88 void bootstat_log(const char* event_name) | 94 void bootstat_log(const char* event_name) |
89 { | 95 { |
90 append_logdata(kUptimeStatisticsFileName, "uptime", event_name); | 96 append_logdata(uptime_statistics_file_name, "uptime", event_name); |
91 append_logdata(kDiskStatisticsFileName, "disk", event_name); | 97 append_logdata(disk_statistics_file_name, "disk", event_name); |
92 } | 98 } |
| 99 |
| 100 |
| 101 void bootstat_set_output_directory(const char* dirname) |
| 102 { |
| 103 if (dirname != NULL) |
| 104 output_directory_name = dirname; |
| 105 else |
| 106 output_directory_name = kDefaultOutputDirectoryName; |
| 107 } |
| 108 |
| 109 |
| 110 void bootstat_set_uptime_file_name(const char* filename) |
| 111 { |
| 112 if (filename != NULL) |
| 113 uptime_statistics_file_name = filename; |
| 114 else |
| 115 uptime_statistics_file_name = kDefaultUptimeStatisticsFileName; |
| 116 } |
| 117 |
| 118 |
| 119 void bootstat_set_disk_file_name(const char* filename) |
| 120 { |
| 121 if (filename != NULL) |
| 122 disk_statistics_file_name = filename; |
| 123 else |
| 124 disk_statistics_file_name = kDefaultDiskStatisticsFileName; |
| 125 } |
OLD | NEW |