× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Hi John,

Your IFS directory code isn't working because it's corrupting memory. Although the problem is in your code, it's actually corrupting the variables inside the readdir() API, and causing it to fail.

The reason it works with some filesystems in the IFS, but not with others, is because the code that IBM wrote for reading a directory is a little different for each filesystem, and you happen to be corrupting something different in the /QDLS case than you are in other cases.

The fact that your code works today on te "root" filesystem, does not mean that it'll work tomorrow, or after applying the next PTF, or when you do a release upgrade. You're just "lucky" that it works today.

Let's look at your code:


Rtn = *Zeros;

@Dir = '/QDLS/FCCASES';

// Open the Directory
 d = opendir(%Trim(@Dir));
 If d = *Null;
   Rtn = -1;
 Else;

Up til this point, the code is okay. One comment I wanted to make, though, is that this is terrible error handling. When your program fails and you have to write a message to the screen or to a log that tells a user why it failed, simply saying "-1" or "it failed" is frankly not good enough.

You need to, at a very minimum, retrieve an error number. I'd go beyond the minimum and actually get an error message that describes the problem. Just returning -1 is not adequate.

   x = *zeros;
   p_dirent = readdir(d);
   dow p_dirent <> *Null;

// Always in the beginning of the DIR you get . twice
if %SubSt(d_Name:1:1) <> '.';
 x = x + 1;
 contents(x) = %Trim(d_Name);
endIf;


%TRIM(d_name) is wrong. You can't do that -- d_name is a variable-length spot in memory. Although it's probably defined as "640A" in your RPG program, it's not REALLY a fixed-length RPG variable.

The readdir() API will make the size of the d_name variable different for every single filename it reads. So if you have a file named "XXX" the d_name field will be 3A. If you have a file named "test.txt" the size of the d_name field will be 8A. If you have a file named "Todays Blue Chip Pricing Report.pdf" the d_name field will be 35A.

The problem is, your program can't dynamically change teh size of the d_name field. You have to define ONE length and then keep using it throughout your program.

So in my examples, I define it as 640A. Then, I'm always VERY careful to make sure that I only refer to the part of the field that was populated. Never refer to anything past that part.

The API will tell you which part of the d_name field is populated in a separate variable called "d_namelen".

So, your code above should look like this:

    contents(x) = %Trim(%subst(d_Name:1:d_namelen));

However, once you've coded that, you'll find that the %TRIM is completely unneceesary, since there won't be any spaces in the filename to begin with. So you may as well code it this way:

    contents(x) = %subst(d_name:1:d_namelen);

Now, on to the really big problem with your code:

/ Clear the Name field for fresh Start
d_Name = *Blanks;

This is the one that's causing your code to fail, and causing memory to be corrupted. Keep in mind what I said about d_name having a dynamic size... sometimes it 3A, sometimes it's 8A, sometimes it's 12A, sometimes it's 35A...

In fact, since the first directory entry in your program will just contain ".", the first time through the loop, it'll be a 1A field.

Since you have it defined as 640A, when you set d_name = *blanks, what have you done? You've overwritten the one "." with a blank. And then the next 639 bytes of memory after that blank -- memory that doesn't belong to you -- memory that's being used for something else inside the readdir() API -- is being set to x'40'.

Ouch. That's REALLY dangerous. Not to mention, it's completely unnecessary. I suspect that the reason you're doing this is so that the earlier %TRIM will work properly -- however, now that you're using %SUBST rather than %TRIM it's completely unnecessary!

Just remove the "d_name = *Blanks" line.

Hope that helps.

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.