diff --git a/src/httplib_must_hide_file.c b/src/httplib_must_hide_file.c index 98963667..bbb3d776 100644 --- a/src/httplib_must_hide_file.c +++ b/src/httplib_must_hide_file.c @@ -29,13 +29,18 @@ int XX_httplib_must_hide_file( struct httplib_connection *conn, const char *path ) { - if (conn && conn->ctx) { - const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$"; - const char *pattern = conn->ctx->config[HIDE_FILES]; - return XX_httplib_match_prefix(pw_pattern, strlen(pw_pattern), path) > 0 - || (pattern != NULL - && XX_httplib_match_prefix(pattern, strlen(pattern), path) > 0); - } + const char *pw_pattern; + const char *pattern; + + if ( conn == NULL || conn->ctx == NULL ) return 0; + + pw_pattern = "**" PASSWORDS_FILE_NAME "$"; + pattern = conn->ctx->config[HIDE_FILES]; + + return XX_httplib_match_prefix(pw_pattern, strlen(pw_pattern), path) > 0 + || (pattern != NULL + && XX_httplib_match_prefix(pattern, strlen(pattern), path) > 0); + return 0; } /* XX_httplib_must_hide_file */ diff --git a/src/httplib_next_option.c b/src/httplib_next_option.c index e32cd9ad..6a01b7e2 100644 --- a/src/httplib_next_option.c +++ b/src/httplib_next_option.c @@ -27,56 +27,58 @@ #include "httplib_main.h" -/* A helper function for traversing a comma separated list of values. +/* + * A helper function for traversing a comma separated list of values. * It returns a list pointer shifted to the next value, or NULL if the end * of the list found. * Value is stored in val vector. If value has form "x=y", then eq_val * vector is initialized to point to the "y" part, and val vector length - * is adjusted to point only to "x". */ + * is adjusted to point only to "x". + */ + const char *XX_httplib_next_option( const char *list, struct vec *val, struct vec *eq_val ) { int end; reparse: - if (val == NULL || list == NULL || *list == '\0') { - /* End of the list */ - list = NULL; - } else { - /* Skip over leading LWS */ - while (*list == ' ' || *list == '\t') list++; + if ( val == NULL || list == NULL || *list == '\0' ) return NULL; + + /* Skip over leading LWS */ + while ( *list == ' ' || *list == '\t' ) list++; - val->ptr = list; - if ((list = strchr(val->ptr, ',')) != NULL) { - /* Comma found. Store length and shift the list ptr */ - val->len = ((size_t)(list - val->ptr)); - list++; - } else { - /* This value is the last one */ - list = val->ptr + strlen(val->ptr); - val->len = ((size_t)(list - val->ptr)); - } + val->ptr = list; + if ((list = strchr(val->ptr, ',')) != NULL) { + /* Comma found. Store length and shift the list ptr */ + val->len = ((size_t)(list - val->ptr)); + list++; + } + + else { + /* This value is the last one */ + list = val->ptr + strlen(val->ptr); + val->len = ((size_t)(list - val->ptr)); + } - /* Adjust length for trailing LWS */ - end = (int)val->len - 1; - while (end >= 0 && (val->ptr[end] == ' ' || val->ptr[end] == '\t')) - end--; - val->len = (size_t)(end + 1); + /* Adjust length for trailing LWS */ + end = (int)val->len - 1; + while ( end >= 0 && ( val->ptr[end] == ' ' || val->ptr[end] == '\t' ) ) end--; - if (val->len == 0) { - /* Ignore any empty entries. */ - goto reparse; - } + val->len = (size_t)(end + 1); - if (eq_val != NULL) { - /* Value has form "x=y", adjust pointers and lengths - * so that val points to "x", and eq_val points to "y". */ - eq_val->len = 0; - eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len); - if (eq_val->ptr != NULL) { - eq_val->ptr++; /* Skip over '=' character */ - eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len; - val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1; - } + if (val->len == 0) { + /* Ignore any empty entries. */ + goto reparse; + } + + if (eq_val != NULL) { + /* Value has form "x=y", adjust pointers and lengths + * so that val points to "x", and eq_val points to "y". */ + eq_val->len = 0; + eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len); + if (eq_val->ptr != NULL) { + eq_val->ptr++; /* Skip over '=' character */ + eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len; + val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1; } } diff --git a/src/httplib_open_auth_file.c b/src/httplib_open_auth_file.c index 3f2050a6..7556db85 100644 --- a/src/httplib_open_auth_file.c +++ b/src/httplib_open_auth_file.c @@ -22,7 +22,7 @@ * THE SOFTWARE. * * ============ - * Release: 1.8 + * Release: 2.0 */ #include "httplib_main.h" @@ -32,43 +32,61 @@ * or search for .htpasswd in the requested directory. */ void XX_httplib_open_auth_file( struct httplib_connection *conn, const char *path, struct file *filep ) { - if ( conn == NULL || conn->ctx == NULL ) return; - char name[PATH_MAX]; const char *p; const char *e; - const char *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE]; + const char *gpass; struct file file = STRUCT_FILE_INITIALIZER; int truncated; - if (gpass != NULL) { - /* Use global passwords file */ - if (!XX_httplib_fopen(conn, gpass, "r", filep)) { -#ifdef DEBUG - httplib_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO)); -#endif - } - /* Important: using local struct file to test path for is_directory - * flag. If filep is used, XX_httplib_stat() makes it appear as if auth file - * was opened. */ - } else if (XX_httplib_stat(conn, path, &file) && file.is_directory) { - XX_httplib_snprintf(conn, &truncated, name, sizeof(name), "%s/%s", path, PASSWORDS_FILE_NAME); + if ( conn == NULL || conn->ctx == NULL ) return; - if (truncated || !XX_httplib_fopen(conn, name, "r", filep)) { + gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE]; + + if ( gpass != NULL ) { + + /* + * Use global passwords file + */ + + if ( ! XX_httplib_fopen( conn, gpass, "r", filep ) ) { #ifdef DEBUG - httplib_cry(conn, "fopen(%s): %s", name, strerror(ERRNO)); + httplib_cry( conn, "fopen(%s): %s", gpass, strerror(ERRNO) ); #endif } - } else { - /* Try to find .htpasswd in requested directory. */ + /* + * Important: using local struct file to test path for is_directory + * flag. If filep is used, XX_httplib_stat() makes it appear as if auth file + * was opened. + */ + + } + + else if ( XX_httplib_stat( conn, path, &file ) && file.is_directory ) { + + XX_httplib_snprintf( conn, &truncated, name, sizeof(name), "%s/%s", path, PASSWORDS_FILE_NAME ); + + if ( truncated || ! XX_httplib_fopen( conn, name, "r", filep ) ) { +#ifdef DEBUG + httplib_cry( conn, "fopen(%s): %s", name, strerror(ERRNO) ); +#endif + } + } + + else { + /* + * Try to find .htpasswd in requested directory. + */ + for (p = path, e = p + strlen(p) - 1; e > p; e--) { if (e[0] == '/') break; } - XX_httplib_snprintf(conn, &truncated, name, sizeof(name), "%.*s/%s", (int)(e - p), p, PASSWORDS_FILE_NAME); - if (truncated || !XX_httplib_fopen(conn, name, "r", filep)) { + XX_httplib_snprintf( conn, &truncated, name, sizeof(name), "%.*s/%s", (int)(e - p), p, PASSWORDS_FILE_NAME ); + + if ( truncated || ! XX_httplib_fopen( conn, name, "r", filep ) ) { #ifdef DEBUG - httplib_cry(conn, "fopen(%s): %s", name, strerror(ERRNO)); + httplib_cry( conn, "fopen(%s): %s", name, strerror(ERRNO) ); #endif } } diff --git a/src/httplib_parse_date_string.c b/src/httplib_parse_date_string.c index f2ee2299..cc79f00b 100644 --- a/src/httplib_parse_date_string.c +++ b/src/httplib_parse_date_string.c @@ -22,7 +22,7 @@ * THE SOFTWARE. * * ============ - * Release: 1.8 + * Release: 2.0 */ #include "httplib_main.h" @@ -35,12 +35,13 @@ static const char *month_names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", " #if !defined(NO_CACHING) /* Convert month to the month number. Return -1 on error, or month number */ -static int get_month_index(const char *s) { +static int get_month_index( const char *s ) { size_t i; for (i = 0; i < ARRAY_SIZE(month_names); i++) { - if (!strcmp(s, month_names[i])) return (int)i; + + if ( ! strcmp( s, month_names[i] ) ) return (int)i; } return -1; @@ -65,16 +66,19 @@ time_t XX_httplib_parse_date_string( const char *datetime ) { ( sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second ) == 6 ) || ( sscanf(datetime, "%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second ) == 6 ) ) { - month = get_month_index(month_str); - if ((month >= 0) && (year >= 1970)) { - memset(&tm, 0, sizeof(tm)); + month = get_month_index( month_str ); + + if ( month >= 0 && year >= 1970 ) { + + memset( &tm, 0, sizeof(tm) ); + tm.tm_year = year - 1900; - tm.tm_mon = month; + tm.tm_mon = month; tm.tm_mday = day; tm.tm_hour = hour; - tm.tm_min = minute; - tm.tm_sec = second; - result = timegm(&tm); + tm.tm_min = minute; + tm.tm_sec = second; + result = timegm( & tm ); } } diff --git a/src/httplib_parse_net.c b/src/httplib_parse_net.c index aa27cf69..e9039c62 100644 --- a/src/httplib_parse_net.c +++ b/src/httplib_parse_net.c @@ -22,7 +22,7 @@ * THE SOFTWARE. * * ============ - * Release: 1.8 + * Release: 2.0 */ #include "httplib_main.h" @@ -43,16 +43,19 @@ int XX_httplib_parse_net( const char *spec, uint32_t *net, uint32_t *mask ) { int b; int c; int d; - int slash = 32; - int len = 0; + int slash; + int len; - if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 - || sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a) - && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 - && slash < 33) { - len = n; - *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d; - *mask = slash ? (0xffffffffU << (32 - slash)) : 0; + slash = 32; + len = 0; + + if ( ( sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 || + sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4 ) && + isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 && slash < 33 ) { + + len = n; + *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d; + *mask = (slash) ? (0xffffffffU << (32 - slash)) : 0; } return len; diff --git a/src/httplib_send_file_data.c b/src/httplib_send_file_data.c index f891ac42..8d265ff9 100644 --- a/src/httplib_send_file_data.c +++ b/src/httplib_send_file_data.c @@ -36,24 +36,34 @@ void XX_httplib_send_file_data( struct httplib_connection *conn, struct file *fi int num_written; int64_t size; - if (!filep || !conn) return; + if ( filep == NULL || conn == NULL ) return; /* Sanity check the offset */ - size = (filep->size > INT64_MAX) ? INT64_MAX : (int64_t)(filep->size); + size = (filep->size > INT64_MAX) ? INT64_MAX : (int64_t)(filep->size); offset = (offset < 0) ? 0 : ((offset > size) ? size : offset); - if (len > 0 && filep->membuf != NULL && size > 0) { - /* file stored in memory */ - if (len > size - offset) { - len = size - offset; - } - httplib_write(conn, filep->membuf + offset, (size_t)len); - } else if (len > 0 && filep->fp != NULL) { + if ( len > 0 && filep->membuf != NULL && size > 0 ) { + + /* + * file stored in memory + */ + + if (len > size - offset) len = size - offset; + httplib_write( conn, filep->membuf + offset, (size_t)len ); + + } + + else if ( len > 0 && filep->fp != NULL ) { + /* file stored on disk */ #if defined(__linux__) - /* sendfile is only available for Linux */ - if ((conn->ssl == 0) && (conn->throttle == 0) - && (!httplib_strcasecmp(conn->ctx->config[ALLOW_SENDFILE_CALL], "yes"))) { + + /* + * sendfile is only available for Linux + */ + + if ( conn->ssl == 0 && conn->throttle == 0 && ! httplib_strcasecmp( conn->ctx->config[ALLOW_SENDFILE_CALL], "yes" ) ) { + off_t sf_offs = (off_t)offset; ssize_t sf_sent; int sf_file = fileno(filep->fp); @@ -62,15 +72,18 @@ void XX_httplib_send_file_data( struct httplib_connection *conn, struct file *fi do { /* 2147479552 (0x7FFFF000) is a limit found by experiment on * 64 bit Linux (2^31 minus one memory page of 4k?). */ - size_t sf_tosend = - (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000); - sf_sent = - sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend); - if (sf_sent > 0) { + size_t sf_tosend = (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000); + sf_sent = sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend); + + if ( sf_sent > 0 ) { + conn->num_bytes_sent += sf_sent; - len -= sf_sent; - offset += sf_sent; - } else if (loop_cnt == 0) { + len -= sf_sent; + offset += sf_sent; + + } + + else if (loop_cnt == 0) { /* This file can not be sent using sendfile. * This might be the case for pseudo-files in the * /sys/ and /proc/ file system. @@ -101,9 +114,7 @@ void XX_httplib_send_file_data( struct httplib_connection *conn, struct file *fi while (len > 0) { /* Calculate how much to read from the file in the buffer */ to_read = sizeof(buf); - if ((int64_t)to_read > len) { - to_read = (int)len; - } + if ((int64_t)to_read > len) to_read = (int)len; /* Read from file, exit the loop on error */ if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->fp)) <= 0) break; diff --git a/src/httplib_send_no_cache_header.c b/src/httplib_send_no_cache_header.c index db54374c..11eda5bf 100644 --- a/src/httplib_send_no_cache_header.c +++ b/src/httplib_send_no_cache_header.c @@ -22,18 +22,21 @@ * THE SOFTWARE. * * ============ - * Release: 1.8 + * Release: 2.0 */ #include "httplib_main.h" int XX_httplib_send_no_cache_header( struct httplib_connection *conn ) { - /* Send all current and obsolete cache opt-out directives. */ - return httplib_printf(conn, + /* + * Send all current and obsolete cache opt-out directives. + */ + + return httplib_printf( conn, "Cache-Control: no-cache, no-store, " "must-revalidate, private, max-age=0\r\n" "Pragma: no-cache\r\n" - "Expires: 0\r\n"); + "Expires: 0\r\n" ); } /* XX_httplib_send_no_cache_header */ diff --git a/src/httplib_ssl_get_client_cert_info.c b/src/httplib_ssl_get_client_cert_info.c index aa1e6a50..7a6945be 100644 --- a/src/httplib_ssl_get_client_cert_info.c +++ b/src/httplib_ssl_get_client_cert_info.c @@ -34,8 +34,6 @@ static int hexdump2string( void *mem, int memlen, char *buf, int buflen ); - - /* * void XX_httplib_ssl_get_client_cert_info( struct httplib_connection *conn ); * @@ -62,7 +60,7 @@ void XX_httplib_ssl_get_client_cert_info( struct httplib_connection *conn ) { /* Get Subject and issuer */ X509_NAME *subj = X509_get_subject_name(cert); - X509_NAME *iss = X509_get_issuer_name(cert); + X509_NAME *iss = X509_get_issuer_name(cert); /* Get serial number */ ASN1_INTEGER *serial = X509_get_serialNumber(cert); diff --git a/src/httplib_sslize.c b/src/httplib_sslize.c index 6405d161..626b8fb7 100644 --- a/src/httplib_sslize.c +++ b/src/httplib_sslize.c @@ -22,7 +22,7 @@ * THE SOFTWARE. * * ============ - * Release: 1.8 + * Release: 2.0 */ #include "httplib_main.h" @@ -45,31 +45,41 @@ int XX_httplib_sslize( struct httplib_connection *conn, SSL_CTX *s, int (*func)( if ( conn == NULL ) return 0; - short_trust = (conn->ctx->config[SSL_SHORT_TRUST] != NULL) && (httplib_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0); + short_trust = ( conn->ctx->config[SSL_SHORT_TRUST] != NULL && ! httplib_strcasecmp( conn->ctx->config[SSL_SHORT_TRUST], "yes" ) ); - if (short_trust) { - int trust_ret = XX_httplib_refresh_trust(conn); - if (!trust_ret) return trust_ret; + if ( short_trust ) { + + int trust_ret = XX_httplib_refresh_trust( conn ); + if ( ! trust_ret ) return trust_ret; } - conn->ssl = SSL_new(s); - if (conn->ssl == NULL) return 0; + conn->ssl = SSL_new( s ); + if ( conn->ssl == NULL ) return 0; - ret = SSL_set_fd(conn->ssl, conn->client.sock); - if (ret != 1) { - err = SSL_get_error(conn->ssl, ret); + ret = SSL_set_fd( conn->ssl, conn->client.sock ); + + if ( ret != 1 ) { + + err = SSL_get_error( conn->ssl, ret ); (void)err; /* TODO: set some error message */ - SSL_free(conn->ssl); + SSL_free( conn->ssl ); conn->ssl = NULL; - /* Avoid CRYPTO_cleanup_all_ex_data(); See discussion: - * https://wiki.openssl.org/index.php/Talk:Library_Initialization */ - ERR_remove_state(0); + + /* + * Avoid CRYPTO_cleanup_all_ex_data(); See discussion: + * https://wiki.openssl.org/index.php/Talk:Library_Initialization + */ + + ERR_remove_state( 0 ); return 0; } - /* SSL functions may fail and require to be called again: + /* + * SSL functions may fail and require to be called again: * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html - * Here "func" could be SSL_connect or SSL_accept. */ + * Here "func" could be SSL_connect or SSL_accept. + */ + for (i = 0; i <= 16; i *= 2) { ret = func(conn->ssl); if (ret != 1) { @@ -85,12 +95,17 @@ int XX_httplib_sslize( struct httplib_connection *conn, SSL_CTX *s, int (*func)( else break; /* Success */ } - if (ret != 1) { - SSL_free(conn->ssl); + if ( ret != 1 ) { + + SSL_free( conn->ssl ); conn->ssl = NULL; - /* Avoid CRYPTO_cleanup_all_ex_data(); See discussion: - * https://wiki.openssl.org/index.php/Talk:Library_Initialization */ - ERR_remove_state(0); + /* + * Avoid CRYPTO_cleanup_all_ex_data(); See discussion: + * https://wiki.openssl.org/index.php/Talk:Library_Initialization + */ + + ERR_remove_state( 0 ); + return 0; } diff --git a/src/httplib_stat.c b/src/httplib_stat.c index 09c82317..850d0cbc 100644 --- a/src/httplib_stat.c +++ b/src/httplib_stat.c @@ -103,16 +103,19 @@ int XX_httplib_stat( struct httplib_connection *conn, const char *path, struct f int XX_httplib_stat( struct httplib_connection *conn, const char *path, struct file *filep ) { struct stat st; - if (!filep) return 0; - memset(filep, 0, sizeof(*filep)); + if ( filep == NULL ) return 0; - if (conn && XX_httplib_is_file_in_memory(conn, path, filep)) return 1; + memset( filep, 0, sizeof(*filep) ); - if (0 == stat(path, &st)) { - filep->size = (uint64_t)(st.st_size); + if ( conn != NULL && XX_httplib_is_file_in_memory( conn, path, filep ) ) return 1; + + if ( stat( path, &st ) == 0 ) { + + filep->size = (uint64_t)(st.st_size); filep->last_modified = st.st_mtime; - filep->is_directory = S_ISDIR(st.st_mode); + filep->is_directory = S_ISDIR(st.st_mode); + return 1; } diff --git a/src/httplib_store_body.c b/src/httplib_store_body.c index 5a8562d1..7d762ebf 100644 --- a/src/httplib_store_body.c +++ b/src/httplib_store_body.c @@ -50,12 +50,13 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path ) } ret = XX_httplib_put_dir( conn, path ); - if (ret < 0) { + if ( ret < 0 ) { + /* -1 for path too long, * -2 for path can not be created. */ return ret; } - if (ret != 1) { + if ( ret != 1 ) { /* Return 0 means, path itself is a directory. */ return 0; } @@ -64,7 +65,7 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path ) ret = httplib_read( conn, buf, sizeof(buf) ); - while ( ret > 0) { + while ( ret > 0 ) { n = (int)fwrite( buf, 1, (size_t)ret, fi.fp ); if ( n != ret ) { @@ -76,8 +77,11 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path ) ret = httplib_read( conn, buf, sizeof(buf) ); } - /* TODO: XX_httplib_fclose should return an error, - * and every caller should check and handle it. */ + /* + * TODO: XX_httplib_fclose should return an error, + * and every caller should check and handle it. + */ + if ( fclose(fi.fp) != 0 ) { XX_httplib_remove_bad_file( conn, path ); diff --git a/src/httplib_uninitialize_ssl.c b/src/httplib_uninitialize_ssl.c index e5f9eea2..da1c5b22 100644 --- a/src/httplib_uninitialize_ssl.c +++ b/src/httplib_uninitialize_ssl.c @@ -22,7 +22,7 @@ * THE SOFTWARE. * * ============ - * Release: 1.8 + * Release: 2.0 */ #include "httplib_main.h" @@ -39,33 +39,36 @@ */ #if !defined(NO_SSL) + void XX_httplib_uninitialize_ssl( struct httplib_context *ctx ) { UNUSED_PARAMETER(ctx); int i; - if (httplib_atomic_dec(&XX_httplib_cryptolib_users) == 0) { + if ( httplib_atomic_dec( & XX_httplib_cryptolib_users ) == 0 ) { - /* Shutdown according to + /* + * Shutdown according to * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl */ - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); + + CRYPTO_set_locking_callback( NULL ); + CRYPTO_set_id_callback( NULL ); ENGINE_cleanup(); - CONF_modules_unload(1); + CONF_modules_unload( 1 ); ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); - ERR_remove_state(0); + ERR_remove_state( 0 ); + + for (i=0; i= 0) && ((size_t)n < buflen); #ifdef __clang__ @@ -52,9 +55,11 @@ void XX_httplib_vsnprintf( const struct httplib_connection *conn, int *truncated #endif if (ok) { - if (truncated) *truncated = 0; - } else { - if (truncated) *truncated = 1; + if ( truncated != NULL ) *truncated = 0; + } + + else { + if ( truncated != NULL ) *truncated = 1; httplib_cry(conn, "truncating vsnprintf buffer: [%.*s]", (int)((buflen > 200) ? 200 : (buflen - 1)), buf); n = (int)buflen - 1; }