libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2011, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as 00007 * published by the Free Software Foundation; either version 3 of the 00008 * License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/stdlib.h> 00020 #include <libexplain/ac/string.h> 00021 #include <libexplain/ac/sys/stat.h> 00022 #include <libexplain/ac/sys/time.h> 00023 #include <libexplain/ac/time.h> 00024 #include <libexplain/ac/limits.h> 00025 #include <libexplain/ac/math.h> 00026 00027 #include <libexplain/buffer/pointer.h> 00028 #include <libexplain/buffer/timeval.h> 00029 #include <libexplain/buffer/time_t.h> 00030 #include <libexplain/is_efault.h> 00031 00032 00033 #if 0 00034 #ifndef MAX_TIME_T 00035 #define MAX_TIME_T ((~(time_t)0) >> 1) 00036 #endif 00037 #ifndef MIN_TIME_T 00038 #define MIN_TIME_T (-MAX_TIME_T - 1) 00039 #endif 00040 #endif 00041 00042 00043 static void 00044 print(explain_string_buffer_t *sb, const struct timeval *data) 00045 { 00046 if (data->tv_usec == UTIME_NOW) 00047 { 00048 explain_string_buffer_puts(sb, "{ tv_usec = UTIME_NOW }"); 00049 } 00050 else if (data->tv_usec == UTIME_OMIT) 00051 { 00052 explain_string_buffer_puts(sb, "{ tv_usec = UTIME_OMIT }"); 00053 } 00054 else if (data->tv_usec < 0u || data->tv_usec >= 1000000u) 00055 { 00056 explain_string_buffer_printf 00057 ( 00058 sb, 00059 "{ tv_sec = %ld, tv_usec = %ld }", 00060 (long)data->tv_sec, 00061 (long)data->tv_usec 00062 ); 00063 } 00064 else 00065 { 00066 /* FIXME: localime? */ 00067 explain_string_buffer_printf 00068 ( 00069 sb, 00070 "{ %.8g seconds }", 00071 data->tv_sec + 1e-6 * data->tv_usec 00072 ); 00073 } 00074 } 00075 00076 00077 void 00078 explain_buffer_timeval(explain_string_buffer_t *sb, const struct timeval *data) 00079 { 00080 if (explain_is_efault_pointer(data, sizeof(*data))) 00081 explain_buffer_pointer(sb, data); 00082 else 00083 print(sb, data); 00084 } 00085 00086 00087 void 00088 explain_buffer_timeval_array(explain_string_buffer_t *sb, 00089 const struct timeval *data, unsigned data_size) 00090 { 00091 unsigned j; 00092 00093 if (explain_is_efault_pointer(data, sizeof(*data) * data_size)) 00094 { 00095 explain_buffer_pointer(sb, data); 00096 return; 00097 } 00098 explain_string_buffer_putc(sb, '{'); 00099 for (j = 0; j < data_size; ++j) 00100 { 00101 if (j) 00102 explain_string_buffer_puts(sb, ", "); 00103 print(sb, data + j); 00104 } 00105 explain_string_buffer_putc(sb, '}'); 00106 } 00107 00108 00109 void 00110 explain_parse_timeval_or_die(const char *text, const char *caption, 00111 struct timeval *result) 00112 { 00113 if (0 == strcmp(text, "UTIME_NOW")) 00114 { 00115 result->tv_sec = 0; 00116 result->tv_usec = UTIME_NOW; 00117 return; 00118 } 00119 if (0 == strcmp(text, "UTIME_OMIT")) 00120 { 00121 result->tv_sec = 0; 00122 result->tv_usec = UTIME_OMIT; 00123 return; 00124 } 00125 00126 { 00127 char *ep = 0; 00128 double n = strtod(text, &ep); 00129 if (ep != text && !*ep) 00130 { 00131 /* cope with overflow */ 00132 if (n + 0.5 >= MAX_TIME_T) 00133 { 00134 result->tv_sec = MAX_TIME_T; 00135 result->tv_usec = 0; 00136 return; 00137 } 00138 00139 /* cope with underflow */ 00140 if (n - 0.5 <= MIN_TIME_T) 00141 { 00142 result->tv_sec = MIN_TIME_T; 00143 result->tv_usec = 0; 00144 return; 00145 } 00146 00147 /* 00148 * Note: tv_sec is signed, but tv_usec is required to be in 00149 * the range 0..<1e6, because negative values mean something 00150 * else. The floor() function will push negative tv_sec 00151 * values more negative, which means adding the positive 00152 * tv_usec part brings them back up to the appropriate 00153 * floating point value. 00154 */ 00155 result->tv_sec = floor(n); 00156 result->tv_usec = floor((n - result->tv_sec) * 1e6 + 0.5); 00157 if (result->tv_usec >= 1000000) 00158 { 00159 /* could have overflowed on rounding */ 00160 result->tv_sec++; 00161 result->tv_usec = 0; 00162 } 00163 return; 00164 } 00165 } 00166 00167 { 00168 time_t n = explain_parse_time_t_or_die(text, caption); 00169 result->tv_sec = n; 00170 result->tv_usec = 0; 00171 } 00172 } 00173 00174 00175 /* vim: set ts=8 sw=4 et : */