On 11/07/2008, at 12:52 AM, CRPence wrote:

I agree with you that both of those, the *LIB and the database *FILE,
are native OS/400 object types. I think what you are missing, is the
probability that the code was written something like the following [not
to imply that I know; I do not]:

dcl is_dir int init 0
dcl is_lnk int init 0
dcl is_ntv int init 0
dcl is_sck int init 0
when object_is_container() then is_dir = 1;
when object_is_socket() then is_sck = 1;
when object_is_lnk() then is_lnk = 1;
otherwise do;
... if ... is_ntv = 1; ...
end select;

Implication being that probably, once the code determines that the
object is capable of drill-down, being an effective /directory/, the
IsNative likely just remains unset, due to how it was coded.

It's more fundamental than that. The stat() function populates a structure. One of the sub-fields is st_mode which is a mode_t which is an unsigned integer. Each bit in the 4-byte integer is either reserved or has meaning. The left-most 15 bits (i.e., 0-14 in IBM's bit numbering scheme) are reserved (or not used). The next 5 bits (15-19) indicate the type of object (note that only bits 16-19 are used on most (all?) Unix variants). Bits 20 and 21 indicate UID and GID set. Bit 22 appears reserved. Finally bits 23-31 are permission bits indicating RWX for each of User (i.e, owner), Group, and Other (i.e., public).

There are 8 (7 on Unix) object types represented by the 5 type bits:
Regular file
Character special file
Block special file
FIFO (or pipe)
Symbolic link
Native object (OS/400 only)

There are a bunch of C macros in sys/stat.h that provide a means of testing these bits. They are used as follows:

if (S_ISDIR(ifsInfo.st_mode) )

These macros are all of the form where the supplied st_mode is bitwise-ANDed with a mask to extract the type bits which are then compared with constants containing the expected bit pattern for that type. Thus S_ISDIR becomes:

if ( ( ifsInfo.st_mode & 0370000 ) == 0040000 )

NOTE: That this is C so literal numbers beginning with 0 are in Octal. Converting to hexadecimal makes the bit pattern of types more obvious:

S_IFFIFO 0010000 0x1000
S_IFCHR 0020000 0x2000
S_IFDIR 0040000 0x4000
S_IFBLK 0060000 0x6000
S_IFREG 0100000 0x8000
S_IFLNK 0120000 0xA000
S_IFSOCK 0140000 0xC000
S_IFNATIVE 0200000 0x10000

Most of these use a single bit to indicate the type but some (BLK, LNK and SOCK) use 2 bits.

So although most code that uses these macros presumes they are exclusive and is written like:

if (S_ISREG(buf.st_mode)) ptr = "regular";
else if (S_ISDIR(buf.st_mode)) ptr = "directory";
else if (S_ISCHR(buf.st_mode)) ptr = "character special";
else if (S_ISBLK(buf.st_mode)) ptr = "block special";
else if (S_ISFIFO(buf.st_mode)) ptr = "fifo";
#ifdef S_ISLNK
else if (S_ISLNK(buf.st_mode)) ptr = "symbolic link";
#ifdef S_ISSOCK
else if (S_ISSOCK(buf.st_mode)) ptr = "socket";
else if (S_ISNATIVE(buf.st_mode)) ptr = "OS/400 object";
else ptr = "** unknown mode **";

printf("type %s\n", ptr);

There is nothing in the use of these bits that precludes having more than one type evaluate to true (except possibly precedence on other platforms i.e., they are presumed to be unique).

For *LIB and *FILE the S_IFDIR bit is set, for *MBR the S_IFREG bit is set and none of the three have the S_IFNATIVE bit set. The only objects that have the S_IFNATIVE bit set are things that are not *DIR, *STMF, *DDIR, *DSTMF, *LIB, *FILE, or *MBR objects.

Oh ... having written all that I see what you mean. The OS code that determines which bits to set also presumes a single unique bit pattern i.e., a given object can only ever be of one type thus it only sets one pattern.

Hmm, short-sighted design. Oh well, I'll leave this in the archives-- someone else may find it helpful.

However I
doubt even if anyone in development agreed, they'd probably just say
/working as designed/ even though more likely it is /working as coded/;
or at least state that it is too dangerous to change because someone
[the OS itself, being most notable] may have coded to that anomalous
outcome, irrespective of how illogical. No harm in trying :-)

I'll open this as a documentation issue because the description of S_ISNATIVE should be more explicit about which OS objects will not be considered "native".

I can't see this being changed to work as is should (rather than as it does) simply because Rochester would need to change the definitions of the various S_ISxxxxx macros to allow for the S_IFNATIVE bit being set in addition to the S_IFDIR or S_IFREG bits.

Easy enough to change by resetting the OS/400 bit mask of 0370000 (x'1F0000') back to the Unix S_IFMT value of 0170000 (x'F0000') to ignore the S_IFNATIVE bit on all macros except S_ISNATIVE. However, because Cs idea of a macro is simply code substitution, lots of existing code will contain an incorrect bit mask and corresponding test and thus will break when such a change is implemented.

I'll just have to code around it by testing the st_objtype for the three anomalous object types.

Simon Coulter.
FlyByNight Software OS/400, i5/OS Technical Specialists

Phone: +61 2 6657 8251 Mobile: +61 0411 091 400 /"\
Fax: +61 2 6657 8251 \ /
ASCII Ribbon campaign against HTML E-Mail / \

This thread ...


Return to Archive home page | Return to MIDRANGE.COM home page