root/usr/src/lib/librpcsvc/common/mountlist_xdr.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#include <stdio.h>                              /* for fprintf() */
#include <stdlib.h>                             /* for malloc() */
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpcsvc/mount.h>


/*
 * XDR routines to handle mountlist structure
 *
 * These are iterative versions to avoid the stack-blowing problems of
 * the recursive routines generated by rpcgen.
 *
 * XXXX These should be removed when rpcgen is fixed to produce better
 * code in these circumstances.
 */


bool_t
xdr_mountlist(xdrs, objp)
        register XDR *xdrs;
        mountlist *objp;
{
        bool_t more_data;

        switch (xdrs->x_op) {

        case XDR_FREE: {
                mountbody *mb, *tmp;

                tmp = *objp;

                while (tmp != NULL) {
                        mb = tmp;
                        tmp = mb->ml_next;
                        if (!xdr_name(xdrs, &mb->ml_hostname))
                                return (FALSE);
                        if (!xdr_dirpath(xdrs, &mb->ml_directory))
                                return (FALSE);
                        free(mb);
                }

                break;
        }

        case XDR_DECODE: {
                mountbody *mb;
                mountbody *mb_prev = NULL;

                for (;;) {
                        if (!xdr_bool(xdrs, &more_data))
                                return (FALSE);

                        if (!more_data)
                                break;

                        mb = (mountbody *)malloc(sizeof (struct mountbody));
                        if (mb == NULL) {
                                fprintf(stderr,
                                    "xdr_mountlist: out of memory\n");
                                return (FALSE);
                        }
                        mb->ml_hostname = NULL;
                        mb->ml_directory = NULL;
                        mb->ml_next = NULL;

                        if (mb_prev == NULL) {
                                mb_prev = mb;
                                *objp = mb;
                        }

                        if (!xdr_name(xdrs, &mb->ml_hostname))
                                return (FALSE);
                        if (!xdr_dirpath(xdrs, &mb->ml_directory))
                                return (FALSE);

                        if (mb_prev != mb) {
                                mb_prev->ml_next = mb;
                                mb_prev = mb;
                        }
                }
                break;
        }

        case XDR_ENCODE: {
                mountbody *mb;

                mb = *objp;

                for (;;) {
                        more_data = mb != NULL;

                        if (!xdr_bool(xdrs, &more_data))
                                return (FALSE);

                        if (!more_data)
                                break;

                        if (!xdr_name(xdrs, &mb->ml_hostname))
                                return (FALSE);
                        if (!xdr_dirpath(xdrs, &mb->ml_directory))
                                return (FALSE);

                        mb = mb->ml_next;
                }
                break;
        }

        default:
                break;
        }

        return (TRUE);
}


/*
 * xdr_mountbody() is included here simply for backward compatibility. It is
 * no longer used by xdr_mountlist(), nor by any other SunOS routine as of
 * now.
 *
 * This is simply a copy of the rpcgen generated routine.
 */
bool_t
xdr_mountbody(xdrs, objp)
        register XDR *xdrs;
        mountbody *objp;
{
        if (!xdr_name(xdrs, &objp->ml_hostname))
                return (FALSE);
        if (!xdr_dirpath(xdrs, &objp->ml_directory))
                return (FALSE);
        if (!xdr_mountlist(xdrs, &objp->ml_next))
                return (FALSE);
        return (TRUE);
}