RPG-ILE - Converting Decimal to Octal values for STAT function

From MidrangeWiki
Revision as of 13:18, 26 January 2018 by Phenrico (talk | contribs) (Created page with "==Background== When you extract data with the STAT function from IFS objects, it returns a lot of information. Unfortunately, it becomes difficult to always tie that informa...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Background

When you extract data with the STAT function from IFS objects, it returns a lot of information. Unfortunately, it becomes difficult to always tie that information to what you will see on the screen. One of the challenges I had was to write program in RPG that pulled information out similar to the QRYIFSLIB freeware tool. The problem came in when I wanted to know what permissions were loaded on the file or directory. This procedure will show how you can translate the value received from stat for the file mode into an octal value for you to retrieve the information needed to determine the permissions.


Problem definition

When you run the stat function on an IFS object, one of the very first fields (usually named st_mode) returns a decimal value. The value corresponds to the actual permissions on the file. However, since it is retrieved as a decimal value, it involves having a large number of permutations to make up the rwxrwxrwx permission structure. For example:

I have the following files with their respective permissions in an IFS directory:

----------   Jan 25 17:06 testfile1  
---x------   Jan 25 17:11 testfile10 
-rw-------   Jan 26 09:38 testfile11 
-rwx------   Jan 26 09:38 testfile12 
-r-x------   Jan 26 09:38 testfile13 
--wx------   Jan 26 09:38 testfile14 
----rw----   Jan 26 09:38 testfile15 

The permissions list here will each correspond to a specific decimal number:

st_Mode = 32768 => return '---------';
st_Mode = 32769 => return '--------x';
st_Mode = 32770 => return '-------w-';
st_Mode = 17924 => return '------r--';
st_Mode = 32776 => return '-----x---';
etc

To make the process easier, I have written a DecimalToOctal function that takes the st_mode value, translates it into octal, and then determine the correct permissions. It has been based on method 2 as described on this link: [1]


     *======================================================================*    
     *  Subroutine.... DecimalToOctal                                       *    
     *  Description... Take the st_mode decimal value and return an octal value* 
     *======================================================================*    
       dcl-proc DecimalToOctal;                                                  
       dcl-pi DecimalToOctal                 int(10);                         
               p_St_Mode                     int(10) value;                   
       end-pi;                                                                   
       //                                                                        
           dcl-s OctalVal                    char(15);                           
           dcl-s WorkField1                  int(10);                             
           dcl-s WorkField2                  int(10);                            
           dcl-s WorkField3                  int(10);                                 
           dcl-s LoopCount                   int(10);                                
           dcl-s OctalPosition               int(10);                                
       //                                                                        
           OctalPosition = 15;  // will start at the right side                  
           WorkField3 = p_St_Mode;                                               
           DoU WorkField3 = 0;                                                   
               WorkField1 = %div(WorkField3:8);                                  
               WorkField2 = WorkField3 - (8 * WorkField1);              
               %subst(OctalVal:OctalPosition:1) = %char(WorkField2);    
               OctalPosition -= 1;                                      
               WorkField3 = WorkField1;                                 
           EndDo;                                                       
           Return %Int(OctalVal);                                       
       End-proc;                                                        

The next step will be to use this returned value in a subprocedure to determine the correct permissions. The permissions have been determined as per this url: [2]


     *======================================================================* 
     *  Subroutine.... RetrievAuthority                                     * 
     *  Description... Take the st_mode value and return an RWX-based string* 
     *======================================================================* 
       dcl-proc RetrieveAuthority;                                            
       dcl-pi RetrieveAuthority              char(10);                        
               p_St_Mode                     int(10) value;                   
       end-pi;                                                                
       //                                                                     
           dcl-s OctalChar                   char(15);                        
           dcl-s OctalLength                 int(10);                         
           dcl-s PermissionList              char(9) inz('---------');        
           dcl-s OctalVal                    int(10);                         
       //                                                                     
           OctalVal =  DecimalToOctal(p_st_mode);                             
           OctalChar = %char(OctalVal);                                       
           OctalLength = %len(%trim(OctalChar));                              
       //      
       // Determine the owner permissions here                                                               
           Select;                                                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '7';             
              %subst(PermissionList:1:3) = 'rwx';                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '6';             
              %subst(PermissionList:1:3) = 'rw-';                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '5';             
              %subst(PermissionList:1:3) = 'r-x';                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '4';             
              %subst(PermissionList:1:3) = 'r--';                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '3';             
              %subst(PermissionList:1:3) = 'rw-';                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '2';             
              %subst(PermissionList:1:3) = '-w-';                            
           When %subst(%trim(OctalChar):OctalLength - 2:1) = '1';             
              %subst(PermissionList:1:3) = '--x';                            
           Other;                                                             
              %subst(PermissionList:1:3) = '---';                            
          EndSl;                                                             
          // Determine the group permissions here                                                                
          Select;                                                            
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '7';             
              %subst(PermissionList:4:3) = 'rwx';                            
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '6';             
              %subst(PermissionList:4:3) = 'rw-';                     
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '5';      
              %subst(PermissionList:4:3) = 'r-x';                     
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '4';      
              %subst(PermissionList:4:3) = 'r--';                     
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '3';      
              %subst(PermissionList:4:3) = 'rw-';                     
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '2';      
              %subst(PermissionList:4:3) = '-w-';                     
           When %subst(%trim(OctalChar):OctalLength - 1:1) = '1';      
              %subst(PermissionList:4:3) = '--x';                     
           Other;                                                      
              %subst(PermissionList:4:3) = '---';                     
          EndSl;                                                      
          // Determine the *PUBLIC permissions here
          Select;                                                     
           When %subst(%trim(OctalChar):OctalLength:1) = '7';          
              %subst(PermissionList:7:3) = 'rwx';                     
           When %subst(%trim(OctalChar):OctalLength:1) = '6';          
              %subst(PermissionList:7:3) = 'rw-';                     
           When %subst(%trim(OctalChar):OctalLength:1) = '5';          
               %subst(PermissionList:7:3) = 'r-x';                         
           When %subst(%trim(OctalChar):OctalLength:1) = '4';              
               %subst(PermissionList:7:3) = 'r--';                         
           When %subst(%trim(OctalChar):OctalLength:1) = '3';              
               %subst(PermissionList:7:3) = 'rw-';                         
           When %subst(%trim(OctalChar):OctalLength:1) = '2';              
               %subst(PermissionList:7:3) = '-w-';                         
           When %subst(%trim(OctalChar):OctalLength:1) = '1';              
               %subst(PermissionList:7:3) = '--x';                         
           Other;                                                          
               %subst(PermissionList:7:3) = '---';                         
          EndSl;                                                          
          Return PermissionList;                                          
       End-proc;                                         

In order to use this in your program, do the following:

- Declare your permission variable

 dcl-s Permissions   char(9);

- Run your stat process against the IFS object itself

- Call the subprocedure to determine the permissions

 Permissions = RetrieveAuthority(st_mode);