| 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 |