/* * Serializes/deserializes a ypmaplist. */ static bool xdr_ypmaplist(XDR *xdrs, struct ypmaplist **lst) { bool_t more_elements; int freeing = (xdrs->x_op == XDR_FREE); struct ypmaplist **next; for (;;) { more_elements = (*lst != NULL); if (!xdr_bool(xdrs, &more_elements)) return (FALSE); if (!more_elements) return (TRUE); /* All done */ if (freeing) next = &((*lst)->ypml_next); if (!xdr_reference(xdrs, (caddr_t *)lst, (uint_t)sizeof (struct ypmaplist), (xdrproc_t)xdr_ypmaplist_wrap_string)) return (FALSE); lst = (freeing) ? next : &((*lst)->ypml_next); } /*NOTREACHED*/ }
/* * What is going on with linked lists? (!) * First recall the link list declaration from pmap_prot.h: * * struct pmaplist { * struct pmap pml_map; * struct pmaplist *pml_map; * }; * * Compare that declaration with a corresponding xdr declaration that * is (a) pointer-less, and (b) recursive: * * typedef union switch (bool_t) { * * case TRUE: struct { * struct pmap; * pmaplist_t foo; * }; * * case FALSE: struct {}; * } pmaplist_t; * * Notice that the xdr declaration has no nxt pointer while * the C declaration has no bool_t variable. The bool_t can be * interpreted as ``more data follows me''; if FALSE then nothing * follows this bool_t; if TRUE then the bool_t is followed by * an actual struct pmap, and then (recursively) by the * xdr union, pmaplist_t. * * This could be implemented via the xdr_union primitive, though this * would cause a one recursive call per element in the list. Rather than do * that we can ``unwind'' the recursion * into a while loop and do the union arms in-place. * * The head of the list is what the C programmer wishes to past around * the net, yet is the data that the pointer points to which is interesting; * this sounds like a job for xdr_reference! */ bool_t xdr_pmaplist( register XDR *xdrs, register struct pmaplist **rp) { /* * more_elements is pre-computed in case the direction is * XDR_ENCODE or XDR_FREE. more_elements is overwritten by * xdr_bool when the direction is XDR_DECODE. */ bool_t more_elements; register int freeing = (xdrs->x_op == XDR_FREE); register struct pmaplist **next; while (TRUE) { more_elements = (bool_t)(*rp != NULL); if (! xdr_bool(xdrs, &more_elements)) return (FALSE); if (! more_elements) return (TRUE); /* we are done */ /* * the unfortunate side effect of non-recursion is that in * the case of freeing we must remember the next object * before we free the current object ... */ if (freeing) next = &((*rp)->pml_next); if (! xdr_reference(xdrs, (caddr_t *)rp, (u_int)sizeof(struct pmaplist), xdr_pmap)) return (FALSE); rp = (freeing) ? next : &((*rp)->pml_next); } }
/* * XDR remote call results * written for XDR_DECODE direction only */ bool_t xdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp) { caddr_t port_ptr; port_ptr = (caddr_t)crp->port_ptr; if (xdr_reference(xdrs, &port_ptr, sizeof (u_long), xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { crp->port_ptr = (u_long *)port_ptr; return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); } return (FALSE); }
/* * xdr_pointer(): * * XDR a pointer to a possibly recursive data structure. This * differs with xdr_reference in that it can serialize/deserialiaze * trees correctly. * * What's sent is actually a union: * * union object_pointer switch (boolean b) { * case TRUE: object_data data; * case FALSE: void nothing; * } * * > objpp: Pointer to the pointer to the object. * > obj_size: size of the object. * > xdr_obj: routine to XDR an object. * */ bool_t xdr_pointer(XDR *xdrs, char **objpp, uint_t obj_size, const xdrproc_t xdr_obj) { bool_t more_data; more_data = (*objpp != NULL); if (!xdr_bool(xdrs, &more_data)) return (FALSE); if (!more_data) { *objpp = NULL; return (TRUE); } return (xdr_reference(xdrs, objpp, obj_size, xdr_obj)); }
/* * XDR remote call results * written for XDR_DECODE direction only */ bool_t xdr_rmtcallres( register XDR *xdrs, register struct rmtcallres *crp) { char* port_ptr; port_ptr = (char*)crp->port_ptr; if (xdr_reference(xdrs, &port_ptr, sizeof (unsigned long), (xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { crp->port_ptr = (unsigned long *)port_ptr; return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); } return (FALSE); }
bool_t xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp) { /* * more_elements is pre-computed in case the direction is * XDR_ENCODE or XDR_FREE. more_elements is overwritten by * xdr_bool when the direction is XDR_DECODE. */ bool_t more_elements; int freeing = (xdrs->x_op == XDR_FREE); rpcb_entry_list_ptr next; rpcb_entry_list_ptr next_copy; next = NULL; for (;;) { more_elements = (bool_t)(*rp != NULL); if (! xdr_bool(xdrs, &more_elements)) { return (FALSE); } if (! more_elements) { return (TRUE); /* we are done */ } /* * the unfortunate side effect of non-recursion is that in * the case of freeing we must remember the next object * before we free the current object ... */ if (freeing) next = (*rp)->rpcb_entry_next; if (! xdr_reference(xdrs, (caddr_t *)rp, (u_int)sizeof (rpcb_entry_list), (xdrproc_t)xdr_rpcb_entry)) { return (FALSE); } if (freeing && *rp) { next_copy = next; rp = &next_copy; /* * Note that in the subsequent iteration, next_copy * gets nulled out by the xdr_reference * but next itself survives. */ } else if (*rp) { rp = &((*rp)->rpcb_entry_next); } } /*NOTREACHED*/ }
/* * XDR remote call results * written for XDR_DECODE direction only */ bool_t xdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp) { caddr_t port_ptr; assert(xdrs != NULL); assert(crp != NULL); port_ptr = (caddr_t)(void *)crp->port_ptr; if (xdr_reference(xdrs, &port_ptr, sizeof (u_long), (xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { crp->port_ptr = (u_long *)(void *)port_ptr; return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); } return (FALSE); }
/* * xdr_pointer(): * * XDR a pointer to a possibly recursive data structure. This * differs with xdr_reference in that it can serialize/deserialize * trees correctly. * * What's sent is actually a union: * * union object_pointer switch (boolean b) { * case TRUE: object_data data; * case FALSE: void nothing; * } * * > objpp: Pointer to the pointer to the object. * > obj_size: size of the object. * > xdr_obj: routine to XDR an object. * */ bool_t xdr_pointer (XDR *xdrs, char **objpp, u_int obj_size, xdrproc_t xdr_obj) { bool_t more_data; more_data = (*objpp != NULL); if (!xdr_bool (xdrs, &more_data)) { return FALSE; } if (!more_data) { *objpp = NULL; return TRUE; } return xdr_reference (xdrs, objpp, obj_size, xdr_obj); }
bool_t xdr_pointer(register XDR *xdrs, char **objpp, u_int obj_size, XDRPROC_T_TYPE xdr_obj) { if (amuDebug(D_XDRTRACE)) plog(XLOG_DEBUG, "xdr_pointer:"); bool_t more_data; more_data = (*objpp != NULL); if (!xdr_bool(xdrs, &more_data)) { return (FALSE); } if (!more_data) { *objpp = NULL; return (TRUE); } return (xdr_reference(xdrs, objpp, obj_size, xdr_obj)); }