/* b01902062 藍ĉŒşç‘‹ */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "chttpd-log.h" #include "memwrap.h" #include #include #include #include #include #include #include ChttpdLog* chttpd_log_new (const char* name, int log_fd) { char* name_start = strrchr (name, '/'); name = name_start == NULL ? name : name_start + 1; size_t name_len = (name == NULL) ? 0 : strlen (name); char* mem = xmalloc (sizeof (ChttpdLog) + name_len + 1); void* mem_generic = mem; ChttpdLog* hlog = mem_generic; hlog->name = mem + sizeof (ChttpdLog); if (name != NULL) { strncpy (hlog->name, name, name_len + 1); } hlog->name[name_len] = '\0'; hlog->ref_count = 1; hlog->pid = getpid (); hlog->log_fd = log_fd; hlog->log_data = lbs_list_meta_new (free); pthread_cond_init (&hlog->ref_change, NULL); pthread_mutex_init (&hlog->ref_mutex, NULL); pthread_rwlock_init (&hlog->log_lock, NULL); return hlog; } ChttpdLog* chttpd_log_new_file (const char* name, const char* file) { int log_fd = open (file, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0600); if (log_fd < 0) { return NULL; } return chttpd_log_new (name, log_fd); } ChttpdLog* chttpd_log_ref (ChttpdLog* hlog) { pthread_mutex_lock (&hlog->ref_mutex); hlog->ref_count++; pthread_mutex_unlock (&hlog->ref_mutex); pthread_cond_broadcast (&hlog->ref_change); return hlog; } void chttpd_log_unref (ChttpdLog* hlog) { pthread_mutex_lock (&hlog->ref_mutex); hlog->ref_count--; if (hlog->ref_count <= 0) { /* No thread has a reference on hlog, so we are going to destory it */ pthread_mutex_unlock (&hlog->ref_mutex); pthread_mutex_destroy (&hlog->ref_mutex); pthread_cond_destroy (&hlog->ref_change); pthread_rwlock_destroy (&hlog->log_lock); lbs_list_meta_free (hlog->log_data); free (hlog); } else { pthread_mutex_unlock (&hlog->ref_mutex); pthread_cond_broadcast (&hlog->ref_change); } } int chttpd_log_read_start (ChttpdLog* hlog) { return pthread_rwlock_tryrdlock (&hlog->log_lock); } void chttpd_log_read_stop (ChttpdLog* hlog) { pthread_rwlock_unlock (&hlog->log_lock); } size_t chttpd_log_write (ChttpdLog* hlog, const char* format, ...) { va_list ap; char* str; size_t r; va_start (ap, format); str = lbs_str_vprintf (format, ap); va_end (ap); r = chttpd_log_write_str (hlog, str); free (str); return r; } size_t chttpd_log_write_str (ChttpdLog* hlog, const char* string) { time_t t; struct tm tmd; char* msg; size_t r; time (&t); localtime_r (&t, &tmd); msg = lbs_str_printf ("%04d-%02d-%02d %02d:%02d:%02d %s[%ld]: %s\n", tmd.tm_year + 1900, tmd.tm_mon + 1, tmd.tm_mday, tmd.tm_hour, tmd.tm_min, tmd.tm_sec, hlog->name, (long)(hlog->pid), string); pthread_rwlock_wrlock (&hlog->log_lock); lbs_list_push_back (hlog->log_data, msg, NULL); r = lbs_posix_write_all (hlog->log_fd, msg, 0); pthread_rwlock_unlock (&hlog->log_lock); return r; }