Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F2020142
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/examples/simplelog.c b/examples/simplelog.c
index 8fb0941..17e3b61 100644
--- a/examples/simplelog.c
+++ b/examples/simplelog.c
@@ -1,249 +1,255 @@
/*
* Copyright (c) 2011 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* libqb is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* libqb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include <signal.h>
#include <syslog.h>
#include <qb/qbdefs.h>
#include <qb/qblog.h>
#define MY_TAG_ONE (1)
#define MY_TAG_TWO (1 << 1)
#define MY_TAG_THREE (1 << 2)
static int32_t _log_priority = LOG_WARNING;
static void
func_one(void)
{
FILE *fd;
qb_enter();
qb_logt(LOG_DEBUG, MY_TAG_TWO, "arf arf?");
qb_logt(LOG_CRIT, MY_TAG_THREE, "arrrg!");
qb_logt(134, MY_TAG_THREE, "big priority");
qb_logt(LOG_ERR, MY_TAG_THREE, "oops, I did it again");
qb_log(LOG_INFO, "are you aware ...");
fd = fopen("/nothing.txt", "r+");
if (fd == NULL) {
qb_perror(LOG_ERR, "can't open(\"/nothing.txt\")");
} else {
fclose(fd);
}
qb_leave();
}
static void
func_two(void)
{
qb_enter();
qb_logt(LOG_DEBUG, 0, "arf arf?");
qb_logt(LOG_CRIT, MY_TAG_ONE, "arrrg!");
qb_log(LOG_ERR, "oops, I did it again");
qb_logt(LOG_INFO, MY_TAG_THREE, "are you aware ...");
qb_leave();
}
static void
show_usage(const char *name)
{
printf("usage: \n");
printf("%s <options>\n", name);
printf("\n");
printf(" options:\n");
printf("\n");
printf(" -v verbose\n");
printf(" -t threaded logging\n");
printf(" -e log to stderr\n");
printf(" -b log to blackbox\n");
printf(" -f <filename> log to a file\n");
printf(" -h show this help text\n");
printf("\n");
}
static int32_t do_blackbox = QB_FALSE;
static int32_t do_threaded = QB_FALSE;
static void
sigsegv_handler(int sig)
{
(void)signal(SIGSEGV, SIG_DFL);
qb_log_fini();
if (do_blackbox) {
qb_log_blackbox_write_to_file("simple-log.fdata");
}
raise(SIGSEGV);
}
static const char *
my_tags_stringify(uint32_t tags)
{
if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT)) {
return "libqb";
} else if (qb_bit_is_set(tags, 0)) {
return "ONE";
} else if (qb_bit_is_set(tags, 1)) {
return "TWO";
} else if (qb_bit_is_set(tags, 2)) {
return "THREE";
} else {
return "MAIN";
}
}
static void
trace_logger(int32_t t,
struct qb_log_callsite *cs, time_t timestamp, const char *msg)
{
char output_buffer[QB_LOG_MAX_LEN];
output_buffer[0] = '\0';
qb_log_target_format(t, cs, timestamp, msg, output_buffer);
fprintf(stderr, "%s\n", output_buffer);
}
static void
m_filter(struct qb_log_callsite *cs)
{
if ((cs->priority >= LOG_ALERT &&
cs->priority <= _log_priority) &&
strcmp(cs->filename, __FILE__) == 0) {
qb_bit_set(cs->targets, QB_LOG_STDERR);
} else {
qb_bit_clear(cs->targets, QB_LOG_STDERR);
}
}
int32_t
main(int32_t argc, char *argv[])
{
const char *options = "vhteobdf:";
int32_t opt;
int32_t tracer;
int32_t do_stderr = QB_FALSE;
int32_t do_stdout = QB_FALSE;
int32_t do_dump_blackbox = QB_FALSE;
char *logfile = NULL;
int32_t log_fd = -1;
while ((opt = getopt(argc, argv, options)) != -1) {
switch (opt) {
case 'd':
do_dump_blackbox = QB_TRUE;
break;
case 't':
do_threaded = QB_TRUE;
break;
case 'e':
do_stderr = QB_TRUE;
break;
case 'o':
do_stdout = QB_TRUE;
break;
case 'b':
do_blackbox = QB_TRUE;
break;
case 'f':
logfile = optarg;
break;
case 'v':
_log_priority++;
break;
case 'h':
default:
show_usage(argv[0]);
exit(0);
break;
}
}
if (do_dump_blackbox) {
qb_log_blackbox_print_from_file("simple-log.fdata");
exit(0);
}
signal(SIGSEGV, sigsegv_handler);
qb_log_init("simple-log", LOG_USER, LOG_INFO);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded);
qb_log_tags_stringify_fn_set(my_tags_stringify);
if (do_stderr) {
qb_log_filter_fn_set(m_filter);
qb_log_format_set(QB_LOG_STDERR, "[%p] %4g: %f:%l %b");
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL);
qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_format_set(tracer, "%4g: %n() %b");
qb_log_filter_ctl2(tracer, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, __FILE__,
LOG_TRACE, 200);
}
if (do_stdout) {
qb_log_filter_ctl2(QB_LOG_STDOUT, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, __FILE__,
LOG_ALERT, QB_MIN(LOG_DEBUG, _log_priority));
qb_log_format_set(QB_LOG_STDOUT, "[%p] %4g: %f:%l %b");
qb_log_ctl(QB_LOG_STDOUT, QB_LOG_CONF_ENABLED, QB_TRUE);
}
if (do_blackbox) {
qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 4096);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
}
if (logfile) {
log_fd = qb_log_file_open(logfile);
qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, __FILE__, _log_priority);
qb_log_format_set(log_fd, "[%N] %t %n() [%p] %b");
qb_log_ctl(log_fd, QB_LOG_CONF_THREADED, do_threaded);
qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE);
}
if (do_threaded) {
qb_log_thread_start();
}
qb_log(LOG_DEBUG, "hello");
qb_log(LOG_INFO, "this is an info");
qb_log(LOG_NOTICE, "hello - notice?");
+ {
+ char * str = NULL;
+ qb_log(LOG_ERR,
+ "%s ------%s------------- %u?",
+ NULL, str, 56);
+ }
func_one();
func_two();
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log(LOG_WARNING, "no syslog");
qb_log(LOG_ERR, "no syslog");
#if 0
// test blackbox
logfile = NULL;
logfile[5] = 'a';
#endif
if (do_blackbox) {
qb_log_blackbox_write_to_file("simple-log.fdata");
qb_log_blackbox_print_from_file("simple-log.fdata");
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
}
qb_log_fini();
return 0;
}
diff --git a/lib/log_format.c b/lib/log_format.c
index 0cbb543..6a74fbb 100644
--- a/lib/log_format.c
+++ b/lib/log_format.c
@@ -1,706 +1,710 @@
/*
* Copyright (C) 2011 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* libqb is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* libqb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include <ctype.h>
#include <qb/qbdefs.h>
#include "log_int.h"
static qb_log_tags_stringify_fn _user_tags_stringify_fn;
/*
* syslog prioritynames, facility names to value mapping
* Some C libraries build this in to their headers, but it is non-portable
* so logsys supplies its own version.
*/
struct syslog_names {
const char *c_name;
int32_t c_val;
};
static struct syslog_names prioritynames[] = {
{"emerg", LOG_EMERG},
{"alert", LOG_ALERT},
{"crit", LOG_CRIT},
{"error", LOG_ERR},
{"warning", LOG_WARNING},
{"notice", LOG_NOTICE},
{"info", LOG_INFO},
{"debug", LOG_DEBUG},
{"trace", LOG_TRACE},
{NULL, -1}
};
struct syslog_names facilitynames[] = {
{"auth", LOG_AUTH},
#if defined(LOG_AUTHPRIV)
{"authpriv", LOG_AUTHPRIV},
#endif
{"cron", LOG_CRON},
{"daemon", LOG_DAEMON},
#if defined(LOG_FTP)
{"ftp", LOG_FTP},
#endif
{"kern", LOG_KERN},
{"lpr", LOG_LPR},
{"mail", LOG_MAIL},
{"news", LOG_NEWS},
{"syslog", LOG_SYSLOG},
{"user", LOG_USER},
{"uucp", LOG_UUCP},
{"local0", LOG_LOCAL0},
{"local1", LOG_LOCAL1},
{"local2", LOG_LOCAL2},
{"local3", LOG_LOCAL3},
{"local4", LOG_LOCAL4},
{"local5", LOG_LOCAL5},
{"local6", LOG_LOCAL6},
{"local7", LOG_LOCAL7},
{NULL, -1}
};
static const char log_month_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
/* Convert string "auth" to equivalent number "LOG_AUTH" etc. */
int32_t
qb_log_facility2int(const char *fname)
{
int32_t i;
if (fname == NULL) {
return -EINVAL;
}
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (strcmp(fname, facilitynames[i].c_name) == 0) {
return facilitynames[i].c_val;
}
}
return -EINVAL;
}
/* Convert number "LOG_AUTH" to equivalent string "auth" etc. */
const char *
qb_log_facility2str(int32_t fnum)
{
int32_t i;
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (facilitynames[i].c_val == fnum) {
return facilitynames[i].c_name;
}
}
return NULL;
}
void
qb_log_tags_stringify_fn_set(qb_log_tags_stringify_fn fn)
{
_user_tags_stringify_fn = fn;
}
static int
_strcpy_cutoff(char *dest, const char *src, size_t cutoff, int ralign,
size_t buf_len)
{
size_t len = strlen(src);
if (buf_len <= 1) {
if (buf_len == 0)
dest[0] = 0;
return 0;
}
if (cutoff == 0) {
cutoff = len;
}
cutoff = QB_MIN(cutoff, buf_len - 1);
len = QB_MIN(len, cutoff);
if (ralign) {
memset(dest, ' ', cutoff - len);
memcpy(dest + cutoff - len, src, len);
} else {
memcpy(dest, src, len);
memset(dest + len, ' ', cutoff - len);
}
dest[cutoff] = '\0';
return cutoff;
}
/*
* This function will do static formatting (for things that don't
* change on each log message).
*
* %P PID
* %N name passed into qb_log_init
* %H hostname
*
* any number between % and character specify field length to pad or chop
*/
void
qb_log_target_format_static(int32_t target, const char * format,
char *output_buffer)
{
char tmp_buf[255];
unsigned int format_buffer_idx = 0;
unsigned int output_buffer_idx = 0;
size_t cutoff;
uint32_t len;
int ralign;
int c;
struct qb_log_target *t = qb_log_target_get(target);
if (format == NULL) {
return;
}
while ((c = format[format_buffer_idx])) {
cutoff = 0;
ralign = 0;
if (c != '%') {
output_buffer[output_buffer_idx++] = c;
format_buffer_idx++;
} else {
const char *p;
unsigned int percent_buffer_idx = format_buffer_idx;
format_buffer_idx += 1;
if (format[format_buffer_idx] == '-') {
ralign = 1;
format_buffer_idx += 1;
}
if (isdigit(format[format_buffer_idx])) {
cutoff = atoi(&format[format_buffer_idx]);
}
while (isdigit(format[format_buffer_idx])) {
format_buffer_idx += 1;
}
switch (format[format_buffer_idx]) {
case 'P':
snprintf(tmp_buf, 30, "%d", getpid());
p = tmp_buf;
break;
case 'N':
p = t->name;
break;
case 'H':
if (gethostname(tmp_buf, 255) == 0) {
tmp_buf[254] = '\0';
} else {
(void)strlcpy(tmp_buf, "localhost", 255);
}
p = tmp_buf;
break;
default:
p = &format[percent_buffer_idx];
cutoff = (format_buffer_idx - percent_buffer_idx + 1);
ralign = 0;
break;
}
len = _strcpy_cutoff(output_buffer + output_buffer_idx,
p, cutoff, ralign,
(QB_LOG_MAX_LEN -
output_buffer_idx));
output_buffer_idx += len;
format_buffer_idx += 1;
}
if (output_buffer_idx >= QB_LOG_MAX_LEN - 1) {
break;
}
}
output_buffer[output_buffer_idx] = '\0';
}
/*
* %n FUNCTION NAME
* %f FILENAME
* %l FILELINE
* %p PRIORITY
* %t TIMESTAMP
* %b BUFFER
* %g SUBSYSTEM
*
* any number between % and character specify field length to pad or chop
*/
void
qb_log_target_format(int32_t target,
struct qb_log_callsite *cs,
time_t current_time,
const char *formatted_message, char *output_buffer)
{
char tmp_buf[128];
struct tm tm_res;
unsigned int format_buffer_idx = 0;
unsigned int output_buffer_idx = 0;
size_t cutoff;
uint32_t len;
int ralign;
int c;
struct qb_log_target *t = qb_log_target_get(target);
if (t->format == NULL) {
return;
}
while ((c = t->format[format_buffer_idx])) {
cutoff = 0;
ralign = 0;
if (c != '%') {
output_buffer[output_buffer_idx++] = c;
format_buffer_idx++;
} else {
const char *p;
format_buffer_idx += 1;
if (t->format[format_buffer_idx] == '-') {
ralign = 1;
format_buffer_idx += 1;
}
if (isdigit(t->format[format_buffer_idx])) {
cutoff = atoi(&t->format[format_buffer_idx]);
}
while (isdigit(t->format[format_buffer_idx])) {
format_buffer_idx += 1;
}
switch (t->format[format_buffer_idx]) {
case 'g':
if (_user_tags_stringify_fn) {
p = _user_tags_stringify_fn(cs->tags);
} else {
p = "";
}
break;
case 'n':
p = cs->function;
break;
case 'f':
#ifdef BUILDING_IN_PLACE
p = cs->filename;
#else
p = strrchr(cs->filename, '/');
if (p == NULL) {
p = cs->filename;
} else {
p++; /* move past the "/" */
}
#endif /* BUILDING_IN_PLACE */
break;
case 'l':
snprintf(tmp_buf, 30, "%d", cs->lineno);
p = tmp_buf;
break;
case 't':
(void)localtime_r(¤t_time, &tm_res);
snprintf(tmp_buf, TIME_STRING_SIZE,
"%s %02d %02d:%02d:%02d",
log_month_name[tm_res.tm_mon],
tm_res.tm_mday, tm_res.tm_hour,
tm_res.tm_min, tm_res.tm_sec);
p = tmp_buf;
break;
case 'b':
p = formatted_message;
break;
case 'p':
if (cs->priority > LOG_TRACE) {
p = prioritynames[LOG_TRACE].c_name;
} else {
p = prioritynames[cs->priority].c_name;
}
break;
default:
p = "";
break;
}
len = _strcpy_cutoff(output_buffer + output_buffer_idx,
p, cutoff, ralign,
(QB_LOG_MAX_LEN -
output_buffer_idx));
output_buffer_idx += len;
format_buffer_idx += 1;
}
if (output_buffer_idx >= QB_LOG_MAX_LEN - 1) {
break;
}
}
if (output_buffer[output_buffer_idx - 1] == '\n') {
output_buffer[output_buffer_idx - 1] = '\0';
} else {
output_buffer[output_buffer_idx] = '\0';
}
}
size_t
qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap)
{
char *format;
char *p;
uint32_t location = 0;
int type_long = 0;
int type_longlong = 0;
p = stpcpy(serialize, fmt);
location = p - serialize + 1;
format = (char *)fmt;
for (;;) {
type_long = 0;
type_longlong = 0;
p = strchrnul((const char *)format, '%');
if (*p == '\0') {
break;
}
format = p + 1;
reprocess:
switch (format[0]) {
case '#': /* alternate form conversion, ignore */
case '-': /* left adjust, ignore */
case ' ': /* a space, ignore */
case '+': /* a sign should be used, ignore */
case '\'': /* group in thousands, ignore */
case 'I': /* glibc-ism locale alternative, ignore */
case '.': /* precision, ignore */
case '0': /* field width, ignore */
case '1': /* field width, ignore */
case '2': /* field width, ignore */
case '3': /* field width, ignore */
case '4': /* field width, ignore */
case '5': /* field width, ignore */
case '6': /* field width, ignore */
case '7': /* field width, ignore */
case '8': /* field width, ignore */
case '9': /* field width, ignore */
format++;
goto reprocess;
case '*': /* variable field width, save */ {
int arg_int = va_arg(ap, int);
memcpy(&serialize[location], &arg_int, sizeof (int));
location += sizeof(int);
format++;
goto reprocess;
}
case 'l':
format++;
type_long = 1;
if (*format == 'l') {
type_long = 0;
type_longlong = 1;
format++;
}
goto reprocess;
case 'd': /* int argument */
case 'i': /* int argument */
case 'o': /* unsigned int argument */
case 'u':
case 'x':
case 'X':
if (type_long) {
long int arg_int;
arg_int = va_arg(ap, long int);
memcpy(&serialize[location], &arg_int,
sizeof(long int));
location += sizeof(long int);
format++;
break;
} else if (type_longlong) {
long long int arg_int;
arg_int = va_arg(ap, long long int);
memcpy(&serialize[location], &arg_int,
sizeof(long long int));
location += sizeof(long long int);
format++;
break;
} else {
int arg_int;
arg_int = va_arg(ap, int);
memcpy(&serialize[location], &arg_int,
sizeof(int));
location += sizeof(int);
format++;
break;
}
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
case 'a':
case 'A':
{
double arg_double;
arg_double = va_arg(ap, double);
memcpy (&serialize[location], &arg_double, sizeof (double));
location += sizeof(double);
format++;
break;
}
case 'c':
{
int arg_int;
unsigned char arg_char;
arg_int = va_arg(ap, unsigned int);
arg_char = (unsigned char)arg_int;
memcpy (&serialize[location], &arg_char, sizeof (unsigned char));
location += sizeof(unsigned char);
break;
}
case 's':
{
char *arg_string;
arg_string = va_arg(ap, char *);
- p = stpcpy(&serialize[location], arg_string);
+ if (arg_string == NULL) {
+ p = stpcpy(&serialize[location], "(null)");
+ } else {
+ p = stpcpy(&serialize[location], arg_string);
+ }
location += p - &serialize[location] + 1;
break;
}
case 'p':
{
void *arg_pointer;
arg_pointer = va_arg(ap, void *);
memcpy (&serialize[location], &arg_pointer, sizeof (void *));
location += sizeof (arg_pointer);
break;
}
case '%':
serialize[location++] = '%';
break;
}
}
return (location);
}
#define MINI_FORMAT_STR_LEN 20
size_t
qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf)
{
char *p;
char *format;
char fmt[MINI_FORMAT_STR_LEN];
int fmt_pos;
uint32_t location = 0;
uint32_t data_pos = strlen(buf) + 1;
int type_long = 0;
int type_longlong = 0;
int len;
format = (char *)buf;
for (;;) {
type_long = 0;
type_longlong = 0;
p = strchrnul((const char *)format, '%');
if (*p == '\0') {
p = stpcpy(&string[location], format);
location += p - &string[location] + 1;
break;
}
/* copy from current to the next % */
len = p - format;
strncpy(&string[location], format, len);
location += len;
format = p;
/* start building up the format for snprintf */
fmt_pos = 0;
fmt[fmt_pos++] = *format;
format++;
reprocess:
switch (format[0]) {
case '#': /* alternate form conversion, ignore */
case '-': /* left adjust, ignore */
case ' ': /* a space, ignore */
case '+': /* a sign should be used, ignore */
case '\'': /* group in thousands, ignore */
case 'I': /* glibc-ism locale alternative, ignore */
case '.': /* precision, ignore */
case '0': /* field width, ignore */
case '1': /* field width, ignore */
case '2': /* field width, ignore */
case '3': /* field width, ignore */
case '4': /* field width, ignore */
case '5': /* field width, ignore */
case '6': /* field width, ignore */
case '7': /* field width, ignore */
case '8': /* field width, ignore */
case '9': /* field width, ignore */
fmt[fmt_pos++] = *format;
format++;
goto reprocess;
case '*': {
int arg_int;
memcpy(&arg_int, &buf[data_pos], sizeof(int));
data_pos += sizeof(int);
fmt_pos += snprintf(&fmt[fmt_pos],
MINI_FORMAT_STR_LEN - fmt_pos,
"%d", arg_int);
format++;
goto reprocess;
}
case 'l':
fmt[fmt_pos++] = *format;
format++;
type_long = 1;
if (*format == 'l') {
type_long = 0;
type_longlong = 1;
}
goto reprocess;
case 'd': /* int argument */
case 'i': /* int argument */
case 'o': /* unsigned int argument */
case 'u':
case 'x':
case 'X':
if (type_long) {
long int arg_int;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_int, &buf[data_pos], sizeof(long int));
location += snprintf(&string[location],
str_len - location,
fmt, arg_int);
data_pos += sizeof(long int);
format++;
break;
} else if (type_longlong) {
long long int arg_int;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_int, &buf[data_pos], sizeof(long long int));
location += snprintf(&string[location],
str_len - location,
fmt, arg_int);
data_pos += sizeof(long long int);
format++;
break;
} else {
int arg_int;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_int, &buf[data_pos], sizeof(int));
location += snprintf(&string[location],
str_len - location,
fmt, arg_int);
data_pos += sizeof(int);
format++;
break;
}
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
case 'a':
case 'A':
{
double arg_double;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_double, &buf[data_pos], sizeof(double));
location += snprintf(&string[location],
str_len - location,
fmt, arg_double);
data_pos += sizeof(double);
format++;
break;
}
case 'c':
{
unsigned char *arg_char;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
arg_char = (unsigned char*)&buf[data_pos];
location += snprintf(&string[location],
str_len - location,
fmt, *arg_char);
data_pos += sizeof(unsigned char);
format++;
break;
}
case 's':
{
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
len = snprintf(&string[location],
str_len - location,
fmt, &buf[data_pos]);
location += len;
data_pos += len + 1;
format++;
break;
}
case 'p':
{
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
location = snprintf(&string[location],
str_len - location,
fmt, &buf[data_pos]);
data_pos += sizeof(void*);
format++;
break;
}
case '%':
string[location++] = '%';
format++;
break;
}
}
return location;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 12:42 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128368
Default Alt Text
(22 KB)
Attached To
Mode
rQ LibQB
Attached
Detach File
Event Timeline
Log In to Comment