Novell Home

Extended attributes using server-side APIs (NetWare)

From Developer Community

This program shows how to create and read extended attributes using GetEAInfo(), EnumerateEA(), OpenEA() and other server-side functions.

Sample Code

#include <errno.h>
#include <nwerrno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nit\nwextatt.h>

#define MAX_KEY_BUFFER_SIZE  256
#define DATA_BUFFER_BOUNDARY 128

/*
// ENUMERATE_BUFFER_SIZE must be:
//
// 1. Large enough to accomodate at least one T_enumerateEAnoKey sruct with
//    a key of the largest size,
//    sizeof( T_enumerateEAnoKey) + MAX_KEY_BUFFER_SIZE - 1
// 2. Be rounded to 128 byte boundary:
*/
#define ROUND_TO_DATA_BUFFER_BOUNDARY( x) \
   (((( x) + DATA_BUFFER_BOUNDARY - 1) / \
             DATA_BUFFER_BOUNDARY) * \
             DATA_BUFFER_BOUNDARY)

#define ENUMERATE_BUFFER_SIZE ROUND_TO_DATA_BUFFER_BOUNDARY( sizeof( T_enumerateEAnoKey) + MAX_KEY_BUFFER_SIZE - 1)

static void displayEAs( char* filename) {
   int           handle;
   int           ccode;
   unsigned long totalEAs;
   unsigned long totalDataSizeOfEAs;
   unsigned long totalKeySizeOfEAs;
   int           i;
   if (( handle = OpenEA( filename, 0)) == EFAILURE) {
      printf( "OpenEA failed, errno = %x (%s), NetWareErrno = %x\n",
              errno, strerror( errno), NetWareErrno);
      return;
   }
   if (( ccode = GetEAInfo( handle,
                            &totalEAs,
                            &totalDataSizeOfEAs,
                            &totalKeySizeOfEAs)) != 0) {
      printf( "GetEAInfo failed, ccode = %x, errno = %x (%s), NetWareErrno = %x\n",
              ccode, errno, strerror( errno), NetWareErrno);
      CloseEA( handle);
      return;
   }
   if ( totalEAs == 0) {
      printf( "%s does not have extended attributes\n", filename);
      CloseEA( handle);
      return;
   }
   for ( i = 0; i < totalEAs; ) {
      char          buffer[ ENUMERATE_BUFFER_SIZE];
      char*         cur_key_info = buffer;
      unsigned long dataSize;
      unsigned long EAsInReply;
      int           j;
      if (( ccode = EnumerateEA( handle,
                                 NULL,
                                 ( unsigned char*) buffer,
                                 ENUMERATE_BUFFER_SIZE,
                                 i,
                                 &dataSize,
                                 &EAsInReply)) != 0) {
         printf( "EnumerateEA failed, ccode = %x, errno = %x (%s), NetWareErrno = %x\n",
                 ccode, errno, strerror( errno), NetWareErrno);
         CloseEA( handle);
         return;
      }
      if ( EAsInReply == 0) {
         puts( "EAsInReply == 0 (?)");
         CloseEA( handle);
         return;
      }
      for ( j = 0; j < EAsInReply; ++i, ++j) {
         T_enumerateEAnoKey* info = ( T_enumerateEAnoKey*) cur_key_info;
         char                keyBuffer[ MAX_KEY_BUFFER_SIZE];
         char*               dataBuffer;
         unsigned long       dataBufferSize;
         unsigned long       accessFlags;
         sprintf( keyBuffer, "%.*s", info -> keyLength, info -> keyValue);
         keyBuffer[ info -> keyLength] = '\0';
         printf( "keyBuffer = %s", keyBuffer);
         dataBufferSize = info -> valueLength;
         if ( dataBufferSize % 128 != 0) {
            dataBufferSize += 128 - dataBufferSize % 128;
         }
         if (( dataBuffer = malloc( dataBufferSize)) == NULL) {
            printf( "malloc failed, errno = %x (%s), NetWareErrno = %x\n",
                    errno, strerror( errno), NetWareErrno);
            CloseEA( handle);
            return;
         }
         if ( ReadEA( handle, keyBuffer, dataBuffer,
                      dataBufferSize, &accessFlags) == EFAILURE) {
            printf( "ReadEA failed, errno = %x (%s), NetWareErrno = %x\n",
                    errno, strerror( errno), NetWareErrno);
            free( dataBuffer);
            CloseEA( handle);
            return;
         }
         printf( ", dataBuffer = %.*s\n", dataBufferSize, dataBuffer);
         free( dataBuffer);
         cur_key_info += sizeof( T_enumerateEAnoKey) + info -> keyLength - 1;
      }
   }
   CloseEA( handle);
}
static void createEAs( char* filename) {
   int  handle;
   char keyBuffer[  MAX_KEY_BUFFER_SIZE];
   char dataBuffer[ DATA_BUFFER_BOUNDARY];
   int  i;
   if (( handle = OpenEA( filename, 0)) == EFAILURE) {
      printf( "OpenEA failed, errno = %x (%s), NetWareErrno = %x\n",
              errno, strerror( errno), NetWareErrno);
      return;
   }
   for ( i = 0; i < 6; ++i) {
      sprintf( keyBuffer,  "EAKey%d",   i);
      sprintf( dataBuffer, "EAValue%d", i);
      if ( WriteEA( handle, keyBuffer, dataBuffer, DATA_BUFFER_BOUNDARY, 0) == EFAILURE) {
         printf( "WriteEA failed, errno = %x (%s), NetWareErrno = %x\n",
                 errno, strerror( errno), NetWareErrno);
         CloseEA( handle);
         return;
      }
   }
   CloseEA( handle);
}
int main( int argc, char* argv[]) {
   char* filename;
   char* mode;
   if ( argc != 3 ||
        strcmp( strupr( mode = argv[ 2]), "D") != 0 &&
        strcmp( mode, "C") != 0) {
      puts( "Syntax: CreDisEA <filename> <mode>\n"
            "where\n"
            "<filename> - filename to process\n"
            "<mode>     - C: Create, D: Display");
      return EXIT_FAILURE;
   }
   filename = strupr( argv[ 1]);
   if ( *mode == 'D') displayEAs( filename);
   else               createEAs(  filename);
   return EXIT_SUCCESS;
}

--Dmitry Mityugov

Novell® Making IT Work As One

© 2008 Novell, Inc. All Rights Reserved.