“Whilst like a puffed and reckless libertine Himself the primrose path of dalliance treads And recks not his own rede.” (Hamlet, I, iii)
If you like to name things, the AS/400 Integrated File System (AS/400 IFS) is a treat. Can you correctly type a PC or UNIX-style long path name on the command line again and again? If so, congratulations! File names bedevil me. Since the first release of OS/400 in Version 1, I’ve been struggling with the proper name order for even the simplest of qualified names in CL commands. Is it library-slash-object or object-slash-library? I’m grateful that OS/400 prevents me from creating user libraries within user libraries; otherwise, I might still be debugging legacy code of library-slash-library-slash-object names. So when IBM introduced the AS/400 IFS with long path names in Version 3 five years ago, I thought, “I won’t be using any of this stuff.”
Simplicity vanished. Today, all my projects deal with the AS/400 IFS. From importing electronic data interchange (EDI) X.12 transaction sets across local Sockets objects to exporting Multipurpose Internet Mail Extension (MIME) formatted email and HTML Web pages, my AS/400 IFS has become a crucial warehouse for my business data. Now I must remember the new rules and puzzling quirks of PC and UNIX-style path names. Yet, amazingly, the new rules yield some elegant patterns and concepts. Here are some patterns that help me navigate the maze of new rules.
New Object Type
If you have ever faced a DOS command line, then you know the persnickety nature of path names. A path name tells the system how to locate an object through a sequence of directory and object names. Forward slashes (/) or backward slashes () separate names in this path. On the AS/400, a path name indicates a route into the AS/400 IFS. The AS/400 IFS provides a hierarchical structure where you can organize objects like fruit on different branches of a tree. A path name into the AS/400 IFS specifies the subbranches that lead to a particular “fruit.” By the way, the AS/400 IFS is like a genetically mutated tree because a single fruit may hang from multiple branches.
V3R1 added a new object type that lets you assemble an AS/400 IFS “fruit tree”: the directory object of type *DIR. A directory object is a special object that contains lists of
other objects, including other directories. Directories within directories are called subdirectories. The highest directory in the AS/400 IFS fruit tree is the root (/) directory.
A link is AS/400 IFS parlance for a named connection between a directory and an object. An object is linked to a directory when you first create the object. You can subsequently link an object into multiple directories with the Add Link (ADDLNK) command. The linkage services provided by a directory object are different from the linkage services provided by a library object of type *LIB—although a library masquerades as a directory in the AS/400 IFS fruit tree. Object names in a library are observable through unblocked Machine Interface (MI) instructions, but object names in a directory are only observable through blocked MI database instructions. The object names in a directory are in the two-byte UCS2 level 1 format, also known as Unicode. High-level directory APIs can translate between the internal Unicode representation of an object name and the external code page used by an API caller.
The AS/400 IFS can contain many different types of objects such as Java class files, image files such as JPGs and GIFs, and even video and sound files. In fact, the AS/400 IFS can store pretty much any type of object you’d normally only associate with the PC world.
Current vs. Home
Each job on the AS/400 has a current directory attribute. The system searches the current directory when a job requests an operation on an object, unless the job specifies a different directory path. A job can retrieve its current directory path with the Display Current Directory (DSPCURDIR) command if the call stack entry requesting DSPCURDIR has read (*R) and execute (*X) data authority to every subdirectory in the path. It needs this level of authority because the Change Current Directory (CHGCURDIR) command requires only the execute (*X) data authority to every subdirectory in the path; therefore, a job may change its current directory to a certain path and then be unable to display that path.
Each user profile specifies a home directory. A home directory becomes the current directory when a job starts running under a user profile. If the home directory does not exist, the system changes the current directory to the root (/) directory. A user’s home directory is not automatically created with CRTUSRPRF HOMEDIR(*USRPRF). Rather, a system administrator uses the Create Directory (CRTDIR) command to create a subdirectory in the /home subdirectory of the root (/) directory after a new user profile is created. For example, my user profile name is Gaunt, and my home directory is /home/Gaunt.
Absolute vs. Relative
There are two types of path names: absolute and relative. An absolute path name begins at the highest level with the root (/) directory. A relative path name begins at a job’s current directory. An absolute path name begins with a slash character; a relative path name does not. A tilde (~) character followed by a slash at the beginning of a path name indicates the path begins at the home directory of the user entering the command. For example, look at the following commands. If my job’s current directory is /home/Gaunt, then the following will give me identical results.
EDTF STMF(‘/home/Gaunt/Welcome.html’) /*absolute*/
Objects in QSYS
The QSYS.LIB file system appears in the AS/400 IFS as a subdirectory below the root (/) directory. Each component of a QSYS.LIB path name contains the object name, followed by a period (.), followed by the object type of the object. The object type suffixes are required because the same object name can appear multiple times in a library with different types. Remember to specify the opening slash (/) before QSYS.LIB in order to create an absolute path name. Without the opening slash, the system will treat the path name like a relative path name and try to look for a subdirectory named QSYS.LIB in your current directory. In the following example, I have a file named BILL, which has a member named AUG, which is stored in the library named PROFIT:
EDTF STMF(‘/QSYS.LIB/PROFIT.LIB/BILL.FILE/ +
Simple vs. Long
There are two path name styles in APIs: simple and long. An API uses one or the other but not both. The simple path name style is a pointer to a null-terminated string containing the path name. The long path name style is a pointer to a structure containing seven pieces of information. Figure 1 shows the layout of the long path name structure. The reference manual OS/400 UNIX-Type APIs V4R4 refers to the long path name style with the structure name Qlg_Path_Name_T. Inside the structure, you can specify a coded character set, a country ID, a language ID, a path name length, a path delimiter character, a path type indicator, and a path name subfield.
There are two types of links: hard and soft. A hard link is born when you create an object in a directory. After the hard link is created, you can create secondary hard links between the object and other directories with the ADDLNK command. This capability allows multiple directories to share an object. The Remove Link (RMVLNK) command removes a hard link. After the last hard link is removed between a directory and an object, the object is physically deleted.
A hard link can create an alias path name. I like this feature a lot. The ADDLNK command in the following example creates a hard link named A in my home directory. The A links my home directory to a file named X12.txt in the /exports/daily subdirectory. After this ADDLNK command executes once, the following two EDTF commands give me identical results. Obviously the second EDTF command is easier for me to type!
ADDLNK OBJ(‘/exports/daily/X12.txt’) +
EDTF STMF(‘/exports/daily/X12.txt’) /*absolute*/
/*relative + hard link*/
A soft link is a physical object of type *SYMLNK. A soft link is a little stream file that contains a component of a path name. You can create a soft link by specifying the LNKTYPE(*SYMBOLIC) parameter in the ADDLNK command. When the system encounters a soft link in a path name, the system follows the path name in the soft link and then continues on any remaining path that follows the soft link. If the path name in the soft link begins with a slash, the system returns to the root (/) directory and begins following the path from that point. The objects named in the soft link do not have to exist when the soft link is created. Thus, a soft link provides a path name that you can later add to or replace.
Soft links are useful in HTML anchor tags in a dynamic Web environment. Instead of coding an absolute URL hyperlink in an anchor tag, you can just code a soft link name, followed by a slash, followed by an HTML file name, and then later use ADDLNK to create a soft link to the real subdirectory containing the HTML file. Suppose you code the following HTML anchor tag in a file:
Next Page (/Parent/Page2.html)
Suppose that subdirectory /Testing actually contains the hard link to the Page2.html file. You could create a *SYMLNK object named Parent in the root (/) directory containing a soft link to the /Testing subdirectory with the following command:
ADDLNK OBJ(‘/Testing’) NEWLNK(‘/Parent’) +
Later, if you execute the following two commands to port Page2.html to a subdirectory named Live, your anchor tag will continue to work OK:
ADDLNK OBJ(‘/Live’) NEWLNK(‘/Parent’) LNKTYPE(*SYMBOLIC)
The point here is that you do not have to edit or change the URL in the anchor tag if you use soft links.
The new Process a Path Name (Qp0lProcessSubtree) API from V4R3 uses the long path name style. This API searches the AS/400 IFS directory tree under a specific path name. The API caller passes a pointer to a user exit procedure; the API invokes the user exit procedure for each object in the AS/400 IFS directory tree under the specified path name, passing in the object name as a parameter in two-byte Unicode format. When the user exit procedure receives control, it can build lists or tables. It is this API that drives an EXPLORE utility I have created for this article.
One of the things I like about Windows is the Explorer. Windows Explorer lets me descend through a nest of folders to a file, click the file icon, and auto-fill the absolute path name of the file into some entry field. No typing is necessary. To mimic this behavior, I created a green-screen EXPLORE utility to interface with OS/400 commands on an AS/400 command line. You can download the code for EXPLORE from www.midrangecomputing.com/mc. There are three source member components you will need to compile: command EXPLORE, display file EXP001D, and ILE RPG program EXP001R.
Type EXPLORE on an AS/400 command line and press the Enter key. Figure 2 shows a screen shot of the first screen on my home system when I run EXPLORE. This is the list the objects in my root (/) directory. EXPLORE calls this level 1. The left column lists the object names. The right column lists object types. “More...” or “Bottom” in the lower right-hand corner indicates whether the roll keys will page forward and backward through more objects in the directory.
Position the cursor on an object name of type *DIR, press the Enter key, and EXPLORE will drill down to the next level, displaying all objects in your selected subdirectory, provided you have read (*R) data authority to the directory. The Level count at the bottom of the screen will increment by one. You can drill down to 99 levels. EXPLORE uses a recursive RPG IV subprocedure to drill down through AS/400 IFS subdirectories.
You can interface EXPLORE with OS/400 commands in the following way. Drill down through a nest of subdirectories, position the cursor on the name of an object, and
press the F9 key. EXPLORE will display the absolute path name of that object on message line 24 and also write the absolute path name to the job log as a request (*RQS) message and mark that message as old. Exit the EXPLORE utility, press the F9 key on a standard OS/400 command line, and you’ll see the absolute path name. Then use the Insert and Delete keys to work this absolute path name into a parameter for another command called from the command line. You could also write a little bit of CL code to automatically retrieve that message from the job log and pass it as a command string to some other program. This program source will also give you a good start on using these APIs and in developing your own code.
Path Names Made Simple
With more and more UNIX-type systems being ported to the AS/400, I’ll probably use the EXPLORE utility F9 key more often. No more typing an audaciously long path name on a command line for me!
REFERENCES AND RELATED MATERIALS
• OS/400 UNIX-Type APIs V4R4 (SC41-5875-03, CD-ROM QB3AM403)
Position Type Field
1 - 4 BINARY(4) coded character set ID of the path name
0 = use the current job default CCSID 5 -6 CHAR(2) country ID for the path name
X’0000’ = use the current job country ID 7 -9 CHAR(3) language ID for the path name
X’000000’ = use the current job language ID 10 - 12 CHAR(3) reserved (binary zeros)
13 - 16 BINARY(4) path type indicator
0 = character string (use single delimiter character) 1 = pointer (use single delimiter character) 2 = character string (use double delimiter character) 3 = pointer (use double delimeter character) 17 - 20 BINARY(4) length of path name
21 - 22 CHAR(2) path name delimiter character
23 - 32 CHAR(10) reserved (binary zeros)
33 - CHAR(*) path name (character string or pointer)
Figure 1: A long path name style uses a pointer to the Qlg_Path_Name_T structure.
Figure 2: The EXPLORE utility displays the root (/) directory first.