685 pts.
 Retrieving the name of a file from object links
We are receiving a Daily file containing Chassis information via FTP at a scheduled time in the early morning. I have written a process to automatically retrieve this file, CPYFRMIMPF to my Physical File, then process the data into our Chassis Master. Originally, I was told it would be a specific and constant name so I could retrieve it, copy it then delete it. The problem is, I am now told that the name isn't always going to be the same. They are still figuring out how to do that. The file is coming over as "daily_file_201332074926.csv". I can account for the date in my program and modify the name of the file I'm retrieving, but I don't see how I can get the exact time for the filename. My Question is this: Is there a way for me to somehow retrieve the name of that file from the directory in the object links within a CLLE program?

Software/Hardware used:
V7R1
ASKED: March 20, 2013  11:55 AM
UPDATED: March 20, 2013  12:25 PM
  Help
 Approved Answer - Chosen by Eric Witham (Question Asker)

Interesting. I guess it just seemed illogical to me to have to ftp the system you're already on. I dunno haha. But i did find a solution at the following url:http://www.iprodeveloper.com/forums/aft/79181The solution was done by a Developer named Scott Klement. I modified it for what I needed.Basically the CLLE handles the QSHELL command to retrieve the full path into the record of the file declared. You can see i'm substringing the filename because there could be 3 variations of the name.Anyway, here's the code:             PGM                                                                                                                                             DCL        VAR(&FILENAME) TYPE(*CHAR) LEN(30)                           DCL        VAR(&FILE_EXT) TYPE(*CHAR) LEN(04) VALUE('.csv')             DCLF       FILE(EWITHAM/IFSDCLI00)                                                                                                              OVRDBF     FILE(STDOUT) TOFILE(DIROUTPUT)                               QSH        CMD('ls /depotsystems/chassis/dcli*')                                                                                    #READ:      RCVF                                                                    MONMSG     MSGID(CPF0864) EXEC(GOTO CMDLBL(#EOF))                                                                                               SELECT                                                                  WHEN       COND(%SST(&FULLPATH 46 4) *EQ &FILE_EXT)                     CHGVAR     VAR(&FILENAME) VALUE(%SST(&FULLPATH 23 27))                  WHEN       COND(%SST(&FULLPATH 47 4) *EQ &FILE_EXT)                     CHGVAR     VAR(&FILENAME) VALUE(%SST(&FULLPATH 23 28))                  WHEN       COND(%SST(&FULLPATH 48 4) *EQ &FILE_EXT)                     CHGVAR     VAR(&FILENAME) VALUE(%SST(&FULLPATH 23 29))                  ENDSELECT                                                                                                                                       GOTO       CMDLBL(START)                                    #EOF:       ENDPGM

ANSWERED:  Mar 21, 2013  12:03 AM (GMT)  by Eric Witham

 
Other Answers:

you can create a file for your program to process.   QFTPSRC is a regular source file (PF-SRC) that we store ftp scripts and logs you can use any source file you want (you will specify it in the OVRDBF commands).  In your CL you would:

  • OVRDBF FILE(INPUT) TOFILE(QFTPSRC) MBR(GETLIST) OVRSCOPE(*CALLLVL)
  • OVRDBF FILE(OUTPUT) TOFILE(QFTPSRC) MBR(GETLISTLOG)OVRSCOPE(*CALLLVL)
  • OVRDBF FILE(LSOUTPUT) TOFILE(QTEMP/LSOUTPUT) OVRSCOPE(*CALLLVL)
  • FTP RMTSYS(NONE) 
  • DLTOVR FILE(*ALL) LVL(*)
  • process QTEMP/LSOUTPUT

Member GETLIST would contain the following:

  • open target_site
  • user username password
  • cd library
  • lcd qtemp
  • ls * (DISK
  • close
  • quit
Last Wiki Answer Submitted:  March 20, 2013  2:16 pm  by  Michael Tidmarsh   11,380 pts.
Latest Answer Wiki Contributors:  BigKat   7,175 pts. , Michael Tidmarsh   11,380 pts.
To see other answers submitted to the Answer Wiki: View Answer History.


Discuss This Question:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _


 

I’m not entirely sure this is something that would work. The system I’m on is where the file is, so i can’t very well FTP to the same system.This is in the IFS and I get to the file using the WRKLNK ‘/’ command. One of the directories holds a .CSV file and i’m just trying to retrieve the name of the .CSV file. The only option i can think of is to do a DSPLNK and mark the output as *PRINT, then copy the spooled file to a physical flat file and read that. Since there’s only going to be 1 file in there at a time per day, this might be one of the few workarounds without having to use API’s, which, i’m not entirely opposed to. It just seems that there should be an easier way to deal with the IFS.

 685 pts.

 

…so i can’t very well FTP to the same system.
 
Why not? Is it restricted?
 
FTP to/from same system might be the easiest way to do it. It’s certainly possible to read directory entries, but it’s a little more complicated.
 
Tom

 107,715 pts.

 

If you prefer an actual programmed solution, Qshell isn’t necessary. ILE CL can read directories directly:

pgm    ( +
         &DirName     +
       )

   dcl   &DirName     *char  128


   dcl   &FName       *char  640

   dcl   &x00         *char    1     value( x’00′ )

   dcl   &rc          *int
   dcl   &subrc       *int

   dcl   &Dir         *char  128
   dcl   &Link        *char  640

   dcl   &BUF         *char 4096
   dcl   &mtime       *int           stg( *defined ) defvar( &BUF    29 )
   dcl   &oType       *char   10     stg( *defined ) defvar( &BUF    49 )

   dcl   &pCTime      *ptr
   dcl   &CTime       *char   24     +
                         stg( *BASED )  +
                         basptr( &pCTime )

   dcl   &pDir        *ptr
   dcl   &DirDS       *char    1     +
                         stg( *BASED )  +
                         basptr( &pDir )

 /* Directory entry DS */
   dcl   &pDirEnt     *ptr
   dcl   &DirEnt      *char 1024     +
                         stg( *BASED )  +
                         basptr( &pDirEnt )
   dcl   &res1        *char   16     stg( *defined ) defvar( &DirEnt  1 )
   dcl   &sgenid      *uint          stg( *defined ) defvar( &DirEnt 17 )
   dcl   &sfileno     *int           stg( *defined ) defvar( &DirEnt 21 )
   dcl   &sreclen     *uint          stg( *defined ) defvar( &DirEnt 25 )
   dcl   &res2        *int           stg( *defined ) defvar( &DirEnt 29 )
   dcl   &res3        *char    8     stg( *defined ) defvar( &DirEnt 33 )
   dcl   &snlsinf     *char   12     stg( *defined ) defvar( &DirEnt 41 )
   dcl   &snamlen     *uint          stg( *defined ) defvar( &DirEnt 53 )
   dcl   &sfname      *char  640     stg( *defined ) defvar( &DirEnt 57 )

   dcl   &nullptr     *ptr


   monmsg    ( cpf0000 mch0000 cpf9999 ) exec( goto StdErr )


   chgvar            &Dir         ( &DirName *tcat &x00 )

   callprc     ‘opendir’          ( &Dir ) rtnval( &pDir )
   if ( &pDir *eq &nullptr )  +
      goto  Close_Dir

   dountil  ( &pDirEnt *eq &nullptr )

      callprc     ‘readdir’       ( &DirDS ) rtnval( &pDirEnt )
      if ( &pDirEnt *ne &nullptr )  +
         callsubr    OutEntry     rtnval( &subrc )

   enddo

   goto  Close_Dir

StdErr:

   dmpclpgm
   monmsg (cpf0000 cpf9999 mch0000)

Close_Dir:

   callprc     ‘closedir’         ( &DirDS ) rtnval( &rc )
   monmsg (cpf0000 cpf9999 cee0000 mch0000)

   return

subr     OutEntry

   if ( &snamlen *gt 0 )  do
      chgvar        &FName    %sst( &sfname 1 &snamlen )
      chgvar        &Link         ( +
                                    &DirName *tcat ‘/’ *cat +
                                    &FName   *tcat +
                                    &x00  +
                                  )
      callprc     ‘stat’          ( &Link &BUF ) rtnval( &rc )

      if ( &rc *eq 0 )  do
         callprc  ‘ctime’         ( &mtime ) rtnval( &pCTime )
         sndpgmmsg   msgid( CPF9898 ) msgf( QCPFMSG ) +
                       msgdta( +
                               ‘Object Found’   *bcat +
                               &CTime           *bcat +
                               &FName           *bcat +
                               &oType                 +
                             ) +
                       msgtype( *INFO )
      enddo
      else  +
         rtnsubr rtnval( -1 )
   enddo

   endsubr

endpgm

The program accepts a 128-char directory and lists its contents via messages. Note that the directory name parm value must be padded with blanks if it’s shorter than 128 characters.
 
Compile as a *MODULE. Then use CRTPGM to create the program from the *MODULE and specify BNDDIR(QC2LE) to pull in the APIs.
 
Modify it to cut out the stuff for sending the messages. It’s just an example program, so it can simply return a file name as an output parm. Use this version just to see how opendir(), readdir() and closedir() work.
 
Note that all directories include the [.] and [..] entries. Simple IF-tests can skip those.
 
Tom

 107,715 pts.

 

oh, I thought the files were still on the other system when you had to determine the dynamic name.  Although as Tom mentioned, you can FTP back to yourself and it shouldn’t be restricted, as the data is already being FTP’d to you.

 7,175 pts.

 

BigKat, agreed. My mistake. Company is sending us the file, i just have to retrieve it and don’t know the name. But i found the code that completely helps.Tom, thanks. I think the resolution i posed with the clle code is an actual programmed solutions. I’m using code within a source member to retrieve information. i can make it a dynamic process for other programs to use, but i didn’t because this isn’t a common issue.I appreciate the help from both though!

 685 pts.

 

Re BigKat’s FTP: Essentially all network functions can be routed right back to the originating server. It’s a very useful testing technique to remember for the future. Testing can be done even when you only have a single server simply by using appropriate host names (or IP addresses or even APPN control point names).
 
Re “programmed solution”: Yes, Scott Klement’s method is indeed. To clarify, I was referring to FTP and supplying an alternative to that. Other members following the thread might not allow FTP to be active on their server. Your acceptance of Scott’s work indicated that you were wanting direct programming rather than something of a workaround (i.e., FTP). So, I was showing the basics that was even more direct and that didn’t require an optional OS component. I use Qshell regularly on my own systems just as you’re using it.
 
But because I also work on many other systems, I know that lots of members need alternatives. Qshell won’t be available for some others, and PTF issues might cause trouble for some in production environments.
 
Qshell interaction with QSYS.LIB features does get a little twisted from time to time. If direct access to /root via APIs is understood, or at least working examples are available, some members will get use out of it.
 
Tom

 107,715 pts.