× 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.



Scott,

Thanks for the help and I totally understand now the reason its 
failing...!  As for the error handling this is just a small quick app test 
to make sure I can do what I want then will be created as a service 
program with the error handling done correctly...

Thanks again for the insight to help me understand more!

Thanks-john




Scott Klement <rpg400-l@xxxxxxxxxxxxxxxx> 
Sent by: rpg400-l-bounces@xxxxxxxxxxxx
02/21/2006 11:43 AM
Please respond to
RPG programming on the AS400 / iSeries <rpg400-l@xxxxxxxxxxxx>


To
RPG programming on the AS400 / iSeries <rpg400-l@xxxxxxxxxxxx>
cc

Subject
Re: IFS Reading Question....






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 ...

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.