[Info-vax] Looking for documentation for programming with symlinks

Mark Berryman mark at theberrymans.com
Sun Nov 10 22:51:38 EST 2019


On 11/9/19 6:55 PM, John E. Malmberg wrote:
> On 11/9/2019 10:41 AM, John Reagan wrote:
>> On Friday, November 8, 2019 at 7:34:50 PM UTC-5, John E. Malmberg wrote:
>>> On 11/8/2019 10:13 AM, John Reagan wrote:
>>>> On Friday, November 8, 2019 at 9:04:57 AM UTC-5, John E. Malmberg 
>>>> wrote:
>>>>> Hello,
>>>>>
>>>>> I am looking for documentation on programming symlinks using system
>>>>> services.
>>>>>
>>>>> Particularly the usages of:
>>>>>
>>>>> ATR$C_SYMLINK
>>>>> ATR$S_SYMLINK
>>>>>
>>>>> FAB$C_SYMLINK
>>>>> FAB$C_SYMBOLIC_LINK
>>>>>
>>>>> naml$v_symlink_in_path
>>>>> naml$v_object_symlink
>>>>>
>>>>> I think I can figure most of it out by looking at the header files
>>>>> generated by SDL.
>>>>>
>>>>> Regards,
>>>>> -John
>>>>> wb8tyw at qsl.net_work
>>>>
>>>> The ATR$ symbols are the F11XQP file attribute for a symlink.  The
>>>> FAB$ ones are for creating/accessing a symlink.  For the NAML$ bits,
>>>> I searched ALL the listings on a full Itanium build disk and found no
>>>> uses of SYMLNK_IN_PATH at all.  For OBJECT_SYMLINK, I found one place
>>>> in the CRTL that looks at it, but I found zero places that set it.
>>>
>>> While something in the CRTL has to check if a file is a symlink for the
>>> difference in stat or lstat.
>>>
>>> In my case I need to check if the file is a symlink, and if it is, I
>>> have to check to see if the symlink is to a directory.
>>>
>>> I am already using sys$parse and sys$search to see if the file or link
>>> exists, so I am trying to get the additional information as efficiently
>>> as possible.
>>>
>>> Regards,
>>> -John
>>
>> Well, from POSIX, you'd call lstat() on the file and check the
>> returned mode in the stat buffer to see if S_IFLNK. That's what most of
>> the ACRTL does and what any other program should do.
> 
> I may need to run some more tests on lstat() Currently I am showing in 
> my tests:
> 
> $ create sys$disk:[]test."
> $ create/symlink="./test" sys$disk:[]^9test.
> 
> The CRTL lstat("^9test") is returning st_mode as 100000 instead of 
> 120000 as expected if my test logic is correct.
> 
> I am getting the expected st_mode of 120000 for symlinks to directories.
> 
>> If you want the VMS behind-the-scenes approach (and what the CRTL
>> uses at the bottom), open a channel, use a $QIO to get the IO$_ACCESS
>> file characteristics longword (you'll need a FIB and an attribute
>> list asking  for ATR$C_RECATTR) and look at
>>
>>        8   67497                                 /*
>>        8   67498                                 **  Check for a 
>> symbolic link file
>>        8   67499                                 */
>>        8   67500                                 if ( 
>> (recattr.fat$v_fileorg == FAT$C_SPECIAL) &&
>>        8   67501                                      
>> (recattr.fat$b_special_type == FAT$C_SYMBOLIC_LINK) )
>>
> 
> I already have a $search() FAB/NAML structures, so I was hoping that I 
> could just get the information there.

If you already have a fab from a $search, do a $open, the 
characteristics will be filled in.  If that is all you need, you can try 
doing a minimalist open by setting the fab$v_ufo and fab$v_upi flags and 
see if the necessary characteristics are still filled in.

If you need to know what filename the symlink points to, connect a RAB 
and do a $read.  Here is a snippet of code I have been using with great 
success as a replacement for CRTL readlink call:

int rms_readlink(char *link, char *target, size_t target_len)
{
.
.
.
     fab.fab$v_bio = 1;                         //block I/O
     fab.fab$v_get = 1;                         //perform a GET
     naml.naml$v_open_special = 1;              //do not follow symlinks
     naml.naml$v_no_short_upcase = 1;           //maintain ODS-5 case
     status = SYS$OPEN(&fab);                   //open the file
     if (!$VMS_STATUS_SUCCESS(status)) {
         decc$$translate(status);
         return -1;
     }
     if ((fab.fab$b_org != FAB$C_SPECIAL) || (fab.fab$b_rat != 
FAB$C_SYMBOLIC_LINK)) {
         SYS$CLOSE(&fab);                      //not a symlink
         errno = EINVAL;
         return -1;
     }
     rab.rab$l_fab = &fab;
     rab.rab$w_usz = target_len;
     rab.rab$l_ubf = target;
     status = SYS$CONNECT(&rab);
     if ($VMS_STATUS_SUCCESS(status)) status = SYS$READ(&rab);
     SYS$CLOSE(&fab);
     if (!$VMS_STATUS_SUCCESS(status)) {
         decc$$translate(status);
         return -1;
     }
     target[rab.rab$w_rsz] = 0;
     return rab.rab$w_rsz;
}



More information about the Info-vax mailing list