mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-07 11:30:18 +00:00
New JNI interface to better support cursor result sets
This commit is contained in:
parent
03536301f8
commit
3a93fee8a5
2
cli.c
2
cli.c
@ -99,6 +99,7 @@ int cli_arg(int argc, const char *const *argv, const struct command_line_option
|
|||||||
int arglen = strlen(argname);
|
int arglen = strlen(argname);
|
||||||
int i;
|
int i;
|
||||||
const char *word;
|
const char *word;
|
||||||
|
*dst = defaultvalue;
|
||||||
for(i = 0; (word = o->words[i]); ++i) {
|
for(i = 0; (word = o->words[i]); ++i) {
|
||||||
int wordlen = strlen(word);
|
int wordlen = strlen(word);
|
||||||
/* No need to check that the "<...>" and "[<...>]" are all intact in the command_line_option,
|
/* No need to check that the "<...>" and "[<...>]" are all intact in the command_line_option,
|
||||||
@ -118,7 +119,6 @@ int cli_arg(int argc, const char *const *argv, const struct command_line_option
|
|||||||
never happen, but it can because more than one version of a command line option may exist, one
|
never happen, but it can because more than one version of a command line option may exist, one
|
||||||
with a given argument and another without, and allowing a default value means we can have a
|
with a given argument and another without, and allowing a default value means we can have a
|
||||||
single function handle both in a fairly simple manner. */
|
single function handle both in a fairly simple manner. */
|
||||||
*dst = defaultvalue;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
242
commandline.c
242
commandline.c
@ -61,8 +61,9 @@ int commandline_usage(int argc, const char *const *argv, const struct command_li
|
|||||||
JNIEnv *jni_env = NULL;
|
JNIEnv *jni_env = NULL;
|
||||||
int jni_exception = 0;
|
int jni_exception = 0;
|
||||||
|
|
||||||
jobject outv_list = NULL;
|
jobject jniResults = NULL;
|
||||||
jmethodID listAddMethodId = NULL;
|
jclass IJniResults = NULL;
|
||||||
|
jmethodID startResultSet, setColumnName, putString, putBlob, putLong, putDouble, totalRowCount;
|
||||||
|
|
||||||
char *outv_buffer = NULL;
|
char *outv_buffer = NULL;
|
||||||
char *outv_current = NULL;
|
char *outv_current = NULL;
|
||||||
@ -84,98 +85,128 @@ static int outv_growbuf(size_t needed)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outv_end_field()
|
static int put_blob(jbyte *value, jsize length){
|
||||||
{
|
jbyteArray arr = NULL;
|
||||||
size_t length = outv_current - outv_buffer;
|
if (value && length>0){
|
||||||
outv_current = outv_buffer;
|
arr = (*jni_env)->NewByteArray(jni_env, length);
|
||||||
jbyteArray arr = (*jni_env)->NewByteArray(jni_env, length);
|
if (arr == NULL || (*jni_env)->ExceptionOccurred(jni_env)) {
|
||||||
if (arr == NULL) {
|
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
return WHY("Exception thrown from NewByteArray()");
|
return WHY("Exception thrown from NewByteArray()");
|
||||||
}
|
}
|
||||||
(*jni_env)->SetByteArrayRegion(jni_env, arr, 0, length, (jbyte*)outv_buffer);
|
(*jni_env)->SetByteArrayRegion(jni_env, arr, 0, length, value);
|
||||||
if ((*jni_env)->ExceptionOccurred(jni_env)) {
|
if ((*jni_env)->ExceptionOccurred(jni_env)) {
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
return WHY("Exception thrown from SetByteArrayRegion()");
|
return WHYF("Exception thrown from SetByteArrayRegion()");
|
||||||
}
|
}
|
||||||
(*jni_env)->CallBooleanMethod(jni_env, outv_list, listAddMethodId, arr);
|
}
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, putBlob, arr);
|
||||||
if ((*jni_env)->ExceptionOccurred(jni_env)) {
|
if ((*jni_env)->ExceptionOccurred(jni_env)) {
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
return WHY("Exception thrown from CallBooleanMethod()");
|
return WHY("Exception thrown from CallVoidMethod()");
|
||||||
}
|
}
|
||||||
|
if (arr)
|
||||||
(*jni_env)->DeleteLocalRef(jni_env, arr);
|
(*jni_env)->DeleteLocalRef(jni_env, arr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int outv_end_field()
|
||||||
|
{
|
||||||
|
jsize length = outv_current - outv_buffer;
|
||||||
|
outv_current = outv_buffer;
|
||||||
|
return put_blob((jbyte *)outv_buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Throw(JNIEnv *env, const char *class, const char *msg){
|
||||||
|
jclass exceptionClass = NULL;
|
||||||
|
if ((exceptionClass = (*env)->FindClass(env, class)) == NULL)
|
||||||
|
return -1; // exception
|
||||||
|
(*env)->ThrowNew(env, exceptionClass, msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* JNI entry point to command line. See org.servalproject.servald.ServalD class for the Java side.
|
/* JNI entry point to command line. See org.servalproject.servald.ServalD class for the Java side.
|
||||||
JNI method descriptor: "(Ljava/util/List;[Ljava/lang/String;)I"
|
JNI method descriptor: "(Ljava/util/List;[Ljava/lang/String;)I"
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jint JNICALL Java_org_servalproject_servald_ServalD_rawCommand(JNIEnv *env, jobject this, jobject outv, jobjectArray args)
|
JNIEXPORT jint JNICALL Java_org_servalproject_servald_ServalD_rawCommand(JNIEnv *env, jobject this, jobject outv, jobjectArray args)
|
||||||
{
|
{
|
||||||
jclass stringClass = NULL;
|
if (!IJniResults){
|
||||||
jclass listClass = NULL;
|
IJniResults = (*env)->FindClass(env, "org/servalproject/servald/IJniResults");
|
||||||
unsigned char status = 0; // to match what the shell gets: 0..255
|
if (IJniResults==NULL)
|
||||||
// Enforce non re-entrancy.
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate class org.servalproject.servald.IJniResults");
|
||||||
if (jni_env) {
|
startResultSet = (*env)->GetMethodID(env, IJniResults, "startResultSet", "(I)V");
|
||||||
jclass exceptionClass = NULL;
|
if (startResultSet==NULL)
|
||||||
if ((exceptionClass = (*env)->FindClass(env, "java/lang/IllegalStateException")) == NULL)
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method startResultSet");
|
||||||
return -1; // exception
|
setColumnName = (*env)->GetMethodID(env, IJniResults, "setColumnName", "(ILjava/lang/String;)V");
|
||||||
(*env)->ThrowNew(env, exceptionClass, "re-entrancy not supported");
|
if (setColumnName==NULL)
|
||||||
return -1;
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method setColumnName");
|
||||||
|
putString = (*env)->GetMethodID(env, IJniResults, "putString", "(Ljava/lang/String;)V");
|
||||||
|
if (putString==NULL)
|
||||||
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method putString");
|
||||||
|
putBlob = (*env)->GetMethodID(env, IJniResults, "putBlob", "([B)V");
|
||||||
|
if (putBlob==NULL)
|
||||||
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method putBlob");
|
||||||
|
putLong = (*env)->GetMethodID(env, IJniResults, "putLong", "(J)V");
|
||||||
|
if (putLong==NULL)
|
||||||
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method putLong");
|
||||||
|
putDouble = (*env)->GetMethodID(env, IJniResults, "putDouble", "(D)V");
|
||||||
|
if (putDouble==NULL)
|
||||||
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method putDouble");
|
||||||
|
totalRowCount = (*env)->GetMethodID(env, IJniResults, "totalRowCount", "(I)V");
|
||||||
|
if (totalRowCount==NULL)
|
||||||
|
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method totalRowCount");
|
||||||
}
|
}
|
||||||
// Get some handles to some classes and methods that we use later on.
|
unsigned char status = 0; // to match what the shell gets: 0..255
|
||||||
if ((stringClass = (*env)->FindClass(env, "java/lang/String")) == NULL)
|
|
||||||
return -1; // exception
|
if (jni_env)
|
||||||
if ((listClass = (*env)->FindClass(env, "java/util/List")) == NULL)
|
return Throw(env, "java/lang/IllegalStateException", "re-entrancy not supported");
|
||||||
return -1; // exception
|
|
||||||
if ((listAddMethodId = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z")) == NULL)
|
|
||||||
return -1; // exception
|
|
||||||
// Construct argv, argc from this method's arguments.
|
// Construct argv, argc from this method's arguments.
|
||||||
jsize len = (*env)->GetArrayLength(env, args);
|
jsize len = (*env)->GetArrayLength(env, args);
|
||||||
const char **argv = malloc(sizeof(char*) * (len + 1));
|
const char **argv = alloca(sizeof(char*) * (len + 1));
|
||||||
if (argv == NULL) {
|
if (argv == NULL)
|
||||||
jclass exceptionClass = NULL;
|
return Throw(env, "java/lang/OutOfMemoryError", "alloca returned NULL");
|
||||||
if ((exceptionClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError")) == NULL)
|
|
||||||
return -1; // exception
|
argv[len]=NULL;
|
||||||
(*env)->ThrowNew(env, exceptionClass, "malloc returned NULL");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
jsize i;
|
jsize i;
|
||||||
for (i = 0; i <= len; ++i)
|
|
||||||
argv[i] = NULL;
|
|
||||||
int argc = len;
|
int argc = len;
|
||||||
// From now on, in case of an exception we have to free some resources before
|
// From now on, in case of an exception we have to free some resources before
|
||||||
// returning.
|
// returning.
|
||||||
jni_exception = 0;
|
jni_exception = 0;
|
||||||
for (i = 0; !jni_exception && i != len; ++i) {
|
const char *empty="";
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
||||||
if (arg == NULL)
|
if ((*env)->ExceptionOccurred(env))
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
else {
|
|
||||||
|
argv[i] = empty;
|
||||||
|
if (arg != NULL && !jni_exception){
|
||||||
const char *str = (*env)->GetStringUTFChars(env, arg, NULL);
|
const char *str = (*env)->GetStringUTFChars(env, arg, NULL);
|
||||||
if (str == NULL)
|
if (str == NULL){
|
||||||
jni_exception = 1;
|
jni_exception = 1;
|
||||||
else
|
}else
|
||||||
argv[i] = str;
|
argv[i] = str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jni_exception) {
|
if (!jni_exception) {
|
||||||
// Set up the output buffer.
|
// Set up the output buffer.
|
||||||
outv_list = outv;
|
jniResults = outv;
|
||||||
outv_current = outv_buffer;
|
outv_current = outv_buffer;
|
||||||
// Execute the command.
|
// Execute the command.
|
||||||
jni_env = env;
|
jni_env = env;
|
||||||
status = parseCommandLine(NULL, argc, argv);
|
status = parseCommandLine(NULL, argc, argv);
|
||||||
jni_env = NULL;
|
jni_env = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release argv Java string buffers.
|
// Release argv Java string buffers.
|
||||||
for (i = 0; i != len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
if (argv[i]) {
|
if (argv[i] && argv[i]!=empty) {
|
||||||
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
const jstring arg = (jstring)(*env)->GetObjectArrayElement(env, args, i);
|
||||||
(*env)->ReleaseStringUTFChars(env, arg, argv[i]);
|
(*env)->ReleaseStringUTFChars(env, arg, argv[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(argv);
|
|
||||||
// Deal with Java exceptions: NewStringUTF out of memory in outv_end_field().
|
// Deal with Java exceptions: NewStringUTF out of memory in outv_end_field().
|
||||||
if (jni_exception || (outv_current != outv_buffer && outv_end_field() == -1))
|
if (jni_exception || (outv_current != outv_buffer && outv_end_field() == -1))
|
||||||
return -1;
|
return -1;
|
||||||
@ -231,7 +262,6 @@ int cli_putchar(char c)
|
|||||||
*outv_current++ = c;
|
*outv_current++ = c;
|
||||||
return (unsigned char) c;
|
return (unsigned char) c;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
return putchar(c);
|
return putchar(c);
|
||||||
}
|
}
|
||||||
@ -257,7 +287,6 @@ int cli_write(const unsigned char *buf, size_t len)
|
|||||||
outv_current += len;
|
outv_current += len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
return fwrite(buf, len, 1, stdout);
|
return fwrite(buf, len, 1, stdout);
|
||||||
}
|
}
|
||||||
@ -309,6 +338,117 @@ int cli_printf(const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cli_columns(int columns, const char *names[]){
|
||||||
|
#ifdef HAVE_JNI_H
|
||||||
|
if (jni_env) {
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, startResultSet, columns);
|
||||||
|
if ((*jni_env)->ExceptionOccurred(jni_env)) {
|
||||||
|
jni_exception = 1;
|
||||||
|
WHY("Exception thrown from CallVoidMethod()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for (i=0;i<columns;i++){
|
||||||
|
jstring str = (jstring)(*jni_env)->NewStringUTF(jni_env, names[i]);
|
||||||
|
if (str == NULL) {
|
||||||
|
jni_exception = 1;
|
||||||
|
WHY("Exception thrown from NewStringUTF()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, setColumnName, i, str);
|
||||||
|
(*jni_env)->DeleteLocalRef(jni_env, str);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cli_printf("%d",columns);
|
||||||
|
cli_delim("\n");
|
||||||
|
int i;
|
||||||
|
for (i=0;i<columns;i++){
|
||||||
|
cli_puts(names[i]);
|
||||||
|
if (i+1==columns)
|
||||||
|
cli_delim("\n");
|
||||||
|
else
|
||||||
|
cli_delim(":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cli_field_name(const char *name, const char *delim){
|
||||||
|
#ifdef HAVE_JNI_H
|
||||||
|
if (jni_env) {
|
||||||
|
jstring str = (jstring)(*jni_env)->NewStringUTF(jni_env, name);
|
||||||
|
if (str == NULL) {
|
||||||
|
jni_exception = 1;
|
||||||
|
WHY("Exception thrown from NewStringUTF()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, setColumnName, -1, str);
|
||||||
|
(*jni_env)->DeleteLocalRef(jni_env, str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cli_puts(name);
|
||||||
|
cli_delim(delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cli_put_long(int64_t value, const char *delim){
|
||||||
|
#ifdef HAVE_JNI_H
|
||||||
|
if (jni_env) {
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, putLong, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cli_printf("%lld",value);
|
||||||
|
cli_delim(delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cli_put_string(const char *value, const char *delim){
|
||||||
|
#ifdef HAVE_JNI_H
|
||||||
|
if (jni_env) {
|
||||||
|
jstring str = NULL;
|
||||||
|
if (value){
|
||||||
|
str = (jstring)(*jni_env)->NewStringUTF(jni_env, value);
|
||||||
|
if (str == NULL) {
|
||||||
|
jni_exception = 1;
|
||||||
|
WHY("Exception thrown from NewStringUTF()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, putString, str);
|
||||||
|
(*jni_env)->DeleteLocalRef(jni_env, str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (value)
|
||||||
|
cli_puts(value);
|
||||||
|
cli_delim(delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cli_put_hexvalue(const unsigned char *value, int length, const char *delim){
|
||||||
|
#ifdef HAVE_JNI_H
|
||||||
|
if (jni_env) {
|
||||||
|
put_blob((jbyte*)value, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (value)
|
||||||
|
cli_puts(alloca_tohex(value, length));
|
||||||
|
cli_delim(delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cli_row_count(int rows){
|
||||||
|
#ifdef HAVE_JNI_H
|
||||||
|
if (jni_env) {
|
||||||
|
(*jni_env)->CallVoidMethod(jni_env, jniResults, totalRowCount, rows);
|
||||||
|
if ((*jni_env)->ExceptionOccurred(jni_env)) {
|
||||||
|
jni_exception = 1;
|
||||||
|
WHY("Exception thrown from CallVoidMethod()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Delimit the current output field. This closes the current field, so that the next cli_ output
|
/* Delimit the current output field. This closes the current field, so that the next cli_ output
|
||||||
function will start appending to a new field. Returns 0 on success, -1 on error. If not in a
|
function will start appending to a new field. Returns 0 on success, -1 on error. If not in a
|
||||||
JNI call, then this simply writes a newline to standard output (or the value of the
|
JNI call, then this simply writes a newline to standard output (or the value of the
|
||||||
@ -1397,7 +1537,7 @@ int app_rhizome_list(int argc, const char *const *argv, const struct command_lin
|
|||||||
return -1;
|
return -1;
|
||||||
if (rhizome_opendb() == -1)
|
if (rhizome_opendb() == -1)
|
||||||
return -1;
|
return -1;
|
||||||
return rhizome_list_manifests(service, name, sender_sid, recipient_sid, atoi(offset), atoi(limit));
|
return rhizome_list_manifests(service, name, sender_sid, recipient_sid, atoi(offset), atoi(limit), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int app_keyring_create(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
int app_keyring_create(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||||
|
@ -310,7 +310,7 @@ long long rhizome_bar_version(unsigned char *bar);
|
|||||||
unsigned long long rhizome_bar_bidprefix_ll(unsigned char *bar);
|
unsigned long long rhizome_bar_bidprefix_ll(unsigned char *bar);
|
||||||
int rhizome_list_manifests(const char *service, const char *name,
|
int rhizome_list_manifests(const char *service, const char *name,
|
||||||
const char *sender_sid, const char *recipient_sid,
|
const char *sender_sid, const char *recipient_sid,
|
||||||
int limit, int offset);
|
int limit, int offset, char count_rows);
|
||||||
int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest *m);
|
int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest *m);
|
||||||
|
|
||||||
#define RHIZOME_DONTVERIFY 0
|
#define RHIZOME_DONTVERIFY 0
|
||||||
|
@ -930,11 +930,11 @@ rollback:
|
|||||||
|
|
||||||
int rhizome_list_manifests(const char *service, const char *name,
|
int rhizome_list_manifests(const char *service, const char *name,
|
||||||
const char *sender_sid, const char *recipient_sid,
|
const char *sender_sid, const char *recipient_sid,
|
||||||
int limit, int offset)
|
int limit, int offset, char count_rows)
|
||||||
{
|
{
|
||||||
IN();
|
IN();
|
||||||
strbuf b = strbuf_alloca(1024);
|
strbuf b = strbuf_alloca(1024);
|
||||||
strbuf_sprintf(b, "SELECT id, manifest, version, inserttime, author FROM manifests WHERE 1=1");
|
strbuf_sprintf(b, "SELECT id, manifest, version, inserttime, author, rowid FROM manifests WHERE 1=1");
|
||||||
|
|
||||||
if (service && *service)
|
if (service && *service)
|
||||||
strbuf_sprintf(b, " AND service = ?1");
|
strbuf_sprintf(b, " AND service = ?1");
|
||||||
@ -947,8 +947,6 @@ int rhizome_list_manifests(const char *service, const char *name,
|
|||||||
|
|
||||||
strbuf_sprintf(b, " ORDER BY inserttime DESC");
|
strbuf_sprintf(b, " ORDER BY inserttime DESC");
|
||||||
|
|
||||||
if (limit)
|
|
||||||
strbuf_sprintf(b, " LIMIT %u", limit);
|
|
||||||
if (offset)
|
if (offset)
|
||||||
strbuf_sprintf(b, " OFFSET %u", offset);
|
strbuf_sprintf(b, " OFFSET %u", offset);
|
||||||
|
|
||||||
@ -977,24 +975,30 @@ int rhizome_list_manifests(const char *service, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret=0;
|
ret=0;
|
||||||
|
|
||||||
size_t rows = 0;
|
size_t rows = 0;
|
||||||
cli_puts("12"); cli_delim("\n"); // number of columns
|
|
||||||
cli_puts("service"); cli_delim(":");
|
const char *names[]={
|
||||||
cli_puts("id"); cli_delim(":");
|
"_id",
|
||||||
cli_puts("version"); cli_delim(":");
|
"service",
|
||||||
cli_puts("date"); cli_delim(":");
|
"id",
|
||||||
cli_puts(".inserttime"); cli_delim(":");
|
"version",
|
||||||
cli_puts(".author"); cli_delim(":");
|
"date",
|
||||||
cli_puts(".fromhere"); cli_delim(":");
|
".inserttime",
|
||||||
cli_puts("filesize"); cli_delim(":");
|
".author",
|
||||||
cli_puts("filehash"); cli_delim(":");
|
".fromhere",
|
||||||
cli_puts("sender"); cli_delim(":");
|
"filesize",
|
||||||
cli_puts("recipient"); cli_delim(":");
|
"filehash",
|
||||||
cli_puts("name"); cli_delim("\n"); // should be last, because name may contain ':'
|
"sender",
|
||||||
|
"recipient",
|
||||||
|
"name"
|
||||||
|
};
|
||||||
|
cli_columns(13,names);
|
||||||
|
|
||||||
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
|
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
|
||||||
++rows;
|
++rows;
|
||||||
if (!( sqlite3_column_count(statement) == 5
|
if (limit>0 && rows>limit)
|
||||||
|
break;
|
||||||
|
if (!( sqlite3_column_count(statement) == 6
|
||||||
&& sqlite3_column_type(statement, 0) == SQLITE_TEXT
|
&& sqlite3_column_type(statement, 0) == SQLITE_TEXT
|
||||||
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
|
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
|
||||||
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
|
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
|
||||||
@ -1017,6 +1021,8 @@ int rhizome_list_manifests(const char *service, const char *name,
|
|||||||
long long q_version = sqlite3_column_int64(statement, 2);
|
long long q_version = sqlite3_column_int64(statement, 2);
|
||||||
long long q_inserttime = sqlite3_column_int64(statement, 3);
|
long long q_inserttime = sqlite3_column_int64(statement, 3);
|
||||||
const char *q_author = (const char *) sqlite3_column_text(statement, 4);
|
const char *q_author = (const char *) sqlite3_column_text(statement, 4);
|
||||||
|
long long rowid = sqlite3_column_int64(statement, 5);
|
||||||
|
|
||||||
if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize) == -1) {
|
if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize) == -1) {
|
||||||
WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid);
|
WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid);
|
||||||
} else {
|
} else {
|
||||||
@ -1024,6 +1030,7 @@ int rhizome_list_manifests(const char *service, const char *name,
|
|||||||
if (blob_version != q_version)
|
if (blob_version != q_version)
|
||||||
WARNF("MANIFESTS row id=%s version=%lld does not match manifest blob.version=%lld", q_manifestid, q_version, blob_version);
|
WARNF("MANIFESTS row id=%s version=%lld does not match manifest blob.version=%lld", q_manifestid, q_version, blob_version);
|
||||||
int match = 1;
|
int match = 1;
|
||||||
|
|
||||||
const char *blob_service = rhizome_manifest_get(m, "service", NULL, 0);
|
const char *blob_service = rhizome_manifest_get(m, "service", NULL, 0);
|
||||||
if (service[0] && !(blob_service && strcasecmp(service, blob_service) == 0))
|
if (service[0] && !(blob_service && strcasecmp(service, blob_service) == 0))
|
||||||
match = 0;
|
match = 0;
|
||||||
@ -1037,43 +1044,64 @@ int rhizome_list_manifests(const char *service, const char *name,
|
|||||||
if (!(blob_recipient && strcasecmp(recipient_sid, blob_recipient) == 0))
|
if (!(blob_recipient && strcasecmp(recipient_sid, blob_recipient) == 0))
|
||||||
match = 0;
|
match = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
const char *blob_name = rhizome_manifest_get(m, "name", NULL, 0);
|
const char *blob_name = rhizome_manifest_get(m, "name", NULL, 0);
|
||||||
long long blob_date = rhizome_manifest_get_ll(m, "date");
|
long long blob_date = rhizome_manifest_get_ll(m, "date");
|
||||||
const char *blob_filehash = rhizome_manifest_get(m, "filehash", NULL, 0);
|
const char *blob_filehash = rhizome_manifest_get(m, "filehash", NULL, 0);
|
||||||
long long blob_filesize = rhizome_manifest_get_ll(m, "filesize");
|
long long blob_filesize = rhizome_manifest_get_ll(m, "filesize");
|
||||||
int from_here = 0;
|
int from_here = 0;
|
||||||
|
unsigned char senderSid[SID_SIZE];
|
||||||
|
unsigned char recipientSid[SID_SIZE];
|
||||||
|
|
||||||
|
if (blob_sender)
|
||||||
|
stowSid(senderSid, 0, blob_sender);
|
||||||
|
if (blob_recipient)
|
||||||
|
stowSid(recipientSid, 0, blob_recipient);
|
||||||
|
|
||||||
if (q_author) {
|
if (q_author) {
|
||||||
if (config.debug.rhizome) DEBUGF("q_author=%s", alloca_str_toprint(q_author));
|
if (config.debug.rhizome) DEBUGF("q_author=%s", alloca_str_toprint(q_author));
|
||||||
unsigned char authorSid[SID_SIZE];
|
stowSid(m->author, 0, q_author);
|
||||||
stowSid(authorSid, 0, q_author);
|
|
||||||
int cn = 0, in = 0, kp = 0;
|
int cn = 0, in = 0, kp = 0;
|
||||||
from_here = keyring_find_sid(keyring, &cn, &in, &kp, authorSid);
|
from_here = keyring_find_sid(keyring, &cn, &in, &kp, m->author);
|
||||||
}
|
}
|
||||||
if (!from_here && blob_sender) {
|
if (!from_here && blob_sender) {
|
||||||
if (config.debug.rhizome) DEBUGF("blob_sender=%s", alloca_str_toprint(blob_sender));
|
if (config.debug.rhizome) DEBUGF("blob_sender=%s", alloca_str_toprint(blob_sender));
|
||||||
unsigned char senderSid[SID_SIZE];
|
|
||||||
stowSid(senderSid, 0, blob_sender);
|
|
||||||
int cn = 0, in = 0, kp = 0;
|
int cn = 0, in = 0, kp = 0;
|
||||||
from_here = keyring_find_sid(keyring, &cn, &in, &kp, senderSid);
|
from_here = keyring_find_sid(keyring, &cn, &in, &kp, senderSid);
|
||||||
}
|
}
|
||||||
if (config.debug.rhizome) DEBUGF("manifest payload size = %lld", blob_filesize);
|
if (config.debug.rhizome) DEBUGF("manifest payload size = %lld", blob_filesize);
|
||||||
cli_puts(blob_service ? blob_service : ""); cli_delim(":");
|
|
||||||
cli_puts(q_manifestid); cli_delim(":");
|
cli_put_long(rowid, ":");
|
||||||
cli_printf("%lld", blob_version); cli_delim(":");
|
cli_put_string(blob_service, ":");
|
||||||
cli_printf("%lld", blob_date); cli_delim(":");
|
cli_put_hexvalue(m->cryptoSignPublic, RHIZOME_MANIFEST_ID_BYTES, ":");
|
||||||
cli_printf("%lld", q_inserttime); cli_delim(":");
|
cli_put_long(blob_version, ":");
|
||||||
cli_puts(q_author ? q_author : ""); cli_delim(":");
|
cli_put_long(blob_date, ":");
|
||||||
cli_printf("%d", from_here); cli_delim(":");
|
cli_put_long(q_inserttime, ":");
|
||||||
cli_printf("%lld", blob_filesize); cli_delim(":");
|
cli_put_hexvalue(q_author?m->author:NULL, SID_SIZE, ":");
|
||||||
cli_puts(blob_filehash ? blob_filehash : ""); cli_delim(":");
|
cli_put_long(from_here, ":");
|
||||||
cli_puts(blob_sender ? blob_sender : ""); cli_delim(":");
|
cli_put_long(m->fileLength, ":");
|
||||||
cli_puts(blob_recipient ? blob_recipient : ""); cli_delim(":");
|
|
||||||
cli_puts(blob_name ? blob_name : ""); cli_delim("\n");
|
unsigned char filehash[SHA512_DIGEST_LENGTH];
|
||||||
|
if (m->fileLength)
|
||||||
|
fromhex(filehash, blob_filehash, SHA512_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
cli_put_hexvalue(m->fileLength?filehash:NULL, SHA512_DIGEST_LENGTH, ":");
|
||||||
|
|
||||||
|
cli_put_hexvalue(blob_sender?senderSid:NULL, SID_SIZE, ":");
|
||||||
|
cli_put_hexvalue(blob_recipient?recipientSid:NULL, SID_SIZE, ":");
|
||||||
|
cli_put_string(blob_name, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m) rhizome_manifest_free(m);
|
if (m) rhizome_manifest_free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret==0 && count_rows){
|
||||||
|
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW)
|
||||||
|
++rows;
|
||||||
|
}
|
||||||
|
cli_row_count(rows);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
sqlite3_finalize(statement);
|
sqlite3_finalize(statement);
|
||||||
RETURN(ret);
|
RETURN(ret);
|
||||||
|
6
serval.h
6
serval.h
@ -630,6 +630,12 @@ int cli_putchar(char c);
|
|||||||
int cli_puts(const char *str);
|
int cli_puts(const char *str);
|
||||||
int cli_printf(const char *fmt, ...);
|
int cli_printf(const char *fmt, ...);
|
||||||
int cli_delim(const char *opt);
|
int cli_delim(const char *opt);
|
||||||
|
void cli_columns(int columns, const char *names[]);
|
||||||
|
void cli_row_count(int rows);
|
||||||
|
void cli_field_name(const char *name, const char *delim);
|
||||||
|
void cli_put_long(int64_t value, const char *delim);
|
||||||
|
void cli_put_string(const char *value, const char *delim);
|
||||||
|
void cli_put_hexvalue(const unsigned char *value, int length, const char *delim);
|
||||||
|
|
||||||
int overlay_mdp_getmyaddr(int index,unsigned char *sid);
|
int overlay_mdp_getmyaddr(int index,unsigned char *sid);
|
||||||
int overlay_mdp_bind(unsigned char *localaddr,int port);
|
int overlay_mdp_bind(unsigned char *localaddr,int port);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user