Example: ILE C for iSeries program to copy an iSeries database file to QNetWare File System

Note:
Read the Code disclaimer information for important legal information.

Suppose you have a customer file that you want to make available to all NetWare users, and that file contains fields that need conversion from packed decimal format. Example: Copying an iSeries™ database file shows you how to copy and convert that file with a series of integrated file system commands. You can also copy and convert the necessary field by using an ILE C for iSeries program. Before you use integrated file system APIs on the QNetWare file system, you should be aware of some considerations.

This sample program is not restricted to the QNetWare file system. You can use it to copy an iSeries database file into other file systems that the integrated file system supports. For example, you could change the hard-coded name of the stream file path to be the current directory: ./CUST.DAT. Before you run the program, use the CHGCURDIR command to change to the directory in which you want to create the stream file. However, you cannot copy this file into the QSYS.LIB file system because CUST.DAT is not a valid name for the QSYS.LIB file system.

The file in this example is in library DATALIB and has the name CUSTCDT. You can refer to these example displays:

The following ILE C for iSeries program, NWCUST, uses the external description of CUSTCDT. To convert the data from EBCDIC to ASCII, it uses the system APIs from the service program QTQICONV. This service program provides APIs to convert a buffer of characters from one coded character set identifier (CCSID) into another CCSID. To create the stream file CUST.DAT, it uses the open(), write() and close() integrated file system APIs.

Note:
Read the Code disclaimer information for important legal information.

To create the ILE C for iSeries module and bind it to the QTQICONV service program to create the NWCUST program, you would use these commands:

CRTCMOD MODULE(NWCUST) SRCFILE(QCSRC) OUTPUT(*PRINT) OPTION(*SHOWUSR)
CRTPGM PGM(NWCUST) BNDSRVPGM(QTQICONV)
  1. Open the stream file with the integrated file system open() API. Refer to  1  in Figure 2.

    This function opens the stream file for write only (O_WRONLY flag). If the file does not exist, it is created (O_CREAT flag). If it exists, it is truncated to 0 bytes length (O_TRUNC flag). This ensures that the stream file is replaced every time the program runs.

    S_IRWXU sets file authority bits.

    S_IRWXU
    Read, write, and search or execute for the file owner.

    The open() API requires authority bits to be set when the O_CREAT flag is set.

    S_IRWU is used to let you read and write to the file. NetWare file mode support has information about which attributes NetWare sets for owner permission.

  2. Build the buffer for the stream file record. Add a comma as the field delimiter  2 .

    The sprintf() function converts all packed decimal data fields from the database file into characters and formats them correctly with the format-string, for example: "D(6.2)".

  3. Convert stream file buffer from CCSID 37 to CCSID 850  3 .

    Function iconv() converts the stream file buffer to ASCII code page 850. Use the code page of your NetWare server. To determine the code page of the server, use the DSPMFSINF command. For example, to obtain the code page of directory SYSTEM in volume SYS of server NTWSERV1, enter:

      DSPMFSINF OBJ('/QNetWare/NTWSERV1.SVR/SYS/SYSTEM')
  4. Add ASCII carriage return and line feed as a record delimiter to the stream file buffer  4 . The character string "\15\12" represents hex x'0D0A' in octal form.
  5. Write the stream file buffer to the file using the Integrated File System write() API 5 . The library DATALIB, where the CUSTCDT database file is, has to be in the library list of the job from which you run the program.

Here is the source listing for the example program:

Figure 2. Example: ILE C for iSeries program using integrated file system APIs
                                                * * * * *   S O U R C E   * * * * *
 Line  STMT                                                                                                      SEQNBR   INCNO
             *...+.....1.....+.....2.....+.....3.....+.....4.....+.....5.....+.....6.....+.....7.....+.....8.....+.....9.....+.....
    1       |/* This program copies the AS/400 database file CUSTCDT to a          */                          |      1
    2       |/* stream file in the QNetWare file system. It uses Integrated File System APIs to       */       |      2
    3       |/* create and write the file. It converts the data from CCSID 37      */                          |      3
    4       |/* to ASCII codepage 850 using the QTQICONV system API.               */                          |      4
    5       |                                                                                                  |      5
    6       |#include <stdio.h>                                                                                |      6
    7       |#include <recio.h>                                                                                |      7
    8       |#include <stdlib.h>                                                                               |      8
    9       |#include <string.h>                                                                               |      9
   10       |#include <decimal.h>                                                                              |     10
   11       |#include <fcntl.h>                                                                                |     11
   12       |#include <unistd.h>                                                                               |     12
   13       |#include <qtqiconv.h>                                                                             |     13
   14       |                                                                                                  |     14
   15       |/* Include the external definition of the database file CUSTCDT.      */                          |     15
   16       |                                                                                                  |     16
   17       |#pragma mapinc("custmf","CUSTCDT(cusrec)","input","_P")                                           |     17
   18       |#include "custmf"                                                                                 |     18
    1       |/* ------------------------------------------------------------------------*/                     |     19     19
    2       |/* PHYSICAL FILE: DATALIB/CUSTCDT                                          */                     |     20     19
    3       |/* FILE CREATION DATE: 94/08/22                                            */                     |     21     19
    4       |/* RECORD FORMAT: CUSREC                                                   */                     |     22     19
    5       |/* FORMAT LEVEL IDENTIFIER: 39C301DBCB10B                                  */                     |     23     19
    6       |/* ------------------------------------------------------------------------*/                     |     24     19
    7       |typedef _Packed struct {                                                                          |     25     19
    8       |   decimal( 6, 0) CUSNUM;               /*  Customer number                                    */ |     26     19
    9       |                                        /*  PACKED SPECIFIED IN DDS                            */ |     27     19
   10       |   char LSTNAM[8];                      /*  Last name                                          */ |     28     19
   11       |   char INIT[3];                        /*  First/middle initial                               */ |     29     19
   12       |   char STREET[13];                     /*  Street address                                     */ |     30     19
   13       |   char CITY[6];                        /*  City                                               */ |     31     19
   14       |   char STATE[2];                       /*  State abbreviation                                 */ |     32     19
   15       |   decimal( 5, 0) ZIPCOD;               /*  Zip code                                           */ |     33     19
   16       |                                        /*  PACKED SPECIFIED IN DDS                            */ |     34     19
   17       |   decimal( 4, 0) CDTLMT;               /*  Credit limit                                       */ |     35     19
   18       |                                        /*  PACKED SPECIFIED IN DDS                            */ |     36     19
   19       |   decimal( 1, 0) CHGCOD;               /*  Charge code                                        */ |     37     19
   20       |                                        /*  PACKED SPECIFIED IN DDS                            */ |     38     19
   21       |   decimal( 6, 2) BALDUE;               /*  Balance due                                        */ |     39     19
   22       |                                        /*  PACKED SPECIFIED IN DDS                            */ |     40     19
   23       |   decimal( 6, 2) CDTDUE;               /*  Credit due                                         */ |     41     19
   24       |                                        /*  PACKED SPECIFIED IN DDS                            */ |     42     19
   25       |}DATALIB_CUSTCDT_CUSREC_i_t;                                                                      |     43     19
   26       |                                                                                                  |     44     19
   19       |#define _RCDLEN 100                                                                               |     45
   20       |                                                                                                  |     46
   21       |int main(void)                                                                                    |     47
   22       |{                                                                                                 |     48
   23       | /* Declare rcd, dta of data structure type DATALIB_CUSTCDT_CUSREC_i_t. */                        |     49
   24       | /* The data structure type was defined from the DDS specified.         */                        |     50
   25       |                                                                                                  |     51
   26       | DATALIB_CUSTCDT_CUSREC_i_t rcd, *dta = &rcd;                                                     |     52
   27       | _RFILE       *in;                                                                                |     53
   28       | _RIOFB_T     *fb;                                                                                |     54
   29       | char         dbrcd[_RCDLEN];                                                                     |     55
   30       | char         stmrcd[_RCDLEN];                                                                    |     56
   31       | char         *dbfile   = "CUSTCDT";                                                              |     57
   32       | char         *stmfile  = "QNetWare/SERVER.SVR/VOLUME/DATA/CUST.DAT";                             |     58
   33       | int          fildes, stmlen;                                                                     |     59
   34       |                                                                                                  |     60
   35       | /* Declare necessary variables for code conversion CCSID 37 to 850. */                           |     61
   36       |                                                                                                  |     62
   37       | char         fromcode[32] = "IBMCCSID000370000000";                                              |     63
   38       | char         tocode[32]   = "IBMCCSID00850";                                                     |     64
   39       | char         *ibuf, *obuf;                                                                       |     65
   40       | iconv_t      cd;                                                                                 |     66
   41       | size_t       ilen, olen;                                                                         |     67
   42       |                                                                                                  |     68
   43       |  /* Open and create the stream file using the open() Integrated File System API.        */       |     69
   44       |                                                                                                  |     70
   45     1 |  fildes = open( stmfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU );                             1      |     71
   46     2 |  if (fildes == -1)                                                                               |     72
   47       |  {                                                                                               |     73
   48     3 |      printf ( "Open to stream file %s failed\n", stmfile );                                      |     74
   49     4 |      exit ( 1 );                                                                                 |     75
   50       |  }                                                                                               |     76
   51       |  else                                                                                            |     77
   52       |  {                                                                                               |     78
   53       |      /* Open the database file for processing in arrival sequence.    */                         |     79
   54       |                                                                                                  |     80
   55     5 |      if (( in = _Ropen( dbfile, "rr, arrseq=Y" )) == NULL )                                      |     81
   56       |      {                                                                                           |     82
   57     6 |          printf ( "Open to database file %s failed\n", dbfile );                                 |     83
   58     7 |          exit ( 1 );                                                                             |     84
   59       |      }                                                                                           |     85
   60       |      else                                                                                        |     86
   61       |      {                                                                                           |     87
   62       |        /* Open a code conversion descriptor for CCSID 37 to 850       */                         |     88
   63       |        /* conversion.                                                 */                         |     89
   64       |                                                                                                  |     90
   65     8 |          cd = iconv_open( tocode, fromcode );                                                    |     91
   66       |                                                                                                  |     92
   67     9 |          fb = _Rreadn( in, dta, in->buf_length, __DFT );                                         |     93
   68    10 |          while ( fb->num_bytes != EOF )                                                          |     94
   69       |          {                                                                                       |     95
   70       |           /* Create the buffer for the stream file. Each field will be   */                      |     96
   71       |           /* separated by a comma.                                       */                      |     97
   72       |                                                                                                  |     98
   73    11 |              ilen  = sprintf( dbrcd,      "%D(6,0),", rcd.CUSNUM );                      2       |     99
   74    12 |              ilen += sprintf( dbrcd+ilen, "%8.8s,",   rcd.LSTNAM );                              |    100
   75    13 |              ilen += sprintf( dbrcd+ilen, "%3.3s,",   rcd.INIT   );                              |    101
   76    14 |              ilen += sprintf( dbrcd+ilen, "%13.13s,", rcd.STREET );                              |    102
   77    15 |              ilen += sprintf( dbrcd+ilen, "%6.6s,",   rcd.CITY   );                              |    103
   78    16 |              ilen += sprintf( dbrcd+ilen, "%2.2s,",   rcd.STATE  );                              |    104
   79    17 |              ilen += sprintf( dbrcd+ilen, "%D(5,0),", rcd.ZIPCOD );                              |    105
   80    18 |              ilen += sprintf( dbrcd+ilen, "%D(4,0),", rcd.CDTLMT );                              |    106
   81    19 |              ilen += sprintf( dbrcd+ilen, "%D(1,0),", rcd.CHGCOD );                              |    107
   82    20 |              ilen += sprintf( dbrcd+ilen, "%D(6,2),", rcd.BALDUE );                              |    108
   83    21 |              ilen += sprintf( dbrcd+ilen, "%D(6,2)",  rcd.CDTDUE );                              |    109
   84       |                                                                                                  |    110
   85       |        /* Set pointers for CCSID 37 to CCSID 850 conversion.            */                       |    111
   86       |        /* Use the iconv() function to convert the data.                 */                       |    112
   87       |                                                                                                  |    113
   88    22 |              stmlen = olen = ilen;                                                               |    114
   89    23 |              ibuf = &dbrcd[0];                                                                   |    115
   90    24 |              obuf = &stmrcd[0];                                                                  |    116
   91    25 |              iconv( cd, &ibuf, &ilen, &obuf, &olen );                                    3       |    117
   92       |                                                                                                  |    118
   93       |         /* Add ASCII carriage return and line feed.                      */                      |    119
   94       |                                                                                                  |    120
   95    26 |              stmlen += sprintf( stmrcd+stmlen, "\15\12" );                               4       |    121
   96       |                                                                                                  |    122
   97       |         /* Write the buffer to the stream file using the Integrated File System write() API.*/   |    123
   98       |                                                                                                  |    124
   99    27 |              if (( write( fildes, stmrcd, stmlen )) == -1 )                          5           |    125
  100       |              {                                                                                   |    126
  101    28 |                  printf ( "Write to stream file %s failed\n", stmfile );                         |    127
  102    29 |                  exit ( 1 );                                                                     |    128
  103    30 |              };                                                                                  |    129
  104    31 |              fb = _Rreadn( in, dta, in->buf_length, __DFT );                                     |    130
  105    32 |          };                                                                                      |    131
  106    33 |          iconv_close( cd );    /* Close data conversion descriptor. */                           |    132
  107    34 |          _Rclose( in );        /* Close the database file.          */                           |    133
  108    35 |      };                                                                                          |    134
  109    36 |     close( fildes );            /* Close the streamfile.            */                           |    135
  110    37 |  };                                                                                              |    136
  111       |}                                                                                                 |    137
                                         * * * * *   E N D   O F   S O U R C E   * * * * *

Figure 3 shows the contents of the stream file CUST.DAT after the NWCUST program has run and created it.

Figure 3. Content of CUST.DAT from a for DOS or OS/2 TYPE command
[C:\]type \\J:cust.dat
938472,Henning ,G K,4859 Elm Ave ,Dallas,TX,75217,5000,3,37.00,0.00
839283,Jones   ,B D,21B NW 135 St,Clay  ,NY,13041,400,1,100.00,0.00
392859,Vine    ,S S,PO Box 79    ,Broton,VT,5046,700,1,439.00,0.00
938485,Johnson ,J A,3 Alpine Way ,Helen ,GA,30545,9999,2,3987.50,33.50
397267,Tyron   ,W E,13 Myrtle Dr ,Hector,NY,14841,1000,1,0.00,0.00
389572,Stevens ,K L,208 Snow Pass,Denver,CO,80226,400,1,58.75,1.50
846283,Alison  ,J S,787 Lake Dr  ,Isle  ,MN,56342,5000,3,10.00,0.00
475938,Doe     ,J W,59 Archer Rd ,Sutter,CA,95685,700,2,250.00,100.00
693829,Thomas  ,A N,3 Dove Circle,Casper,WY,82609,9999,2,0.00,0.00
593029,Williams,E D,485 SE 2 Ave ,Dallas,TX,75218,200,1,25.00,0.00
192837,Lee     ,F L,5963 Oak St  ,Hector,NY,14841,700,2,489.50,0.50
583990,Abraham ,M T,392 Mill St  ,Isle  ,MN,56342,9999,3,500.00,0.00
 
[C:\]

In this example, the J: drive was mapped to SERVER:VOLUME\DATA using the NetWare client.

Because the fields in CUST.DAT are separated by a comma, it is very easy to incorporate the file into a spreadsheet application.