AutoXDR - NFSv4 Debug Library Code


This is a debug version substitution for the normal client code. It will directly call the server code so that you can debug the protocol in a single process.

AutoXDR will also produce template code for the client side main procedure (*-clmain.c) and the server side implementation procedures (*-svstub.c). They are not shown here, but they can be seen by downloading the AutoXDR tarball and generating the sources.

The following example is from NFSv4 with all but one queued call removed:

/*
 *  DO NOT EDIT THIS FILE   (nfsv4-debug.c)
 *  
 *  It has been AutoGen-ed  Saturday May 26, 2001 at 04:36:08 PM PDT
 *  From the definitions    nfsv4.def
 *  and the template file   autoxdr.tpl
 *
 *  This file has been generated by the AutoXDR AutoGen template suite.
 *
 *  These files are compatible with:
 *  RFC1831 - Remote Procedure Call Protocol Specification Version 2
 *  RFC1832 - External Data Representation Standard
 *  and are intended to be used as a layer on top of the ONC IDL
 *  in conjunction with RPCGEN.
 *
 */
#include <stdio.h>
#include <errno.h>

#include "nfsv4-svhdr.h"
#include "nfsv4-clhdr.h"


static int
call_server( int       proc_id,
             caddr_t   p_args,
             caddr_t   p_res )
{
  void* pr = NULL;

  switch (proc_id) {
  case NFS4_NULL:
    pr = nfs4_null_4_svc( (void*)p_args, (struct svc_req *)NULL );
    break;

  case NFS4_COMPOUND:
    pr = nfs4_compound_4_svc( (nfs4_compound_args*)p_args, (struct svc_req *)NULL );
    if (pr != NULL)
      memcpy( (void*)p_res, (void*)pr, sizeof( nfs4_compound_res ));
    break;

  default:
    return RPC_PROCUNAVAIL;
  }

  return (pr == NULL) ? RPC_FAILED : RPC_SUCCESS;
}

/*
 *  IF someone calls this with an invalid cookie, exit the program here
 */
static void
sequence_fail( const char* pz_which )
{
  static const char z_fail_fmt[] =
    "NFS Calling sequence error for %s\n";
  fprintf( stderr, z_fail_fmt, pz_which );
  exit( 1 );
}

void*
nfs4_null_4( void* argp, CLIENT* clnt )
{
  int status;
  static char res;

  status = call_server( NFS4_NULL, (caddr_t)argp, (caddr_t)&res );
  if (status != RPC_SUCCESS)
    return NULL;
  return &res;
}

typedef void (*tp_done)(void);
typedef struct {
    int32_t         magic;
    int32_t         alloc_ct;
    int32_t         used_ct;
    u_nfs4_compound_args*
                    p_data;
    void*           user_cookie;
    tp_done*        pap_done;
    nfs4_compound_args
                    args;
} t_nfs4_compound_cookie;

/*
 *  magic = version << 24  + proc-num << 20  +  program id
 */
#define NFS4_COMPOUND_MAGIC   0x401186A3

/*
 *  Free up the operation space.
 */
static void
free_nfs4_compound_cookie( t_nfs4_compound_cookie* pC )
{
  {
    int       ct    = pC->used_ct;
    tp_done*  p_cp  = pC->pap_done;
    u_nfs4_compound_args* p_arg = pC->p_data;
    while (--ct >= 0)
      {
        switch (p_arg->argop)
          {
            case NFS4_ACCESS4:
              {
                tp_nfs4_access4_done pc =
                    (tp_nfs4_access4_done)*p_cp;
                ACCESS4args* pa =
                    &(p_arg->u_nfs4_compound_args_u.op_access4);

                if (pc == NULL) break;
                (*pc)( pC->user_cookie, (nfs4_compound_res*)NULL,
                       NFS4_STATUS_OMITTED,
                       pa->requested,
                       0 );
                break;
              }
          }

        p_arg++;
        p_cp++;
      }
  }
  if (pC->p_data != NULL)
    free( (void*)pC->p_data );
  if (pC->pap_done != NULL)
    free( (void*)pC->pap_done );
  pC->magic = 0;
  free( (void*)pC );
}

/*
 *  Out of operation space.  Expand it.
 */
static int
expand_nfs4_compound_cookie(
    t_nfs4_compound_cookie* pC )
{
  void* p;
  pC->alloc_ct += 4;

  p = realloc( (void*)pC->p_data,
               pC->alloc_ct * sizeof( u_nfs4_compound_args ));
  if (p == NULL)
    {
      free_nfs4_compound_cookie( pC );
      return ENOMEM;
    }
  pC->p_data = (u_nfs4_compound_args*)p;

  p = realloc( (void*)pC->pap_done,
               pC->alloc_ct * sizeof( tp_done ));
  if (p == NULL)
    {
      free_nfs4_compound_cookie( pC );
      return ENOMEM;
    }
  pC->pap_done = (tp_done*)p;
  return 0;
}

/*
 *  INITIALIZE the state of the COMPOUND request
 */
int
init_nfs4_compound(
    t_nfs_cookie*    p_my_cookie,
    utf8string*      tag_in /* in */,
    void*            user_cookie )
{
  t_nfs4_compound_cookie* pC = (t_nfs4_compound_cookie*)malloc( sizeof( *pC ));

  /*
   *  allocate our cookie, the start of the array of operation arguments
   *  and an array of pointers to procedures that will be called when
   *  the results are ready.
   */
  if (pC == NULL)
    return ENOMEM;

  memset( (void*)pC, 0, sizeof( *pC ));
  pC->p_data   = (u_nfs4_compound_args*)malloc(
      4 * sizeof( u_nfs4_compound_args ));

  if (pC->p_data == NULL)
    {
      free( (void*)pC );
      return ENOMEM;
    }

  pC->pap_done = (tp_done*)malloc( 4 * sizeof(tp_done) );
  if (pC->pap_done == NULL)
    {
      free_nfs4_compound_cookie( pC );
      return ENOMEM;
    }

  /*
   *  Everything is allocated.  Initiaize our private data, plus
   *  the "extra" arguments for this combined op.
   */
  *p_my_cookie     = (t_nfs_cookie)pC;
  pC->magic        = NFS4_COMPOUND_MAGIC;
  pC->alloc_ct     = 4;
  pC->used_ct      = 0;
  pC->user_cookie  = user_cookie;
  pC->args.tag_in  = *tag_in;
  pC->args.minorversion = 0;
  return 0;
}


/*
 *  SEND the COMPOUND request
 *
 *  This routine finally sends the command buffer and invokes
 *  all the callback routines.
 */
int
send_nfs4_compound(
    t_nfs_cookie      my_cookie,
    CLIENT*           clnt )
{
  t_nfs4_compound_cookie* pC = (t_nfs4_compound_cookie*)my_cookie;
  nfs4_compound_res* p_res;

  if (pC->magic != NFS4_COMPOUND_MAGIC)
    sequence_fail( "send_nfs4_compound" );

  pC->args.argarray.argarray_val = pC->p_data;
  pC->args.argarray.argarray_len = pC->used_ct * sizeof( *(pC->p_data) );

  /*
   *  Send the request.  The result is a pointer to a result struct.
   *  Unless the send fails.  In that case, we get NULL back.
   */
  {
    static nfs4_compound_res res;
    memset( (void*)&res, 0, sizeof( res ));
    if (  call_server( NFS4_COMPOUND, (caddr_t)&(pC->args),
                       (caddr_t)&res ) 
       != RPC_SUCCESS )
      p_res = NULL;
    else
      p_res = &res;
  }
  if (p_res == NULL)
    {
      free_nfs4_compound_cookie( pC );
      return (errno>0) ? 0-errno : -1;
    }

  {
    u_nfs4_compound_res* pa_res =
      p_res->resarray.resarray_val;
    u_nfs4_compound_args* pa_arg = pC->p_data;
    tp_done* p_cp = pC->pap_done;

    int res_ct = p_res->resarray.resarray_len / sizeof( *pa_res );
    int req_ct = pC->used_ct;
    int res    = p_res->status;

    /*
     *  FOR each result AND for as long as we get OK (zero) back,
     *    DO  call the result callback procedure
     */
    while (--req_ct >= 0)
      {
        res_ct--;

        switch (pa_arg->argop)
          {
            case NFS4_ACCESS4:
              {
                tp_nfs4_access4_done pc =
                    (tp_nfs4_access4_done)*p_cp;
                ACCESS4args* pa =
                    &(pa_arg->u_nfs4_compound_args_u.op_access4);
                ACCESS4res*  pr =
                    &(pa_res->u_nfs4_compound_res_u.op_access4);

                if (pc == NULL) break;
                if (res_ct >= 0)
                  (*pc)( pC->user_cookie, p_res, p_res->status,
                         pa->requested,
                         pr );
                else
                  (*pc)( pC->user_cookie, NULL, p_res->status,
                         pa->requested,
                         0 );
                break;
              }
          }

        pa_arg++;
        p_cp++;
        pa_res++;
      }

    pC->used_ct = 0; /* prevent the calling of the callback procedures */
    free_nfs4_compound_cookie( pC );
    return res;
  }
}

/*
 *  Stash the data for each flavor of operation.  The "int" value
 *  returned is either ENOMEM or 0 (EOK).
 */
int
do_nfs4_access4(
    t_nfs_cookie     my_cookie,
    tp_nfs4_access4_done
                     p_done,
    uint32_t         requested /* in */ )
{
  t_nfs4_compound_cookie* pC = (t_nfs4_compound_cookie*)my_cookie;
  int idx;
  ACCESS4args* p_args;

  if (pC->magic != NFS4_COMPOUND_MAGIC)
    sequence_fail( "do_nfs4_access4" );

  idx = pC->used_ct;
  if (++(pC->used_ct) >= pC->alloc_ct)
    if (expand_nfs4_compound_cookie( pC ) != 0)
      return ENOMEM;

  pC->pap_done[ idx ] = (tp_done)p_done;
  pC->p_data[ idx ].argop = NFS4_ACCESS4;
  memset( (void*)&(pC->p_data[ idx ].u_nfs4_compound_args_u), 0,
          sizeof(  pC->p_data[ idx ].u_nfs4_compound_args_u ));
  p_args = &(pC->p_data[ idx ].u_nfs4_compound_args_u.op_access4);
  p_args->requested       = requested;
  return 0;
}


Viewable With Any Browser


AutoGen, AutoOpts, columns, getdefs, AutoFSM, AutoXDR and these web pages copyright (c) 1999, 2000, 2001 Bruce Korb, all rights reserved.

AutoXDR copyright (c) 2000 Bruce Korb, all rights reserved.