diff --git a/include/nwdbm.h b/include/nwdbm.h index 5234ad2..dfe6e89 100644 --- a/include/nwdbm.h +++ b/include/nwdbm.h @@ -206,6 +206,11 @@ extern int nw_delete_obj_from_set(int object_type, int member_type, uint8 *member_name, int member_namlen); +extern int nw_list_obj_relations(int object_type, + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + uint32 last_seen, + uint32 *relations, int max_relations); extern int nw_write_prop_value(int object_type, diff --git a/src/nwbind.c b/src/nwbind.c index 109ef2d..5a5bce0 100644 --- a/src/nwbind.c +++ b/src/nwbind.c @@ -1466,8 +1466,33 @@ static void handle_fxx(int gelen, int func) break; case 0x4c : { /* List Relations of an Object */ - XDPRINTF((1, 0, "TODO:List Relations of an Object")); - completition=0xfb; + struct XDATA { + uint8 count[2]; + uint8 relations[32*4]; + } *xdata = (struct XDATA*) responsedata; + uint8 *p = rdata; + uint32 last_seen = GET_BE32(p); + int object_type = GET_BE16(p+4); + int object_namlen = (int)*(p+6); + uint8 *object_name = p+7; + int prop_namlen = (int)*(p+7+object_namlen); + uint8 *prop_name = p+8+object_namlen; + uint32 relations[32]; + int result = nw_list_obj_relations(object_type, + object_name, object_namlen, + prop_name, prop_namlen, + last_seen, relations, 32); + if (result > -1) { + int k; + uint8 *rp = xdata->relations; + U16_TO_BE16((uint16)result, xdata->count); + for (k=0; k < result; k++) { + U32_TO_BE32(relations[k], rp); + rp += 4; + } + data_len = 2 + (result * 4); + XDPRINTF((2, 0, "List Relations of an Object count=%d", result)); + } else completition = (uint8)-result; } break; case 0x64 : { /* Create Queue, prehandled by nwconn */ diff --git a/src/nwdbm.c b/src/nwdbm.c index 01c2f53..50844bd 100644 --- a/src/nwdbm.c +++ b/src/nwdbm.c @@ -999,6 +999,109 @@ int nw_delete_obj_from_set(int object_type, } +static void copy_bindery_packet_name(uint8 *dst, int dst_size, + uint8 *src, int src_len) +{ + int len = min(src_len, dst_size - 1); + if (len > 0) memcpy(dst, src, len); + dst[len] = '\0'; +} + +static int bindery_packet_name_has_wildcards(uint8 *name, int namlen) +{ + while (namlen-- > 0) { + if (*name == '*' || *name == '?') return(1); + ++name; + } + return(0); +} + +static int prop_list_members(uint32 obj_id, int prop_id, int prop_security, + uint32 last_seen, + uint32 *relations, int max_relations) +{ + NETVAL val; + int result; + int count = 0; + int collect = (last_seen == (uint32)0xffffffff); + + if (0 != (result=b_acc(obj_id, prop_security, 0x10))) return(result); + + if (!dbminit(FNVAL)){ + key.dsize = NETVAL_KEY_SIZE; + key.dptr = (char*)&val; + val.obj_id = obj_id; + val.prop_id = (uint8)prop_id; + val.segment = (uint8)0; + + while (val.segment++ < (uint8)255 && count < max_relations) { + data = fetch(key); + if (data.dptr != NULL){ + NETVAL *v = (NETVAL*)data.dptr; + uint8 *p = v->value; + int k = 0; + + while (k++ < 32 && count < max_relations) { + uint32 id = GET_BE32(p); + + if (id != 0) { + if (collect) { + relations[count++] = id; + } else if (id == last_seen) { + collect = 1; + } + } + p += 4; + } + } + } + result = count; + } else result = -0xff; + + dbmclose(); + return(result); +} + + +int nw_list_obj_relations(int object_type, + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + uint32 last_seen, + uint32 *relations, int max_relations) +{ + NETOBJ obj; + NETPROP prop; + int result=-0xff; + + memset(&obj, 0, sizeof(obj)); + memset(&prop, 0, sizeof(prop)); + + if (bindery_packet_name_has_wildcards(object_name, object_namlen)) + return(-0xf0); + + copy_bindery_packet_name(obj.name, sizeof(obj.name), + object_name, object_namlen); + copy_bindery_packet_name(prop.name, sizeof(prop.name), + prop_name, prop_namlen); + obj.type = (uint16)object_type; + + XDPRINTF((2,0, "nw_list_obj_relations obj=%s,0x%x, prop=%s, last=0x%x", + obj.name, object_type, prop.name, last_seen)); + + if ((result = find_obj_id(&obj)) == 0) { + result = find_first_prop_id(&prop, obj.id); + if (!result) { + if (!(prop.flags & P_FL_SET)) + result = -0xfb; + else + result = prop_list_members(obj.id, (int)prop.id, prop.security, + last_seen, relations, max_relations); + } + } + return(result); +} + + int nw_write_prop_value(int object_type, uint8 *object_name, int object_namlen, int segment_nr, int erase_segments,