Midrange News for the IBM i Community

Posted by: Bob Cozzi
Rogue Programmer
Cozzi Productions, Inc.
has no ratings.
Published: 16 Jul 2013
Revised: 02 Aug 2013 - 1328 days ago
Last viewed on: 22 Mar 2017 (4773 views) 

Using IBM i? Need to create Excel, CSV, HTML, JSON, PDF, SPOOL reports? Learn more about the fastest and least expensive tool for the job: SQL iQuery.

Zip and UnZip at IBM i V7R1 Published by: Bob Cozzi on 16 Jul 2013 view comments


For several years I've been using the QSH (QShell) JAR (Java Archive) tool on IBM i to zip up IFS file and system objects. Anything from an HTML webpage on the IFS to a *SAVF in QGPL has been stuffed into a ZIP file.

In early 2012, IBM ported the ZLIB ZIP utilities to IBM i in the form of the QZIPUTIL *SRVPGM. The two exported subprocedure APIs are QzipZip and QzipUnzip. The names are case-sensitive. 

While these APIs are highly limited compared to other operating system implementations, they do provide a primative ZIP capability for both IFS files and regular objects.

Rather that go over the API parameters, I've built a CL wrapper that runs the QzipZIP tool. I will produce one for Unzip shortly and update this article. Be sure to FOLLOW this article to be notified of updates.

Below is the CTZIP (Cozzi Tools ZIP Utility) command source. It allows you to create a ZIP file that contains a sysetm object (such as a program, file, user space, just about anything) or a file or folder on the IFS. The nature of these APIs is such that you may only add one item at a time to the ZIP file. To add multiple items, you need to run the command once for eah item you wish you add. Note: All Zip files are created on the IFS.

There are couple of parameters that I should highlight.

VERBOSE: This parameter is used when you want the API to report progress message to the joblog. The API itself calls for a *VERBOSE or *NONE option, but I simplified it on the command, to VERBOSE( *YES or *NO ).

SUBDIR: This parameter is when an IFS folder is being zipped up. If you want the subdirectories and their contents to be included in the resulting ZIP file, then specify SUBDIR(*YES). Again, the API uses an usual set of options *ALL and *NONE, which I've simplified via the command to SUBDIR(*YES or *NO).


Unfortunately, IBM is now outsourcing its IBM i development to all over the world. While the developers do seem to be very talented, I have noticed that the 35 years of IBM i knowledge from Rochester, MN USA is NOT being well transferred to this new generation of developers. Lots of omissions and implementation errors are appearing in almost everything new feature coming onto this system. QZIPUTIL is no exception.

In order to compile an RPG program that leverages the APIs in this service program, it must first be added to either a user-supplised Binding Directory or to the IBM system API binding directory. It should have been included in the IBM System API binding directory but it is not. So as a one-time thing, run the following CL command, so that you can compile programs that call QzipZip and QzipUnzip APIs:


Hopefully IBM will see this article and add it in a tech refresh or CUMPTF package.

Once compiled, type in CTZIP and press F4 to prompt it. If you want to ZIP up something from the IFS, specify OBJ(*STMF) and the STMF parameter shall appear in the prompter (when you press Enter). Otherwise, type in the name of an IBM i object.

CTZIP can archive any IFS file or IBM i user objects such as Files, User Spaces, Save Files (a form of *FILE) and maybe a few others--nothing is documented so it is trial-and-error for this API.


Then look in your HOME directory on the IFS for the zip file you just created. To add to it, just run the command again with another object. If you have trouble, specify VERBOSE(*YES) when running it to see if it gives you any feedback.

CTZIP Command Definition Source

Cut/paste the folloiwng code into a source member named CTZIP. The name CTZIP means "COZZI TOOLS Zip Utility"

 CTZIP:      CMD        PROMPT('COZZI - ZIP Utility')                                               
             PARM       KWD(OBJ) TYPE(QUAL1) SNGVAL((*STMF)) MIN(1) +                               
                          PROMPT('Object to add to ZIP file')                                       
 QUAL1:      QUAL       TYPE(*NAME) LEN(10) EXPR(*YES)                                              
             QUAL       TYPE(*NAME) LEN(10) DFT(*CURLIB) +                                          
                          SPCVAL((*CURLIB)) EXPR(*YES) +                                            
                          PROMPT('Object library')                                                  
             PARM       KWD(OBJTYPE) TYPE(*CHAR) LEN(10) DFT(*FILE) +                               
                          SPCVAL((*FILE) (*SAVF *FILE) (*USRSPC)) +                                 
                          PROMPT('Object type')                                                     
 STMF:       PARM       KWD(STMF) TYPE(*PNAME) LEN(640) DFT(*NONE) +                                
                          SPCVAL((*NONE '')) MIN(0) EXPR(*YES) +                                    
                          VARY(*YES) PMTCTL(USESTMF) PROMPT('IFS File')                             
             PARM       KWD(SUBDIR) TYPE(*CHAR) RSTD(*YES) DFT(*YES) +                              
                          SPCVAL((*YES *ALL) (*NO *NONE)) +                                         
                          EXPR(*YES) PROMPT('Include subdirectories')                               
             PARM       KWD(ZIPLOC) TYPE(*PNAME) LEN(5000) DFT(*HOME) +                             
                          SPCVAL((*HOME)) EXPR(*YES) VARY(*YES) +                                   
                          INLPMTLEN(32) PROMPT('Zip file location')                                 
             PARM       KWD(ZIP) TYPE(*PNAME) LEN(5000) DFT(*OBJ) +                                 
                          SPCVAL((*OBJ) (*OBJLIB)) EXPR(*YES) +                                     
                          VARY(*YES) INLPMTLEN(32) PROMPT('Zip file +                               
             PARM       KWD(VERBOSE) TYPE(*CHAR) RSTD(*YES) DFT(*NO) +                              
                          SPCVAL((*YES *VERBOSE) (*NO *NONE)) +                                     
                          EXPR(*YES) PROMPT('Verbose messages')                                     
             PARM       KWD(COMMENTS) TYPE(*CHAR) LEN(512) +                                        
                          DFT(*NONE) SPCVAL((*NONE '')) EXPR(*YES) +                                
                          VARY(*YES) PROMPT('Embedded Comments')                                    
 USESTMF:    PMTCTL     CTL(OBJ) COND((*EQ *STMF) (*EQ *NONE)) +                                    
                          NBRTRUE(*GE 1)

CTZIP RPG IV Source Code

I managed to avoid using any of my improved COZZI TOOLS /COPY members to build this utility. So it is a stand-alone module. Just compile it and it'll work. If you do NOT have the proper PTFs on your IBM i V7R1 build, then you won't have QZIPUTIL in QSYSINC and this program will not compile. Assuming you ran the ADDBNDDIRE command above, then it should compile just fine.

Cut/paste the following RPG IV code into a source member on your system and compile it.


      /copy qsysinc/qrpglesrc,qziputil

      /copy qsysinc/qrpglesrc,qusrobjd
      /copy qsysinc/qrpglesrc,qusec

     D PSDS           SDS                  Qualified
     D  runlib                       10A   overlay(PSDS:081)
     D  JobName                      10A   Overlay(PSDS:244)
     D  usrprf                       10A   Overlay(PSDS:254)
     D  JobNbr                        6A   Overlay(PSDS:264)

     D QusROBJD2       PR                  extPgm('QUSROBJD')
     D  rtnData                   65535A   OPTIONS(*VARSIZE)
     D  nRtnDataLen                  10I 0 Const
     D  Format                        8A   Const
     D  QualObj                      20A   Const
     D  ObjType                      10A   Const
     D  api_error                          LikeDS(QUSEC)
     D                                     OPTIONS(*VARSIZE:*NOPASS)

     D qualObj_T       DS                  Qualified
     D  name                         10A
     D  lib                          10A

     D qualObjType_T   DS                  Qualified
     D  name                         10A
     D  lib                          10A
     D  type                         10A

     D entryPList      PR                  extPgm('CTZIP')
     D  obj                                Const LikeDS(qualObj_T)
     D  objtype                      10A   Const
     D  ifsFile                    5000A   Const Varying
     D  subdir                       10A   Const
     D  zipDir                     5000A   Const Varying
     D  zipFile                    5000A   Const Varying
     D  verbose                      10A   Const
     D  comments                    512A   Const Varying

     D zipPath         DS                  LikeDS(qlg_Path_Name_T) Inz
     D objPath         DS                  LikeDS(qlg_Path_Name_T) Inz
     D ifsPath         S           5000A   Varying
     D suffix          S              4A
     D objDesc         DS                  LikeDS(QUSD0100) Inz
     D zipOptions      DS                  LikeDS( QZIP_zip_options_ZIP00100_T )
     D                                     Inz
     D apiError        DS                  LikeDS(QUSEC) Inz(*LIKEDS)
     D object          DS                  LikeDS(qualObjType_T)

     D entryPList      PI
     D  obj                                Const LikeDS(qualObj_T)
     D  objtype                      10A   Const
     D  ifsFile                    5000A   Const Varying
     D  subdir                       10A   Const
     D  zipDir                     5000A   Const Varying
     D  zipFile                    5000A   Const Varying
     D  verbose                      10A   Const
     D  comments                    512A   Const Varying

     C                   MOVE      *ON           *INLR
           if (zipDir = '*HOME');
             ifsPath = '/home/' + %trimR(psds.usrprf);
             ifsPath = %TrimR(zipDir);

           if (zipFile = '*OBJ');
             ifsPath += '/' + %trimR(obj.name) + '.ZIP';
           elseif (zipFile = '*OBJLIB');
             ifsPath += '/' + %trimR(obj.Lib) + '/' + %trimR(obj.Name) +
              ifsPath += '/' + %trimR(zipFile);
           EVALR suffix = %TrimR(ifsPath);
           if (suffix <> '.ZIP' and suffix <> '.zip');
              ifsPath += '.ZIP';

           zipPath.CCSID = 0;
           zipPath.Country_ID = *ALLX'00';
           zipPath.Language_ID = *ALLX'00';
           zipPath.reserved = *ALLX'00';
           zipPath.reserved2 = *ALLX'00';
           zipPath.path_Type = 0;
           zipPath.path_Name_Delimiter = '/';
           zipPath.path_Length = %len(ifsPath);
           zipPath.path_Name = ifsPath;
           apiError = *ALLX'00';

           if ((obj.name = '*STMF') or (obj.name = '*NONE') or
               (obj.name = ''));
              ifsPath = %trimR(ifsFile);
             QusROBJD2(objDesc : %size(objDesc) :'OBJD0100':
                        obj : objType : apiError );
             if (objDesc.qusbrtn06 > 0);  // Got something?
                object.name = objDesc.qusobjn00;
                object.lib  = objDesc.qusrl01;
                object.type = %subst(objDesc.QUSOBJT00 : 2);

             ifsPath = '/qsys.lib/' + %trimR(object.lib) + '.lib' + '/' +
                         %trimR(object.name) + '.' + %trimR(object.Type);
           objPath.CCSID = 0;
           objPath.Country_ID = *ALLX'00';
           objPath.Language_ID = *ALLX'00';
           objPath.reserved = *ALLX'00';
           objPath.reserved2 = *ALLX'00';
           objPath.path_Type = 0;
           objPath.path_Name_Delimiter = '/';
           objPath.path_Length = %len(ifsPath);
           objPath.path_Name = ifsPath;

           zipOptions.verbose_Option = verbose;
           zipOptions.subtree_Option = subdir;
           if (%Len(comments) > 0 and comments <> '');
              zipOptions.comment = comments;
              zipOptions.comment_Length = %len(comments);

           apiError = *ALLX'00';
           qzipzip( objPath : zipPath : 'ZIP00100' : zipOptions : apiError );


Return to midrangenews.com home page.
Sort Ascend | Descend