00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #include "ink_config.h"
00025 
00026 #include <assert.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <stdarg.h>
00030 #include <string.h>
00031 #include <time.h>
00032 
00033 #include <sys/time.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <unistd.h>
00037 #include <sys/socket.h>
00038 #include <netinet/in.h>
00039 #include <arpa/inet.h>
00040 #include <netdb.h>
00041 
00042 #include "P_RecProcess.h"
00043 
00044 
00045 
00046 
00047 #include "Compatability.h"
00048 
00049 #include "LogUtils.h"
00050 #include "LogLimits.h"
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 int
00065 LogUtils::timestamp_to_str(long timestamp, char *buf, int size)
00066 {
00067   static const char *format_str = "%Y%m%d.%Hh%Mm%Ss";
00068   struct tm res;
00069   struct tm *tms;
00070   tms = ink_localtime_r((const time_t *) ×tamp, &res);
00071   return strftime(buf, size, format_str, tms);
00072 }
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 char *
00086 LogUtils::timestamp_to_netscape_str(long timestamp)
00087 {
00088   static char timebuf[64];      
00089   static char gmtstr[16];
00090   static long last_timestamp = 0;
00091   static char bad_time[] = "Bad timestamp";
00092 
00093   
00094   if (timestamp < 0) {
00095     return bad_time;
00096   }
00097   
00098   
00099   
00100   
00101 
00102   if (timestamp != last_timestamp) {
00103     
00104     
00105     
00106     
00107 #ifdef NEED_ALTZONE_DEFINED
00108     time_t altzone = timezone;
00109 #endif
00110     struct tm res;
00111     struct tm *tms = ink_localtime_r((const time_t *) ×tamp, &res);
00112     
00113 #ifdef NEED_ALTZONE_DEFINED
00114     long zone = (tms->tm_isdst > 0) ? altzone : timezone;
00115 #else
00116     long zone = -tms->tm_gmtoff;        
00117 #endif
00118     int offset;
00119     char sign;
00120 
00121     if (zone >= 0) {
00122       offset = zone / 60;
00123       sign = '-';
00124     } else {
00125       offset = zone / -60;
00126       sign = '+';
00127     }
00128     int glen = snprintf(gmtstr, 16, "%c%.2d%.2d", sign, offset / 60, offset % 60);
00129 
00130     strftime(timebuf, 64 - glen, "%d/%b/%Y:%H:%M:%S ", tms);
00131     ink_strlcat(timebuf, gmtstr, sizeof(timebuf));
00132     last_timestamp = timestamp;
00133   }
00134   return timebuf;
00135 }
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 char *
00145 LogUtils::timestamp_to_date_str(long timestamp)
00146 {
00147   static char timebuf[64];      
00148   static long last_timestamp = 0;
00149   static char bad_time[] = "Bad timestamp";
00150 
00151   
00152   if (timestamp < 0) {
00153     return bad_time;
00154   }
00155   
00156   
00157   
00158   
00159 
00160   if (timestamp != last_timestamp) {
00161     struct tm res;
00162     struct tm *tms = ink_localtime_r((const time_t *) ×tamp, &res);
00163     strftime(timebuf, 64, "%Y-%m-%d", tms);
00164     last_timestamp = timestamp;
00165   }
00166   return timebuf;
00167 }
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 char *
00177 LogUtils::timestamp_to_time_str(long timestamp)
00178 {
00179   static char timebuf[64];      
00180   static long last_timestamp = 0;
00181   static char bad_time[] = "Bad timestamp";
00182 
00183   
00184   if (timestamp < 0) {
00185     return bad_time;
00186   }
00187   
00188   
00189   
00190   
00191 
00192   if (timestamp != last_timestamp) {
00193     struct tm res;
00194     struct tm *tms = ink_localtime_r((const time_t *) ×tamp, &res);
00195     strftime(timebuf, 64, "%H:%M:%S", tms);
00196     last_timestamp = timestamp;
00197   }
00198   return timebuf;
00199 }
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 void
00212 LogUtils::manager_alarm(LogUtils::AlarmType alarm_type, const char *msg, ...)
00213 {
00214   char msg_buf[LOG_MAX_FORMATTED_LINE];
00215   va_list ap;
00216 
00217   ink_assert(alarm_type >= 0 && alarm_type < LogUtils::LOG_ALARM_N_TYPES);
00218 
00219   if (msg == NULL) {
00220     snprintf(msg_buf, sizeof(msg_buf), "No Message");
00221   } else {
00222     va_start(ap, msg);
00223     vsnprintf(msg_buf, LOG_MAX_FORMATTED_LINE, msg, ap);
00224     va_end(ap);
00225   }
00226 
00227   switch (alarm_type) {
00228   case LogUtils::LOG_ALARM_ERROR:
00229     RecSignalManager(REC_SIGNAL_LOGGING_ERROR, msg_buf);
00230     break;
00231 
00232   case LogUtils::LOG_ALARM_WARNING:
00233     RecSignalManager(REC_SIGNAL_LOGGING_WARNING, msg_buf);
00234     break;
00235 
00236   default:
00237     ink_assert(false);
00238   }
00239 }
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 void
00251 LogUtils::strip_trailing_newline(char *buf)
00252 {
00253   if (buf != NULL) {
00254     int len =::strlen(buf);
00255     if (len > 0) {
00256       if (buf[len - 1] == '\n') {
00257         buf[len - 1] = '\0';
00258       }
00259     }
00260   }
00261 }
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 char *
00273 LogUtils::escapify_url(Arena *arena, char *url, size_t len_in, int *len_out, char *dst, size_t dst_size, const unsigned char *map)
00274 {
00275   
00276   
00277   
00278   
00279   
00280   
00281   
00282   static const unsigned char codes_to_escape[32] = {
00283     0xFF, 0xFF, 0xFF, 0xFF,     
00284     0xB4,                       
00285     0x00, 0x00,                 
00286     0x0A,                       
00287     0x00, 0x00, 0x00,           
00288     0x1E, 0x80,                 
00289     0x00, 0x00,                 
00290     0x1F,                       
00291     0x00, 0x00, 0x00, 0x00,     
00292     0x00, 0x00, 0x00, 0x00,     
00293     0x00, 0x00, 0x00, 0x00,     
00294     0x00, 0x00, 0x00, 0x00      
00295   };
00296 
00297   static char hex_digit[16] = {
00298     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
00299     'D', 'E', 'F'
00300   };
00301 
00302   if (!url || (dst && dst_size < len_in)) {
00303     *len_out = 0;
00304     return NULL;
00305   }
00306 
00307   if (!map)
00308     map = codes_to_escape;
00309 
00310   
00311   
00312   int count = 0;
00313   char *p = url;
00314   char *in_url_end = url + len_in;
00315 
00316   while (p < in_url_end) {
00317     unsigned char c = *p;
00318     if (map[c / 8] & (1 << (7 - c % 8))) {
00319       ++count;
00320     }
00321     ++p;
00322   }
00323 
00324   if (!count) {
00325     
00326     
00327     *len_out = len_in;
00328     if (dst)
00329       ink_strlcpy(dst, url, dst_size);
00330     return url;
00331   }
00332 
00333   
00334   
00335   
00336   
00337   
00338   
00339   
00340   size_t out_len = len_in + 2 * count;
00341 
00342   if (dst && out_len > dst_size) {
00343     *len_out = 0;
00344     return NULL;
00345   }
00346 
00347   
00348   
00349   
00350   
00351   char *new_url;
00352 
00353   if (dst)
00354     new_url = dst;
00355   else
00356     new_url = (char *) arena->str_alloc(out_len + 1);
00357 
00358   char *from = url;
00359   char *to = new_url;
00360 
00361   while (from < in_url_end) {
00362     unsigned char c = *from;
00363     if (map[c / 8] & (1 << (7 - c % 8))) {
00364       *to++ = '%';
00365       *to++ = hex_digit[c / 16];
00366       *to++ = hex_digit[c % 16];
00367     } else {
00368       *to++ = *from;
00369     }
00370     from++;
00371   }
00372   *to = '\0';                      
00373 
00374   *len_out = out_len;
00375   return new_url;
00376 }
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 void
00388 LogUtils::remove_content_type_attributes(char *type_str, int *type_len)
00389 {
00390   if (!type_str) {
00391     *type_len = 0;
00392     return;
00393   }
00394   
00395   
00396   char *p = (char *) memchr(type_str, ';', *type_len);
00397   if (p) {
00398     *type_len = p - type_str;
00399   }
00400 }
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 int
00417 LogUtils::timestamp_to_hex_str(unsigned ip, char *buf, size_t bufLen, size_t * numCharsPtr)
00418 {
00419   static const char *table = "0123456789abcdef@";
00420   int retVal = 1;
00421   int shift = 28;
00422   if (buf && bufLen > 0) {
00423     if (bufLen > 8)
00424       bufLen = 8;
00425     for (retVal = 0; retVal < (int) bufLen;) {
00426       buf[retVal++] = (char) table[((ip >> shift) & 0xf)];
00427       shift -= 4;
00428     }
00429 
00430     if (numCharsPtr) {
00431       *numCharsPtr = (size_t) retVal;
00432     }
00433     retVal = (retVal == 8) ? 0 : 1;
00434   }
00435   return retVal;
00436 }
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 int
00456 LogUtils::seconds_to_next_roll(time_t time_now, int rolling_offset, int rolling_interval)
00457 {
00458   struct tm lt;
00459   ink_localtime_r((const time_t *) &time_now, <);
00460   int sidl = lt.tm_sec + lt.tm_min * 60 + lt.tm_hour * 3600;
00461   int tr = rolling_offset * 3600;
00462   return ((tr >= sidl ? (tr - sidl) % rolling_interval : (86400 - (sidl - tr)) % rolling_interval));
00463 }
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 int
00486 LogUtils::file_is_writeable(const char *full_filename,
00487                             off_t * size_bytes, bool * has_size_limit, uint64_t * current_size_limit_bytes)
00488 {
00489   int ret_val = 0;
00490   int e;
00491   struct stat stat_data;
00492 
00493   e = stat(full_filename, &stat_data);
00494   if (e == 0) {
00495     
00496     
00497     
00498     if (!(stat_data.st_mode & S_IFREG || stat_data.st_mode & S_IFIFO)) {
00499       ret_val = 1;
00500     } else if (!(stat_data.st_mode & S_IWUSR)) {
00501       errno = EACCES;
00502       ret_val = -1;
00503     }
00504     if (size_bytes)
00505       *size_bytes = stat_data.st_size;
00506   } else {
00507     
00508     
00509     if (errno != ENOENT) {
00510       
00511       
00512       ret_val = -1;
00513     } else {
00514       
00515       
00516 
00517       char *dir;
00518       char *prefix = 0;
00519 
00520       
00521       
00522       
00523       const char *slash = strrchr(full_filename, '/');
00524       if (slash) {
00525         size_t prefix_len = slash - full_filename + 1;
00526         prefix = new char[prefix_len + 1];
00527         memcpy(prefix, full_filename, prefix_len);
00528         prefix[prefix_len] = 0;
00529         dir = prefix;
00530       } else {
00531         dir = (char *) ".";     
00532       }
00533 
00534       
00535       
00536       e = access(dir, X_OK | W_OK);
00537       if (e < 0) {
00538         ret_val = -1;
00539       } else {
00540         if (size_bytes)
00541           *size_bytes = 0;
00542       }
00543 
00544       if (prefix) {
00545         delete[]prefix;
00546       }
00547     }
00548   }
00549 
00550   
00551   
00552   if (ret_val == 0) {
00553     struct rlimit limit_data;
00554     e = getrlimit(RLIMIT_FSIZE, &limit_data);
00555     if (e < 0) {
00556       ret_val = -1;
00557     } else {
00558       if (limit_data.rlim_cur != (rlim_t)RLIM_INFINITY) {
00559         if (has_size_limit)
00560           *has_size_limit = true;
00561         if (current_size_limit_bytes)
00562           *current_size_limit_bytes = limit_data.rlim_cur;
00563       } else {
00564         if (has_size_limit)
00565           *has_size_limit = false;
00566       }
00567     }
00568   }
00569 
00570   return ret_val;
00571 }