Problem solve Get help with specific problems with your technologies, process and projects.

Cleaning up unused or temporary IFS files – Part II

In a previous tip, "Cleaning up unused or temporary IFS files -- Part 1" Ron Turull introduced you to the code for the DELIFSFILE utility. In part II, Ron discusses the code in detail, including customizing the command, things to watch out for and more.

Ron Turull

In my pervious tip, Cleaning up unused or temporary IFS files -- Part 1 we looked at the code for the DELIFSFILE utility, but we had not yet discussed it. Let's finish up by discussing the code in detail.

More Information

The first thing the program does after defining some fairly simple variables is create two type definitions, Lg_Path_Name_T and P0l_AttrTypes_List_t. Unfortunately, the IBM versions of these type definitions are unusable as is because the last member of each data structure is commented-out. Therefore, we are forced to define our own, which is simple enough to do with cut and paste and a slight name change. Another alternative would be to use the IBM definition to define the first member of a data structure (i.e., a data structure within a data structure) and then add the commented out part. For example, the Lg_Path_Name_T type definition could be defined as follows:

 Qlg_Path_Name_T FirstPart;
 char   *Path_Name;

In our specific case, you could also define it as:

 Qlg_Path_Name_T FirstPart;
 char   QualFileName[1024];
That would save the step of assigning Path_Name to QualFileName, as in:

PathNameStruct.Path_Name = QualFileName;

Either way you do it, you still have to create your own definitions. The advantage of doing it the way shown in the code is it makes it easier for the reader (and the programmer to a certain extent) to follow the code. All of the members of the data structure are right there in the code -- not buried in some included file. The advantage of doing it as shown above is that it is safer should IBM ever change the structure; the program will probably need recompiling but not modifying.

Next, the program initializes some variables and then parses the incoming parameters. In the process of parsing the parameters, the program does some validity checking and prints out appropriate messages, as needed.

The program then gets down to business. Having divided the PATH parameter (the first parameter) into the directory portion and the file name portion, the program can then open the directory. This is akin to opening a file. The program can then read through the contents, or the entries, of the directory.

The program enters a "while-loop" to read each entry in the directory, perform the necessary checks on it, and delete it if it passes the checks. The loop is terminated when the readdir() function returns a null-pointer -- meaning no more directories entries to be read.

The validity checks that are performed on each file (i.e., directory entry) are as follows:

  • Make sure the entry is a regular file and not, for example, a subdirectory. The program uses the stat() function and the S_ISREG macro to determine that.

  • Does the file's name match the name specified by the user? Because the user can specify the wildcard characters * and ? as part of the name, the program cannot merely check for equivalence. Instead, the program must perform a wildcard match, which is done using our NameMatch() function (defined at the bottom of the code).

  • Finally, if the name matches, then the file's usage data is retrieved and the last-used date is checked against the date the user specified (actually, the user specifies the number of days the file must be unused, the program calculates the date-limit based on this number).

  • Customizing the command

    The Qp0lGetAttr API retrieves many other details about a file, in addition to the usage data. Basically, any attribute stored in the entry -- and then some --can be retrieved by the Qp0lGetAttr API. You can further refine that utility to meet your needs. We needed something that would get rid of the unused temporary files. You may want to selectively delete entries based on certain entry types or the entry's owner.

    Whatever the case may be, most customizations can be made by simply adding parameters to the command definition. Then have the Qp0lGetAttr API retrieve the necessary attributes and compare.

    Warning: Last-used date may not be what it seems

    Be very careful using that command and program as is. Make sure you use it only on file systems with which you are familiar. About the only check the program does is to make sure the file to be deleted is a regular file. That prevents the program from trying to delete an entire directory, for instance.

    However, many other possible "gotchas" exist (as is the case any time you are deleting something). One in particular is the last-used date. The manual states the last-used date is "The number of seconds since the Epoch that corresponds to the date the object was last used. This field is zero when the object is created. If usage data is not maintained for the iSeries type or the file system to which an object belongs, that field is zero."

    Therefore, it is possible to delete a file that was just used and/or is still actively being used if the system does not maintain its usage data and the last-used date is zero. The program can, of course, be easily modified to check for that and ask the user for a confirmation, for example. The program can also be modified to check for any other concerns you might have.

    Although that last one is not really a "gotcha", it is something to be aware of: Because the last-used date is stored as the number of seconds since Epoch time (January 1, 1970), one day is the equivalent of 86,400 seconds. When the user specifies that he wants files deleted that haven't been used in at least two days, the program will delete files that haven't been used for at least 172,800 seconds. If you run the DELIFSFILE command at 12:00 noon on May 25, files that haven't been used since before noon on May 23 will be deleted; those used after noon on May 23 won't.

    C for RPG programmers

    Note: I will be starting a year-long series on C programming in the November 2005 issue of Inside Version 5, a monthly newsletter for iSeries professionals. This series on C programming will be unique in that it will be discussed decidedly from the RPG programmer's frame of view. To subscribe to Inside Version 5, please call 877-440-0477.

    About the author: Ron Turull is editor of Inside Version 5. He has more than 20 years' experience programming for and managing AS/400-iSeries systems.

    Dig Deeper on Integrated File System (IFS)

    Start the conversation

    Send me notifications when other members comment.

    Please create a username to comment.