AutoXDR - NFSv4 Example Client code

Main
AutoGen
Pages

Home
Announce
FAQ
docs
XML Defs
testimonials
downloads

Automated
Options

AutoOpts
Comparison
Man example
Redistribute
Licensing
local use
using getopt

GCC's
Fixincludes

fixincludes

Automated
FSM

description
example
usagefsm

Addons
addon

Project GNU
Home Page

Automated
XDR

xdr project
  definitions
  XDR

  client
  clt. head
  server
  srv. head

  enums

  debug
  test code

i

These are the client side procedures that are not generated by rpcgen. These are the queued procedure calls that will be processed when their associated carrier procedure's send procedure is called, several bookkeeping routines, plus the init and send routines for each carrier procedure.

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

/*
 *  DO NOT EDIT THIS FILE   (nfsv4-client.c)
 *  
 *  It has been AutoGen-ed  Saturday August 12, 2006 at 11:32:10 AM 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"

/*
 *  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 );
}


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.
   */
  p_res = nfs4_compound_4( &(pC->args), clnt );
  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;
}

top  Viewable With Any Browser  Valid XHTML 1.0!


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

AutoXDR copyright (c) 2000-2001 Bruce Korb, all rights reserved.
Return to GNU's home page.

Please send FSF & GNU inquiries & questions to gnu@gnu.org. There are also other ways to contact the FSF.

Please send comments on these web pages to webmasters@www.gnu.org, send other questions to gnu@gnu.org.

This article, Copyright © 2000-2002 by Bruce Korb

Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. Last modified: Sun Oct 1 12:59:24 PDT 2006