Moving an Object in the IFS

Article ID: 18505

Q: Is there an API equivalent of the MOV CL command?

A: When you "move" an object on disk, you're not really moving the location of the object's data, you're changing the directory and/or filename that is used to access that data. In most cases, a "move" is equivalent to a "rename."

There are two IFS APIs that can be used for renaming an object. They are Qp0lRenameKeep() and Qp0lRenameUnlink(). The difference between them is the action taken when the destination filename already exists. Qp0lRenameKeep() will return an error, but Qp0lRenameUnlink() will replace the destination file.

One situation where "move" is not the same as "rename" is when the source filename and destination filename are on different file systems. In that situation, it's necessary to physically move the file's data from one place on disk to another rather than just rename it. If this is desired, you'll need to copy the file and then delete the old one.

Here's a sample program that moves a file using the Qp0lRenameKeep() API:

     H DFTACTGRP(*NO) BNDDIR('QC2LE')

     D rename          PR            10I 0 ExtProc('Qp0lRenameKeep')
     D   old                           *   Value options(*string)
     D   new                           *   Value options(*string)

     D ReportError     PR

     D Source          s            100A
     D Target          s            100A

     c                   eval      Source='/home/klemscot/editest.txt'
     c                   eval      Target='/tmp/editest.txt'

      *
      * Note that if Source and Target are in different file systems,
      *      this will fail with "CPE3405: Improper Link"
      *
     c                   if        rename(%trimr(source):
     c                                    %trimr(target)) < 0
     c                   callp     ReportError
     c                   endif

     c                   eval      *inlr = *on
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * ReportError():  Send an escape message explaining any errors
      *                 that occurred.
      *
      *  This function requires binding directory QC2LE in order
      *  to access the __errno() function.
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     P ReportError     B
     D ReportError     PI

     D sys_errno       PR              *   ExtProc('__errno')
     D p_errno         s               *
     D errno           s             10I 0 based(p_errno)

     D QMHSNDPM        PR                  ExtPgm('QMHSNDPM')
     D   MessageID                    7A   Const
     D   QualMsgF                    20A   Const
     D   MsgData                      1A   Const
     D   MsgDtaLen                   10I 0 Const
     D   MsgType                     10A   Const
     D   CallStkEnt                  10A   Const
     D   CallStkCnt                  10I 0 Const
     D   MessageKey                   4A
     D   ErrorCode                 8192A   options(*varsize)

     D dsEC            DS
     D  BytesProv              1      4I 0 inz(0)
     D  BytesAvail             5      8I 0 inz(0)

     D MsgKey          S              4A
     D MsgNo           s              4P 0

     c                   eval      p_errno = sys_errno
     c                   eval      msgno = errno

     c                   callp     QMHSNDPM( 'CPE' + %editc(msgno:'X')
     c                                     : 'QCPFMSG   *LIBL'
     c                                     : ' ': 0: '*ESCAPE': '*': 3
     c                                     : MsgKey: dsEC)
     P                 E

Another alternative is to call the MOV command using the QCMDEXC API. The disadvantage to this method is that you have to make sure that the filenames do not contain quotes or other characters that would cause QCMDEXC to misinterpret the file names. If that's not a concern, QCMDEXC and MOV can be used to do the job:

     D QCMDEXC         PR                  ExtPgm('QCMDEXC')
     D   command                   3000A   const options(*varsize)
     D   length                      15P 5 const

     D Source          s            100A
     D Target          s            100A
     D cmd             s           3000A   varying

     c                   eval      Source='/tmp/editest.txt'
     c                   eval      Target='/home/klemscot/editest.txt'

     c                   eval      cmd = 'MOV OBJ(''' + %trimr(source) +
     c                                 ''') TOOBJ(''' + %trimr(target) +
     c                                 ''')'

     c                   callp     QCMDEXC(cmd: %len(cmd))

     c                   eval      *inlr = *on

ProVIP Sponsors

ProVIP Sponsors